From a2fd97920a46cd3ab350711e597f1ef5723e155e Mon Sep 17 00:00:00 2001 From: Jukezter Date: Thu, 19 Aug 2021 10:59:53 +0800 Subject: [PATCH] added Jun Yu's homework --- HW1/HW01_ChuaJunYu.py | 148 ++++++++++++++++ HW3/HW03_ChuaJunYu.py | 145 +++++++++++++++ HW4/HW04_ChuaJunYu.py | 190 ++++++++++++++++++++ HW5/HW05_ChuaJunYu.py | 399 ++++++++++++++++++++++++++++++++++++++++++ HW6/HW06_ChuaJunYu.py | 51 ++++++ 5 files changed, 933 insertions(+) create mode 100644 HW1/HW01_ChuaJunYu.py create mode 100644 HW3/HW03_ChuaJunYu.py create mode 100644 HW4/HW04_ChuaJunYu.py create mode 100644 HW5/HW05_ChuaJunYu.py create mode 100644 HW6/HW06_ChuaJunYu.py diff --git a/HW1/HW01_ChuaJunYu.py b/HW1/HW01_ChuaJunYu.py new file mode 100644 index 0000000..6b56138 --- /dev/null +++ b/HW1/HW01_ChuaJunYu.py @@ -0,0 +1,148 @@ +""" Homework 1: Control """ + +# Q1 +from operator import add, 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 = lambda a, b: a - b + else: + f = lambda a, b: a + b + 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 (sorted([a, b, c])[1] ** 2 + sorted([a, b, c])[2] ** 2) + + +# Q3 +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 + """ + factors = [] + for i in range(1, n): + if (n % i) == 0: + factors.append(i) + + return factors[-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(): + global x + x = "2" + return False + + +def t(): + global x + x = """1 +2""" + + +def f(): + global x + print(x) + + +# 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 + """ + + print(n) + if n == 1: + return 1 + elif (n % 2) == 0: + return hailstone(int(n/2)) + 1 + else: + return hailstone(int(3 * n + 1)) + 1 + + +# Q6 +quine = """ +"*** YOUR CODE HERE ***" +""" \ No newline at end of file diff --git a/HW3/HW03_ChuaJunYu.py b/HW3/HW03_ChuaJunYu.py new file mode 100644 index 0000000..9325593 --- /dev/null +++ b/HW3/HW03_ChuaJunYu.py @@ -0,0 +1,145 @@ +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 + """ + if k % 10 == 7: + return True + elif k == 0: + return False + else: + return has_seven(k // 10) + + +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 direction(n): + if n < 7: + return 1 + # if previous n is multiple of 7 or has seven, change direction + elif has_seven(n - 1) or ((n-1) % 7) == 0: + return direction(n-1) * -1 + # Else return same direction as previous n + else: + return direction(n-1) + + if n < 7: + return n + else: + return pingpong(n-1) + direction(n) + + +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_ChuaJunYu.py b/HW4/HW04_ChuaJunYu.py new file mode 100644 index 0000000..5c0c9f2 --- /dev/null +++ b/HW4/HW04_ChuaJunYu.py @@ -0,0 +1,190 @@ +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 + """ + street_distance = abs(street(a) - street(b)) + avenue_distance = abs(avenue(a) - avenue(b)) + return street_distance + avenue_distance + +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 + else: + 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 + """ + + i = 1 + curr, next1, next2 = 1, 2, 3 + while i < n: + curr, next1, next2, = next1, next2, (3*curr + 2*next1 + next2) + i += 1 + return curr + + +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 + """ + + def find_pow_two(z): + i = 1 + while i < z: + i *= 2 + return i + + def convert_pow_two(x): + return find_pow_two(x) // 2 + + def is_pow_two(y): + if find_pow_two(y) == y: + return True + else: + return False + + def helper(n, m): + if n == 0: + return 1 + elif n < 0: + return 0 + elif m == 1: + return 1 + + if not is_pow_two(m): + m = convert_pow_two(m) + + return helper(n-m, m) + helper(n, m/2) + + return helper(amount, amount) + + +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_ChuaJunYu.py b/HW5/HW05_ChuaJunYu.py new file mode 100644 index 0000000..bb1fae4 --- /dev/null +++ b/HW5/HW05_ChuaJunYu.py @@ -0,0 +1,399 @@ +######### +# Trees # +######### + +def tree(label, branches=[]): + """Construct a tree with the given label value and a list of branches.""" + for branch in branches: + assert is_tree(branch), 'branches must be trees' + return [label] + list(branches) + +def label(tree): + """Return the label value of a tree.""" + return tree[0] + +def branches(tree): + """Return the list of branches of the given tree.""" + return tree[1:] + +def is_tree(tree): + """Returns True if the given tree is a tree, and False otherwise.""" + if type(tree) != list or len(tree) < 1: + return False + for branch in branches(tree): + if not is_tree(branch): + return False + return True + +def is_leaf(tree): + """Returns True if the given tree's list of branches is empty, and False + otherwise. + """ + return not branches(tree) + +def print_tree(t, indent=0): + """Print a representation of this tree in which each node is + indented by two spaces times its depth from the root. + + >>> print_tree(tree(1)) + 1 + >>> print_tree(tree(1, [tree(2)])) + 1 + 2 + >>> numbers = tree(1, [tree(2), tree(3, [tree(4), tree(5)]), tree(6, [tree(7)])]) + >>> print_tree(numbers) + 1 + 2 + 3 + 4 + 5 + 6 + 7 + """ + print(' ' * indent + str(label(t))) + for b in branches(t): + print_tree(b, indent + 1) + +def copy_tree(t): + """Returns a copy of t. Only for testing purposes. + + >>> t = tree(5) + >>> copy = copy_tree(t) + >>> t = tree(6) + >>> print_tree(copy) + 5 + """ + return tree(label(t), [copy_tree(b) for b in branches(t)]) + +###################### +# Required questions # +###################### + +def replace_leaf(t, old, new): + """Returns a new tree where every leaf value equal to old has + been replaced with new. + + >>> yggdrasil = tree('odin', + ... [tree('balder', + ... [tree('thor'), + ... tree('loki')]), + ... tree('frigg', + ... [tree('thor')]), + ... tree('thor', + ... [tree('sif'), + ... tree('thor')]), + ... tree('thor')]) + >>> laerad = copy_tree(yggdrasil) # copy yggdrasil for testing purposes + >>> print_tree(replace_leaf(yggdrasil, 'thor', 'freya')) + odin + balder + freya + loki + frigg + freya + thor + sif + freya + freya + >>> laerad == yggdrasil # Make sure original tree is unmodified + True + """ + "*** YOUR CODE HERE ***" + +# Mobiles + +def mobile(left, right): + """Construct a mobile from a left side and a right side.""" + assert is_side(left), "left must be a side" + assert is_side(right), "right must be a side" + return ['mobile', left, right] + +def is_mobile(m): + """Return whether m is a mobile.""" + return type(m) == list and len(m) == 3 and m[0] == 'mobile' + +def left(m): + """Select the left side of a mobile.""" + assert is_mobile(m), "must call left on a mobile" + return m[1] + +def right(m): + """Select the right side of a mobile.""" + assert is_mobile(m), "must call right on a mobile" + return m[2] + +def side(length, mobile_or_weight): + """Construct a side: a length of rod with a mobile or weight at the end.""" + assert is_mobile(mobile_or_weight) or is_weight(mobile_or_weight) + return ['side', length, mobile_or_weight] + +def is_side(s): + """Return whether s is a side.""" + return type(s) == list and len(s) == 3 and s[0] == 'side' + +def length(s): + """Select the length of a side.""" + assert is_side(s), "must call length on a side" + return s[1] + +def end(s): + """Select the mobile or weight hanging at the end of a side.""" + assert is_side(s), "must call end on a side" + return s[2] + +def weight(size): + """Construct a weight of some size.""" + assert size > 0 + "*** YOUR CODE HERE ***" + +def size(w): + """Select the size of a weight.""" + assert is_weight(w), 'must call size on a weight' + "*** YOUR CODE HERE ***" + +def is_weight(w): + """Whether w is a weight.""" + return type(w) == list and len(w) == 2 and w[0] == 'weight' + +def examples(): + t = mobile(side(1, weight(2)), + side(2, weight(1))) + u = mobile(side(5, weight(1)), + side(1, mobile(side(2, weight(3)), + side(3, weight(2))))) + v = mobile(side(4, t), side(2, u)) + return (t, u, v) + +def total_weight(m): + """Return the total weight of m, a weight or mobile. + + >>> t, u, v = examples() + >>> total_weight(t) + 3 + >>> total_weight(u) + 6 + >>> total_weight(v) + 9 + """ + if is_weight(m): + return size(m) + else: + assert is_mobile(m), "must get total weight of a mobile or a weight" + return total_weight(end(left(m))) + total_weight(end(right(m))) + +def balanced(m): + """Return whether m is balanced. + + >>> t, u, v = examples() + >>> balanced(t) + True + >>> balanced(v) + True + >>> w = mobile(side(3, t), side(2, u)) + >>> balanced(w) + False + >>> balanced(mobile(side(1, v), side(1, w))) + False + >>> balanced(mobile(side(1, w), side(1, v))) + False + """ + "*** YOUR CODE HERE ***" + +def totals_tree(m): + """Return a tree representing the mobile with its total weight at the root. + + >>> t, u, v = examples() + >>> print_tree(totals_tree(t)) + 3 + 2 + 1 + >>> print_tree(totals_tree(u)) + 6 + 1 + 5 + 3 + 2 + >>> print_tree(totals_tree(v)) + 9 + 3 + 2 + 1 + 6 + 1 + 5 + 3 + 2 + """ + "*** YOUR CODE HERE ***" + +# Mutable functions in Python + +def make_counter(): + count = {} + def counter(string): + if string in count: + count[string] += 1 + else: + count[string] = 1 + return count[string] + return counter + + +def make_fib(): + data = [1, 0] + def fib(): + data[0], data[1] = data[1], (data[0] + data[1]) + return data[0] + return fib + + + +def make_withdraw(balance, password): + attempts = [] + def withdraw(amount, passwd): + nonlocal balance, password + if len(attempts) == 3: + return f"Your account is locked. Attempts: {attempts}" + elif passwd != password: + attempts.append(passwd) + return 'Incorrect password' + elif amount > balance: + return 'Insufficient funds' + else: + balance = balance - amount + return balance + return withdraw + + +def make_joint(withdraw, old_password, new_password): + check_for_error = withdraw(0, old_password) + if type(check_for_error) == str: + return check_for_error + def joint(amount, password): + if password == new_password: + return withdraw(amount, old_password) + return withdraw(amount, password) + 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_ChuaJunYu.py b/HW6/HW06_ChuaJunYu.py new file mode 100644 index 0000000..faaf366 --- /dev/null +++ b/HW6/HW06_ChuaJunYu.py @@ -0,0 +1,51 @@ +# Object Oriented Programming + +class Fib(): + + def __init__(self, value=0): + self.value = value + + def next(self): + if self.value == 0: + result = Fib(1) + else: + result = Fib(self.value + self.prev) + result.prev = self.value + return result + + def __repr__(self): + return str(self.value) + + +class VendingMachine: + + def __init__(self, item, price): + self.item = item + self.price = price + self.balance = 0 + self.stock = 0 + + def vend(self): + if self.stock == 0: + return 'Machine is out of stock.' + if self.balance < self.price: + difference = self.price - self.balance + return f"You must deposit ${difference} more." + if self.balance > self.price: + change = self.balance - self.price + self.balance = 0 + self.stock -= 1 + return f"Here is your {self.item} and ${change} change." + self.balance = 0 + self.stock -= 1 + return f"Here is your {self.item}." + + def deposit(self, amount): + if self.stock == 0: + return f"Machine is out of stock. Here is your ${amount}." + self.balance += amount + return f"Current balance: ${self.balance}" + + def restock(self, new_stock): + self.stock += new_stock + return f"Current {self.item} stock: {self.stock}" \ No newline at end of file