ATM Machine
February 26, 2019
Since I’ve been writing Awk all day at work, I’ll write this solution in Awk. We keep a file bank that has userid, password and balance in three space-separated fields:
$ cat bank phil correcthorse 1000 sue horsebattery 1000 john batterystaple 500
Here’s the program:
$ cat atm
BEGIN {
while (getline < "bank") {
password[$1] = $2
balance[$1] = $3 }
userid = getuserid()
printf "Your balance is %.2f\n", balance[userid]
while ((cmd = getcommand()) != "Q") {
if (cmd == "D") {
balance[userid] += getamount()
} else if (cmd == "W") {
amt = getamount()
if (amt <= balance[userid]) {
balance[userid] -= amt
} else { print "Can't overdraw account" }
} else { print "Unrecognized command" }
printf "Your balance is %.2f\n", balance[userid] }
print "Thank you for your custom."
for (userid in password) {
if (userid !~ /^ *$/)
print userid, password[userid], balance[userid] > "bank" } }
function getuserid( userid, passwd) {
userid = ""; passwd = "hello"
while (passwd != password[userid]) {
printf "%s ", "Enter userid:"; getline userid
printf "%s ", "Enter password:"; getline passwd }
return userid }
function getcommand( cmd) {
cmd = "X"
while (cmd !~ /[dDwWqQ]/) {
printf "Enter command: D)eposit, W)ithdrawl or Q)uit: "
getline cmd }
return toupper(cmd) }
function getamount( amt) {
amt = "X"
while (amt !~ /[1-9][0-9]*\.?[0-9]*/) {
printf "Enter amount: "; getline amt }
return amt }</pre>
And here it is in action:
$ awk -f atm Enter userid: phil Enter password: correcthorse Your balance is 1000.00 Enter command: D)eposit, W)ithdrawl or Q)uit: d Enter amount: 500 Your balance is 1500.00 Enter command: D)eposit, W)ithdrawl or Q)uit: w Enter amount: 300 Your balance is 1200.00 Enter command: D)eposit, W)ithdrawl or Q)uit: w Enter amount: 2000 Can't overdraw account Your balance is 1200.00 Enter command: D)eposit, W)ithdrawl or Q)uit: q Thank you for your custom.
There is nothing tricky here, just straight forward coding on a simple algorithm. You can run the program at https://ideone.com/szzB46.
Your suggested solution has a large chunk missing (comparing with the ideone version, looks like a section in angle brackets has disappeared).
@matthew: Thanks. I think it’s fixed now. On the other hand, last night when I edited the exercise it looked right, too. WordPress has been playing with their editor lately, improving it. Things may change tomorrow.
Here’s a solution in Python.
database = { 'user1': ['password1', 20], 'user2': ['password2', 100], 'user3': ['password3', 0], } while True: user = input('user> ') password = input('password> ') entry = database.get(user) if entry is None or entry[0] != password: print('login error') continue menu = ( '[q] quit\n' '[d] deposit\n' '[w] withdraw' ) while True: balance = entry[1] print('balance: {}'.format(balance)) print(menu) option = input('choice> ') if option == 'q': break elif option == 'd': amount = int(input('amount> ')) entry[1] += amount elif option == 'w': amount = int(input('amount> ')) if amount > balance: print('insufficient funds') else: entry[1] -= amountExample:
Scheme version for completeness:
(import (chicken io) simple-md5 srfi-69) (define account-db (make-hash-table)) (define (prompt-for-line prompt) (print* prompt) (read-line)) (define (get-value prompt) (let ((v (string->number (prompt-for-line prompt)))) (if (and v (>= v 0)) v (begin (print "Invalid amount.") (get-value prompt))))) (define (make-account-dispatcher value) (define (dispatch) (print "\nYou currently have " value " CHF.\n\n" "Options:\n" "- [D]eposit funds\n" "- [W]ithdraw funds\n" "- e[X]it") (case (string->symbol (prompt-for-line "> ")) ((D d) (let ((v (get-value "Amount to deposit: "))) (set! value (+ value v)) (dispatch))) ((W w) (let ((v (get-value "Amount to withdraw: "))) (if (> v value) (print "Insufficient funds!") (set! value (- value v))) (dispatch))) ((X x) (print "Don't forget your card.")) (else (print "Invalid option.") (dispatch)))) dispatch) (define (make-login username password) (cons username (string->md5sum (string-append username password)))) (define (get-login) (make-login (prompt-for-line "Username --> ") (prompt-for-line "Password --> "))) (define (add-account login funds) (hash-table-set! account-db login (make-account-dispatcher funds))) (define (open-account) (print "Assign name and password for new account:") (add-account (get-login) 0) (print "Account created. You may now log in.")) (define (atm) (print "\nWelcome to E-Corp ATM\n" "=====================\n") (let ((login (get-login))) (if (hash-table-exists? account-db login) ((hash-table-ref account-db login)) (print "** Error: Invalid account.")) (atm))) (add-account (make-login "user1" "pass1") 10) (add-account (make-login "user2" "pass2") 20) (add-account (make-login "user3" "pass3") 30) (atm)Example output: