Q.
Suppose that our banking system requires the ability to make joint accounts. Define a function
make_joint
that takes three arguments.
A password-protected
withdraw
function,The password with which that
withdraw
function was defined, andA new password that can also access the original account.
The
make_joint
function returns awithdraw
function that provides additional access to the original account using either the new or old password. Both functions draw down the same balance. Incorrect passwords provided to either function will be stored and cause the functions to be locked after three wrong attempts.Hint: The solution is short (less than 10 lines) and contains no string literals! The key is to call
withdraw
with the right password and interpret the result. You may assume that all failed attempts towithdraw
will return some string (for incorrect passwords, locked accounts, or insufficient funds), while successful withdrawals will return a number.Use
type(value) == str
to test if some value is a string:
Solution
def make_withdraw(balance, password):
"""Return a password-protected withdraw function.
>>> w = make_withdraw(100, 'hax0r')
>>> w(25, 'hax0r')
75
>>> w(90, 'hax0r')
'Insufficient funds'
>>> w(25, 'hwat')
'Incorrect password'
>>> w(25, 'hax0r')
50
>>> w(75, 'a')
'Incorrect password'
>>> w(10, 'hax0r')
40
>>> w(20, 'n00b')
'Incorrect password'
>>> w(10, 'hax0r')
"Your account is locked. Attempts: ['hwat', 'a', 'n00b']"
>>> w(10, 'l33t')
"Your account is locked. Attempts: ['hwat', 'a', 'n00b']"
"""
incorrect_password_list = []
count = 0
def withdraw(amount, input_passwd):
nonlocal count
if count < 3:
if input_passwd == password:
nonlocal balance
if amount < balance:
balance -= amount
return balance
else:
return "Insufficient funds"
else:
nonlocal incorrect_password_list
incorrect_password_list.append(input_passwd)
count += 1
return "Incorrect password"
else:
return "Your account is locked. Attempts: ['{0}', '{1}', '{2}']".format(incorrect_password_list[0], incorrect_password_list[1], incorrect_password_list[2])
return withdraw
def make_joint(withdraw, old_passwd, new_passwd):
"""
>>> w = make_withdraw(100, 'hax0r')
>>> w(25, 'hax0r')
75
>>> make_joint(w, 'my', 'secret')
'Incorrect password'
>>> j = make_joint(w, 'hax0r', 'secret')
>>> w(25, 'secret')
'Incorrect password'
>>> j(25, 'secret')
50
>>> j(25, 'hax0r')
25
>>> j(100, 'secret')
'Insufficient funds'
"""
value = withdraw(0, old_passwd)
if type(value) == str:
return "Incorrect password"
else:
def joint_withdraw(balance, input_passwd):
if (input_passwd == old_passwd) or (input_passwd == new_passwd):
return withdraw(balance, old_passwd)
return joint_withdraw
My question:
Apart from test cases mentioned in docstring of above solution make_joint
, below additional test cases are yet to pass, Please provide an hint to modify make_joint
to satisfy these given additional test cases(below).
>>> j2 = make_joint(j, 'secret', 'code')
>>> j2(5, 'code')
20
>>> j2(5, 'secret')
15
>>> j2(5, 'hax0r')
10
>>> j2(25, 'password')
'Incorrect password'
>>> j2(5, 'secret')
"Your account is locked. Attempts: ['my', 'secret', 'password']"
Let's just focus on these lines:
What happens when the
input_passwd
is neither theold_passwd
nor thenew_passwd
? Your function gives does nothing, and gives no response.Note that you already have code to respond to incorrect passwords. How can you define
joint_withdraw
to reuse that functionality?Fix that problem in the way that I hinted, and you should be able to get
j2(5, 'hax0r')
to work.