From 22c60ccad11b3d5f3af8da452ce6f631d74031f4 Mon Sep 17 00:00:00 2001 From: Lucas Loh <89173757+aekyr@users.noreply.github.com> Date: Thu, 19 Aug 2021 10:59:08 +0800 Subject: [PATCH] test --- HW1/hw01_LohZhengLucas.py | 151 ++++++++++++++++++ HW3/hw03_LohZhengLucas.py | 141 +++++++++++++++++ HW4/hw04_lohzhenglucas.py | 227 +++++++++++++++++++++++++++ HW5/hw05_LohZhengLucas.py | 323 ++++++++++++++++++++++++++++++++++++++ HW6/hw06_LohZhengLucas.py | 117 ++++++++++++++ 5 files changed, 959 insertions(+) create mode 100644 HW1/hw01_LohZhengLucas.py create mode 100644 HW3/hw03_LohZhengLucas.py create mode 100644 HW4/hw04_lohzhenglucas.py create mode 100644 HW5/hw05_LohZhengLucas.py create mode 100644 HW6/hw06_LohZhengLucas.py diff --git a/HW1/hw01_LohZhengLucas.py b/HW1/hw01_LohZhengLucas.py new file mode 100644 index 0000000..d982a0d --- /dev/null +++ b/HW1/hw01_LohZhengLucas.py @@ -0,0 +1,151 @@ +""" Homework 1: Control """ + +# Q1 +from operator import add, index, sub + + +def a_plus_abs_b(a, b): + """Return a+abs(b), but without calling abs. + + >>> a_plus_abs_b(2, 3) + 5 + >>> a_plus_abs_b(2, -3) + 5 + """ + if b < 0: + f = sub + else: + f = add + return f(a,b) + + +# Q2 +def two_of_three(a, b, c): + """Return x*x + y*y, where x and y are the two largest members of the + positive numbers a, b, and c. + + >>> two_of_three(1, 2, 3) + 13 + >>> two_of_three(5, 3, 1) + 34 + >>> two_of_three(10, 2, 8) + 164 + >>> two_of_three(5, 5, 5) + 50 + """ + return max(a*a+b*b, b*b+c*c, a*a+c*c) + + +# Q3 +# range() +# Q3 +# range() +def largest_factor(n): + """Return the largest factor of n that is smaller than n. + + >>> largest_factor(15) # factors are 1, 3, 5 + 5 + >>> largest_factor(80) # factors are 1, 2, 4, 5, 8, 10, 16, 20, 40 + 40 + >>> largest_factor(13) # factor is 1 since 13 is prime + 1 + """ + confirmed_divider = [] + #check all numbers from 1-80 except 80 + for possible_divider in range(1,n): + remainder = n%possible_divider + if remainder == 0: + confirmed_divider.append(possible_divider) + return confirmed_divider[-1] + + +# Q4 +def if_function(condition, true_result, false_result): + """Return true_result if condition is a true value, and + false_result otherwise. + + >>> if_function(True, 2, 3) + 2 + >>> if_function(False, 2, 3) + 3 + >>> if_function(3==2, 3+2, 3-2) + 1 + >>> if_function(3>2, 3+2, 3-2) + 5 + """ + if condition: + return true_result + else: + return false_result + + +def with_if_statement(): + """ + >>> result = with_if_statement() + 2 + >>> print(result) + None + """ + if c(): + return t() + else: + return f() + + +def with_if_function(): + """ + >>> result = with_if_function() + 1 + 2 + >>> print(result) + None + """ + return if_function(c(), t(), f()) + +def c(): + return True + +def t(): + print(1) + +def f(): + print(2) + + +# Q5 +def hailstone(n): + """Print the hailstone sequence starting at n and return its + length. + + >>> a = hailstone(10) + 10 + 5 + 16 + 8 + 4 + 2 + 1 + >>> a + 7 + """ + "*** YOUR CODE HERE ***" + # + a = 1 + + while n != 1: + remainder = n%2 + if remainder == 0: + n /= 2 + else: + n = n * 3 + 1 + #int(n) to remove dp since n always integer + print(int(n)) + a += 1 + + return a + + +# Q6 +quine = """ +"*** YOUR CODE HERE ***" +""" \ No newline at end of file diff --git a/HW3/hw03_LohZhengLucas.py b/HW3/hw03_LohZhengLucas.py new file mode 100644 index 0000000..95f0ada --- /dev/null +++ b/HW3/hw03_LohZhengLucas.py @@ -0,0 +1,141 @@ +HW_SOURCE_FILE = 'hw03.py' + +############# +# Questions # +############# + +from operator import add, mul, sub + +square = lambda x: x * x + +identity = lambda x: x + +triple = lambda x: 3 * x + +increment = lambda x: x + 1 + +def has_seven(k): + """Returns True if at least one of the digits of k is a 7, False otherwise. + + >>> has_seven(3) + False + >>> has_seven(7) + True + >>> has_seven(2734) + True + >>> has_seven(2634) + False + >>> has_seven(734) + True + >>> has_seven(7777) + True + >>> from construct_check import check + >>> check(HW_SOURCE_FILE, 'has_seven', + ... ['Assign', 'AugAssign']) + True + """ + for char in str(k): + if char == '7': + return True + return False + +def pingpong(n): + """Return the nth element of the ping-pong sequence. + + >>> pingpong(7) + 7 + >>> pingpong(8) + 6 + >>> pingpong(15) + 1 + >>> pingpong(21) + -1 + >>> pingpong(22) + 0 + >>> pingpong(30) + 6 + >>> pingpong(68) + 2 + >>> pingpong(69) + 1 + >>> pingpong(70) + 0 + >>> pingpong(71) + 1 + >>> pingpong(72) + 0 + >>> pingpong(100) + 2 + >>> from construct_check import check + >>> check(HW_SOURCE_FILE, 'pingpong', ['Assign', 'AugAssign']) + True + """ +def pingpong(n): + if n <= 7: + return n + else: + return pingpong(n-1) + direction(n-1) + +def direction(n): + if n < 7: + return 1 + else: + if n%7 == 0 or has_seven(n): + return -direction(n-1) + else: + return direction(n-1) + +def accumulate(combiner, base, n, term): + """Return the result of combining the first n terms in a sequence and base. + The terms to be combined are term(1), term(2), ..., term(n). combiner is a + two-argument, associative function. + + >>> accumulate(add, 0, 5, identity) # 0 + 1 + 2 + 3 + 4 + 5 + 15 + >>> accumulate(add, 11, 5, identity) # 11 + 1 + 2 + 3 + 4 + 5 + 26 + >>> accumulate(add, 11, 0, identity) # 11 + 11 + >>> accumulate(add, 11, 3, square) # 11 + 1^2 + 2^2 + 3^2 + 25 + >>> accumulate(mul, 2, 3, square) # 2 * 1^2 * 2^2 * 3^2 + 72 + """ + total, k = base, 1 + while k <= n: + total, k = combiner(total, term(k)), k + 1 + return total + +def filtered_accumulate(combiner, base, pred, n, term): + """Return the result of combining the terms in a sequence of N terms + that satisfy the predicate pred. combiner is a two-argument function. + If v1, v2, ..., vk are the values in term(1), term(2), ..., term(N) + that satisfy pred, then the result is + base combiner v1 combiner v2 ... combiner vk + (treating combiner as if it were a binary operator, like +). The + implementation uses accumulate. + + >>> filtered_accumulate(add, 0, lambda x: True, 5, identity) # 0 + 1 + 2 + 3 + 4 + 5 + 15 + >>> filtered_accumulate(add, 11, lambda x: False, 5, identity) # 11 + 11 + >>> filtered_accumulate(add, 0, odd, 5, identity) # 0 + 1 + 3 + 5 + 9 + >>> filtered_accumulate(mul, 1, greater_than_5, 5, square) # 1 * 9 * 16 * 25 + 3600 + >>> # Do not use while/for loops or recursion + >>> from construct_check import check + >>> check(HW_SOURCE_FILE, 'filtered_accumulate', + ... ['While', 'For', 'Recursion']) + True + """ + def combine_if(x, y): + "*** YOUR CODE HERE ***" + return accumulate(combine_if, base, n, term) + +def odd(x): + return x % 2 == 1 + +def greater_than_5(x): + return x > 5 + diff --git a/HW4/hw04_lohzhenglucas.py b/HW4/hw04_lohzhenglucas.py new file mode 100644 index 0000000..ce24875 --- /dev/null +++ b/HW4/hw04_lohzhenglucas.py @@ -0,0 +1,227 @@ +HW_SOURCE_FILE = 'hw04.py' + +############### +# Questions # +############### + +def intersection(st, ave): + """Represent an intersection using the Cantor pairing function.""" + return (st+ave)*(st+ave+1)//2 + ave + +def street(inter): + return w(inter) - avenue(inter) + +def avenue(inter): + return inter - (w(inter) ** 2 + w(inter)) // 2 + +w = lambda z: int(((8*z+1)**0.5-1)/2) + +def taxicab(a, b): + """Return the taxicab distance between two intersections. + + >>> times_square = intersection(46, 7) + >>> ess_a_bagel = intersection(51, 3) + >>> taxicab(times_square, ess_a_bagel) + 9 + >>> taxicab(ess_a_bagel, times_square) + 9 + """ + #from var outwards: + #street obtains street value from a and b, then place into list via [] + #sorted sorts a and b in ascending order + #item 1 is subtracted from item 0 in list (higher-lower) via - + #repeat for avenue then add via + + return (sorted([street(a), street(b)])[1]) - (sorted([street(a), street(b)])[0]) + (sorted([avenue(a), avenue(b)])[1]) - (sorted([avenue(a), avenue(b)])[0]) + + +def squares(s): + """Returns a new list containing square roots of the elements of the + original list that are perfect squares. + + >>> seq = [8, 49, 8, 9, 2, 1, 100, 102] + >>> squares(seq) + [7, 3, 1, 10] + >>> seq = [500, 30] + >>> squares(seq) + [] + """ + "*** YOUR CODE HERE ***" + +def g(n): + """Return the value of G(n), computed recursively. + + >>> g(1) + 1 + >>> g(2) + 2 + >>> g(3) + 3 + >>> g(4) + 10 + >>> g(5) + 22 + >>> from construct_check import check + >>> check(HW_SOURCE_FILE, 'g', ['While', 'For']) + True + """ + + if n <= 3: + return n + if n > 3: + return g(n-1) + 2 * g(n-2) + 3 * g(n-3) + +def g_iter(n): + """Return the value of G(n), computed iteratively. + + >>> g_iter(1) + 1 + >>> g_iter(2) + 2 + >>> g_iter(3) + 3 + >>> g_iter(4) + 10 + >>> g_iter(5) + 22 + >>> from construct_check import check + >>> check(HW_SOURCE_FILE, 'g_iter', ['Recursion']) + True + """ + if n <= 3: + return n + else: + #gn values used to store g(n-1), g(n-2) and g(n-3) respectively + #they are set to g(1), (2) and (3) intially + gn1 , gn2 , gn3 = 3 , 2 , 1 + #k is the current index of n + k = 4 + while k <= n: + if sorted([gn1,gn2,gn3])[2] == gn1: + gn3 = gn1 + 2*gn2 + 3*gn3 + elif sorted([gn1,gn2,gn3])[2] == gn3: + gn2 = gn3 + 2*gn1 + 3*gn2 + elif sorted([gn1,gn2,gn3])[2] == gn2: + gn1 = gn2 + 2*gn3 + 3*gn1 + k = k+1 + #result must be the highest of gn values since derived by addition + return sorted([gn1,gn2,gn3])[-1] + +def coin_sizes_generator(amount): + #1.1: iterative solution to generate all possible coin sizes for finite amount + #1.2: declare and set intial values for vars + #1.3: k is the power (increases each iteration) + coin_size = 0 + k = -1 + coinsizels = [] + while amount > coin_size: + #since amount is finite, possible coin_sizes is finite too + k += 1 + coin_size = 2 ** k + if amount >= coin_size: + coinsizels.append(coin_size) + else: + return coinsizels + return coinsizels + +def count_change(amount): + """Return the number of ways to make change for amount. + + >>> count_change(7) + 6 + >>> count_change(10) + 14 + >>> count_change(20) + 60 + >>> count_change(100) + 9828 + >>> from construct_check import check + >>> check(HW_SOURCE_FILE, 'count_change', ['While', 'For']) + True + """ + #1: generate an list with all possible coin sizes (number_to_test) to test based on + #2: does not change from start to finish of entire tree recursion + csls = tuple(coin_sizes_generator(amount)) + #3: index of the first target testing number (+1 since using len) + number_to_test = len(csls) + #4: give recur csls (does not change), index of target testing number in csls, and amount (n) + return recur(amount, csls, number_to_test) + +def recur(n, csls, number_to_test): + #5: BASE CASES + if n == 0: + #when amount is 0, there is 1 way to partition: no parts + return 1 + elif n < 0: + #when amount is less than 0, n cannot be subtracted by the coin value + #hence return 0 since not a possibility + return 0 + elif number_to_test <= 0 and n >= 1: + #when the number_to_test is 0, index_to_test is -1 + #ie the list is empty + #no way to partition with no parts. + return 0 + #6: RECURSION TREE + index_to_test = number_to_test - 1 + left_branch = recur(n - csls[index_to_test], csls, number_to_test) + # for left branch, test the biggest coin by subtracting csls[index_to_test] + # csls remains unchanged to keep index constant no matter the recursions + # number_to_test remains same since need to test if csls[index_to_test] can be subtracted from n again + # eg 8: 8-4=4, then do 4-4=0 + right_branch = recur(n, csls, number_to_test-1) + #for right_branch, since the biggest coin has been tested on n, test the next biggest coin as the start of a new parent branch + #hence n remains same but the number_to_test - 1 to refer to next index + #when recurred, the number_to_test - 1 becomes index_to_test -1 due to line 50 + #csls remains unchanged as tuple. + return right_branch + left_branch + #result is sum of right and left branch + +def print_move(origin, destination): + """Print instructions to move a disk.""" + print("Move the top disk from rod", origin, "to rod", destination) + +def move_stack(n, start, end): + """Print the moves required to move n disks on the start pole to the end + pole without violating the rules of Towers of Hanoi. + + n -- number of disks + start -- a pole position, either 1, 2, or 3 + end -- a pole position, either 1, 2, or 3 + + There are exactly three poles, and start and end must be different. Assume + that the start pole has at least n disks of increasing size, and the end + pole is either empty or has a top disk larger than the top n start disks. + + >>> move_stack(1, 1, 3) + Move the top disk from rod 1 to rod 3 + >>> move_stack(2, 1, 3) + Move the top disk from rod 1 to rod 2 + Move the top disk from rod 1 to rod 3 + Move the top disk from rod 2 to rod 3 + >>> move_stack(3, 1, 3) + Move the top disk from rod 1 to rod 3 + Move the top disk from rod 1 to rod 2 + Move the top disk from rod 3 to rod 2 + Move the top disk from rod 1 to rod 3 + Move the top disk from rod 2 to rod 1 + Move the top disk from rod 2 to rod 3 + Move the top disk from rod 1 to rod 3 + """ + assert 1 <= start <= 3 and 1 <= end <= 3 and start != end, "Bad start/end" + "*** YOUR CODE HERE ***" + +################### +# Extra Questions # +################### + +from operator import sub, mul + +def make_anonymous_factorial(): + """Return the value of an expression that computes factorial. + + >>> make_anonymous_factorial()(5) + 120 + >>> from construct_check import check + >>> check(HW_SOURCE_FILE, 'make_anonymous_factorial', ['Assign', 'AugAssign', 'FunctionDef', 'Recursion']) + True + """ + return 'YOUR_EXPRESSION_HERE' diff --git a/HW5/hw05_LohZhengLucas.py b/HW5/hw05_LohZhengLucas.py new file mode 100644 index 0000000..52f43c4 --- /dev/null +++ b/HW5/hw05_LohZhengLucas.py @@ -0,0 +1,323 @@ +######### +# Trees # +######### + +# Mutable functions in Python + +def make_counter(): + """Return a counter function. + + >>> c = make_counter() + >>> c('a') + 1 + >>> c('a') + 2 + >>> c('b') + 1 + >>> c('a') + 3 + >>> c2 = make_counter() + >>> c2('b') + 1 + >>> c2('b') + 2 + >>> c('b') + c2('b') + 5 + """ + s = {} + def counter(input): + nonlocal s + if s.get(input, 0) == 0: + s.update({input:1}) + #use s[index] + else: + newcount = s.get(input)+1 + #s[input] + s[input] = newcount + return s.get(input) + return counter + +def make_fib(): + """Returns a function that returns the next Fibonacci number + every time it is called. + + >>> fib = make_fib() + >>> fib() + 0 + >>> fib() + 1 + >>> fib() + 1 + >>> fib() + 2 + >>> fib() + 3 + >>> fib2 = make_fib() + >>> fib() + sum([fib2() for _ in range(5)]) + 12 + """ + f = [0,1] + index = 0 + def fib(): + nonlocal f , index + if index == 0 or index == 1: + fnew = index + index += 1 + else: + print(f[index-1] + f[index-2]) + fnew = f[index-1] + f[index-2] + f.append(fnew) + index += 1 + return fnew + return fib + +def make_withdraw(balance, password): + """Return a password-protected withdraw function. + + >>> w = make_withdraw(100, 'hax0r') + >>> w(25, 'hax0r') + 75 + >>> error = w(90, 'hax0r') + >>> error + 'Insufficient funds' + >>> error = w(25, 'hwat') + >>> error + 'Incorrect password' + >>> new_bal = w(25, 'hax0r') + >>> new_bal + 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']" + >>> type(w(10, 'l33t')) == str + True + """ + tries = 0 + attempts = [] + def w(amount, password): + nonlocal tries, attempts, balance + #check tries: if 3 or more, lock account + if tries <3: + #check password: if not correct pswd, add tries and save attempt + if password != 'hax0r': + tries += 1 + attempts.append(password) + return 'Incorrect password' + else: + if amount > balance: + #check if amount is insufficient + return 'Insufficient funds' + else: + balance = balance - amount + return balance + else: + return f'Your account is locked. Attempts: {attempts}' + return w + + +def make_joint(withdraw_acc, old_password, new_password): + """Return a password-protected withdraw function that has joint access to + the balance of withdraw. + + >>> 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' + + >>> 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']" + >>> j(5, 'secret') + "Your account is locked. Attempts: ['my', 'secret', 'password']" + >>> w(5, 'hax0r') + "Your account is locked. Attempts: ['my', 'secret', 'password']" + >>> make_joint(w, 'hax0r', 'hello') + "Your account is locked. Attempts: ['my', 'secret', 'password']" + """ + response = withdraw_acc(0, old_password) + if type(response) == str: + return response + else: + #since new password cannot be used to access w(), store passwords in joint + withdraw_password = old_password + joint_password = [] + joint_password.append(old_password) + joint_password.append(new_password) + + def joint(amount, password): + #no need check tries since str return from w() will keep track + if j_password_checker(password) == True: + #if password is correct use original password to access w() + #since joint password cannot be used / stored on w(). + return withdraw_acc(amount, withdraw_password) + else: + #if password is wrong, send to w() to count and keep track + return withdraw_acc(0, password) + #return joint at end + + def j_password_checker(password): + #find number of joint_passwords recorded for the same account + indexes = len(joint_password) - 1 + #test each password individually - starting with index 0 + index = 0 + while index <= indexes: + if password == joint_password[index]: + return True + #if password is false, need to check next password + else: + #hence set next index to index+1 + index += 1 + #while loop breaks when index to check > no. of indexes in list + #ie all passwords have been checked, hence return False. + return False + + return joint + +# Generators + +def generate_paths(t, x): + """Yields all possible paths from the root of t to a node with the label x + as a list. + + >>> t1 = tree(1, [tree(2, [tree(3), tree(4, [tree(6)]), tree(5)]), tree(5)]) + >>> print_tree(t1) + 1 + 2 + 3 + 4 + 6 + 5 + 5 + >>> next(generate_paths(t1, 6)) + [1, 2, 4, 6] + >>> path_to_5 = generate_paths(t1, 5) + >>> sorted(list(path_to_5)) + [[1, 2, 5], [1, 5]] + + >>> t2 = tree(0, [tree(2, [t1])]) + >>> print_tree(t2) + 0 + 2 + 1 + 2 + 3 + 4 + 6 + 5 + 5 + >>> path_to_2 = generate_paths(t2, 2) + >>> sorted(list(path_to_2)) + [[0, 2], [0, 2, 1, 2]] + """ + "*** YOUR CODE HERE ***" + +################### +# Extra Questions # +################### + +def str_interval(x): + """Return a string representation of interval x.""" + return '{0} to {1}'.format(lower_bound(x), upper_bound(x)) + +def add_interval(x, y): + """Return an interval that contains the sum of any value in interval x and + any value in interval y.""" + lower = lower_bound(x) + lower_bound(y) + upper = upper_bound(x) + upper_bound(y) + return interval(lower, upper) + +def interval(a, b): + """Construct an interval from a to b.""" + return [a, b] + +def lower_bound(x): + """Return the lower bound of interval x.""" + "*** YOUR CODE HERE ***" + +def upper_bound(x): + """Return the upper bound of interval x.""" + "*** YOUR CODE HERE ***" + +def mul_interval(x, y): + """Return the interval that contains the product of any value in x and any + value in y.""" + p1 = x[0] * y[0] + p2 = x[0] * y[1] + p3 = x[1] * y[0] + p4 = x[1] * y[1] + return [min(p1, p2, p3, p4), max(p1, p2, p3, p4)] + +def sub_interval(x, y): + """Return the interval that contains the difference between any value in x + and any value in y.""" + "*** YOUR CODE HERE ***" + +def div_interval(x, y): + """Return the interval that contains the quotient of any value in x divided by + any value in y. Division is implemented as the multiplication of x by the + reciprocal of y.""" + "*** YOUR CODE HERE ***" + reciprocal_y = interval(1/upper_bound(y), 1/lower_bound(y)) + return mul_interval(x, reciprocal_y) + +def par1(r1, r2): + return div_interval(mul_interval(r1, r2), add_interval(r1, r2)) + +def par2(r1, r2): + one = interval(1, 1) + rep_r1 = div_interval(one, r1) + rep_r2 = div_interval(one, r2) + return div_interval(one, add_interval(rep_r1, rep_r2)) + +def check_par(): + """Return two intervals that give different results for parallel resistors. + + >>> r1, r2 = check_par() + >>> x = par1(r1, r2) + >>> y = par2(r1, r2) + >>> lower_bound(x) != lower_bound(y) or upper_bound(x) != upper_bound(y) + True + """ + r1 = interval(1, 1) # Replace this line! + r2 = interval(1, 1) # Replace this line! + return r1, r2 + +def multiple_references_explanation(): + return """The multiple reference problem...""" + +def quadratic(x, a, b, c): + """Return the interval that is the range of the quadratic defined by + coefficients a, b, and c, for domain interval x. + + >>> str_interval(quadratic(interval(0, 2), -2, 3, -1)) + '-3 to 0.125' + >>> str_interval(quadratic(interval(1, 3), 2, -3, 1)) + '0 to 10' + """ + "*** YOUR CODE HERE ***" diff --git a/HW6/hw06_LohZhengLucas.py b/HW6/hw06_LohZhengLucas.py new file mode 100644 index 0000000..f48480f --- /dev/null +++ b/HW6/hw06_LohZhengLucas.py @@ -0,0 +1,117 @@ +# Object Oriented Programming + +class Fib(): + """A Fibonacci number. + + >>> start = Fib() + >>> start + 0 + >>> start.next() + 1 + >>> start.next().next() + 1 + >>> start.next().next().next() + 2 + >>> start.next().next().next().next() + 3 + >>> start.next().next().next().next().next() + 5 + >>> start.next().next().next().next().next().next() + 8 + >>> start.next().next().next().next().next().next() # Ensure start isn't changed + 8 + + Implement the next method of the Fib class. For this class, the value attribute is a Fibonacci number. + The next method returns a Fib instance whose value is the next Fibonacci number. + The next method should take only constant time. + + Note that in the doctests, nothing is being printed out. + Rather, each call to .next() returns a Fib instance, which is represented in the interpreter + as the value of that instance (see the __repr__ method). + + Hint: Keep track of the previous number by setting a new instance attribute inside next. + """ + + def __init__(self, value=0): + self.value = value + #value=0 creates input for fib() but sets default to 0 + + def next(self): + "*** YOUR CODE HERE ***" + if self.value == 0: + result = Fib(1) + else: + result = Fib(self.value + self.previous) + result.previous = self.value + return result + + def __repr__(self): + return str(self.value) + +class VendingMachine: + """A vending machine that vends some product for some price. + + >>> v = VendingMachine('candy', 10) + >>> v.vend() + 'Machine is out of stock.' + >>> v.deposit(15) + 'Machine is out of stock. Here is your $15.' + >>> v.restock(2) + 'Current candy stock: 2' + >>> v.vend() + 'You must deposit $10 more.' + >>> v.deposit(7) + 'Current bal: $7' + >>> v.vend() + 'You must deposit $3 more.' + >>> v.deposit(5) + 'Current bal: $12' + >>> v.vend() + 'Here is your candy and $2 change.' + >>> v.deposit(10) + 'Current bal: $10' + >>> v.vend() + 'Here is your candy.' + >>> v.deposit(15) + 'Machine is out of stock. Here is your $15.' + + >>> w = VendingMachine('soda', 2) + >>> w.restock(3) + 'Current soda stock: 3' + >>> w.restock(3) + 'Current soda stock: 6' + >>> w.deposit(2) + 'Current bal: $2' + >>> w.vend() + 'Here is your soda.' + """ + + def __init__(self, item, price): + self.item = item + self.bal, self.stock = 0 , 0 + self.price = price + + def restock(self, n): + self.stock += n + return f'Current {self.item} stock: {self.stock}' + + def deposit(self, amount): + if self.stock > 0: + self.bal += amount + return f'Current bal: ${self.bal}' + else: + return f'Machine is out of stock. Here is your ${amount}.' + + def vend(self): + if self.stock > 0: + if self.bal >= self.price: + change = self.bal - self.price + self.stock -= 1 + self.bal = 0 + if change == 0: + return f'Here is your {self.item}.' + return f'Here is your {self.item} and ${change} change.' + elif self.bal < self.price: + return f'You must deposit ${self.price - self.bal} more.' + else: + return 'Machine is out of stock'