Fill in the blanks in the following function for adding a to the absolute value of b, without calling abs. You may not modify any of the provided code other than the two blanks.
1 2 3 4 5 6 7 8 9 10 11 12 13
defa_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 = _____ else: f = _____ return f(a, b)
Use Ok to test your code:
1
python3 ok -q a_plus_abs_b
my answer:
1 2 3 4 5 6 7 8 9 10 11 12 13
defa_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 = a-b else: f = a+b return f(a, b)
Q3: Two of Three
Write a function that takes three positive numbers as arguments and returns the sum of the squares of the two smallest numbers.Use only a single line for the body of the function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
deftwo_of_three(x, y, z): """Return a*a + b*b, where a and b are the two smallest members of the positive numbers x, y, and z. >>> two_of_three(1, 2, 3) 5 >>> two_of_three(5, 3, 1) 10 >>> two_of_three(10, 2, 8) 68 >>> two_of_three(5, 5, 5) 50 """ return _____
Hint: Consider using the max or min function:
1 2 3 4
>>> max(1,2,3) 3 >>> min(-1,-2,-3) -3
Use Ok to test your code:
1
python3 ok -q two_of_three
my answer:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
deftwo_of_three(x, y, z): """Return a*a + b*b, where a and b are the two smallest members of the positive numbers x, y, and z. >>> two_of_three(1, 2, 3) 5 >>> two_of_three(5, 3, 1) 10 >>> two_of_three(10, 2, 8) 68 >>> two_of_three(5, 5, 5) 50 """ return x*x+y*y+z*z-max(x,y,z)*max(x,y,z)
Q4: Largest Factor
Write a function that takes an integer n that is greater than 1 andreturns the largest integer that is smaller than n and evenly divides n.
1 2 3 4 5 6 7 8 9 10 11
deflargest_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 """ "*** YOUR CODE HERE ***"
Hint: To check if b evenly divides a, you can use the expression a % b == 0, which can be read as, “the remainder of dividing a by b is 0.”
Use Ok to test your code:
1 2
python3 ok -q largest_factor
my answer:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
deflargest_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 """ "*** YOUR CODE HERE ***" i=n-1 while n%i!=0: i=i-1 print(i)
Q6: Hailstone
Douglas Hofstadter’s Pulitzer-prize-winning book, Gödel, Escher, Bach, poses the following mathematical puzzle.
Pick a positive integer n as the start.
If n is even, divide it by 2.
If n is odd, multiply it by 3 and add 1.
Continue this process until n is 1.
The number n will travel up and down but eventually end at 1 (at least for all numbers that have ever been tried – nobody has ever proved that the sequence will terminate). Analogously, a hailstone travels up and down in the atmosphere before eventually landing on earth.
This sequence of values of n is often called a Hailstone sequence. Write a function that takes a single argument with formal parameter name n, prints out the hailstone sequence starting at n, and returns the number of steps in the sequence:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
defhailstone(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 ***"
Hailstone sequences can get quite long! Try 27. What’s the longest you can find?
Use Ok to test your code:
1
python3 ok -q hailstone
my answer:
1 2 3 4 5 6 7 8 9 10 11 12
#hw01 Q6:Hailstone defhailstone(n): i=1 while n!=1: print(int(n)) if n%2==0: n=n/2 else: n=n*3+1 i=i+1 print(1) #print(int(i))
Lab 01: Variables & Functions,Control
Q4: Falling Factorial
Let’s write a function falling, which is a “falling” factorial that takes two arguments, n and k, and returns the product of k consecutive numbers, starting from n and working downwards. When k is 0, the function should return 1.
1 2 3 4 5 6 7 8 9 10 11 12 13
deffalling(n, k): """Compute the falling factorial of n to depth k. >>> falling(6, 3) # 6 * 5 * 4 120 >>> falling(4, 3) # 4 * 3 * 2 24 >>> falling(4, 1) # 4 4 >>> falling(4, 0) 1 """ "*** YOUR CODE HERE ***"
deffalling(n, k): """Compute the falling factorial of n to depth k. >>> falling(6, 3) # 6 * 5 * 4 120 >>> falling(4, 3) # 4 * 3 * 2 24 >>> falling(4, 1) # 4 4 >>> falling(4, 0) 1 """ "*** YOUR CODE HERE ***" ''' if(k==0): temp=1 else: temp=n while(k!=1): k-=1 temp*=(n-1) n-=1 return temp ''' total,stop=1,n-k while n>stop: total,n=total*n,n-1 return total #感觉python有很多都和C++不同,而我的思维还在C++上面
Q5: Sum Digits
Write a function that takes in a nonnegative integer and sums its digits. (Using floor division and modulo might be helpful here!)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
defsum_digits(y): """Sum all the digits of y. >>> sum_digits(10) # 1 + 0 = 1 1 >>> sum_digits(4224) # 4 + 2 + 2 + 4 = 12 12 >>> sum_digits(1234567890) 45 >>> a = sum_digits(123) # make sure that you are using return rather than print >>> a 6 """ "*** YOUR CODE HERE ***"
Use Ok to test your code:
1
python3 ok -q sum_digits
my answer:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
defsum_digits(y): """Sum all the digits of y. >>> sum_digits(10) # 1 + 0 = 1 1 >>> sum_digits(4224) # 4 + 2 + 2 + 4 = 12 12 >>> sum_digits(1234567890) 45 >>> a = sum_digits(123) # make sure that you are using return rather than print >>> a 6 """ "*** YOUR CODE HERE ***" total=y%10 while(y!=0): y=y//10 total+=y%10 return total #这个过的挺轻松的
Q7: Double Eights
Write a function that takes in a number and determines if the digits contain two adjacent 8s.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
defdouble_eights(n): """Return true if n has two eights in a row. >>> double_eights(8) False >>> double_eights(88) True >>> double_eights(2882) True >>> double_eights(880088) True >>> double_eights(12345) False >>> double_eights(80808080) False """ "*** YOUR CODE HERE ***"
defdouble_eights(n): """Return true if n has two eights in a row. >>> double_eights(8) False >>> double_eights(88) True >>> double_eights(2882) True >>> double_eights(880088) True >>> double_eights(12345) False >>> double_eights(80808080) False """ "*** YOUR CODE HERE ***" while(n!=0): t=n%10 if(t==8): n//=10 _t=n%10 if(_t==8): returnTrue else: returnFalse else: n//=10 returnFalse#最后这里不要忘了还有个return,针对while循环走完的情况
Project1:The Game of Hog
Rules
Sow Sad: If any of the dice outcomes is a 1, the current player’s score for the turn is 1.
所有骰子中有一个数为1,则得1分
Picky Piggy: A player who chooses to roll zero dice scores the nth digit of the decimal expansion of 1/7 (0.14285714…), where n is the opponent’s score. As a special case, if n is 0, the player scores 7 points.
玩家选择不掷骰子,则对手分数为几,他的分数就为1/7的第几位数字
Hog Pile: After points for the turn are added to the current player’s score, if the players’ scores are the same, the current player’s score doubles.
如果当前玩家掷骰子后的分数与对手相同,则当前玩家分数翻倍
Phase1: Simulator
In the first phase, you will develop a simulator for the game of Hog.
defroll_dice(num_rolls, dice=six_sided): """Simulate rolling the DICE exactly NUM_ROLLS > 0 times. Return the sum of the outcomes unless any of the outcomes is 1. In that case, return 1. num_rolls: The number of dice rolls that will be made. dice: A function that simulates a single dice roll outcome. """ # These assert statements ensure that num_rolls is a positive integer. asserttype(num_rolls) == int, 'num_rolls must be an integer.' assert num_rolls > 0, 'Must roll at least once.' # BEGIN PROBLEM 1 "*** YOUR CODE HERE ***" sum,f=0,0 num_of_rolls=1 while num_of_rolls<=num_rolls: c=dice() sum+=c num_of_rolls+=1 if c==1: f=1 if f==1: return1 else: returnsum # END PROBLEM 1
defpicky_piggy(score): """Return the points scored from rolling 0 dice. score: The opponent's current score. """ # BEGIN PROBLEM 2 "*** YOUR CODE HERE ***" if score%6==0: return7 else: s=score%6 if s==1: return1 elif s==2: return4 elif s==3: return2 elif s==4: return8 elif s==5: return5 # END PROBLEM 2
deftake_turn(num_rolls, opponent_score, dice=six_sided, goal=GOAL_SCORE): """Simulate a turn rolling NUM_ROLLS dice, which may be 0 in the case of a player using Picky Piggy. Return the points scored for the turn by the current player. num_rolls: The number of dice rolls that will be made. opponent_score: The total score of the opponent. dice: A function that simulates a single dice roll outcome. goal: The goal score of the game. """ # Leave these assert statements here; they help check for errors. asserttype(num_rolls) == int, 'num_rolls must be an integer.' assert num_rolls >= 0, 'Cannot roll a negative number of dice in take_turn.' assert num_rolls <= 10, 'Cannot roll more than 10 dice.' assert opponent_score < goal, 'The game should be over.' # BEGIN PROBLEM 3 "*** YOUR CODE HERE ***" if num_rolls==0: return picky_piggy(opponent_score) else: return roll_dice(num_rolls,dice) # END PROBLEM 3
defhog_pile(player_score, opponent_score): """Return the points scored by player due to Hog Pile. player_score: The total score of the current player. opponent_score: The total score of the other player. """ # BEGIN PROBLEM 4 "*** YOUR CODE HERE ***" if player_score!=opponent_score: return0 else: return player_score # END PROBLEM 4
defplay(strategy0, strategy1, score0=0, score1=0, dice=six_sided, goal=GOAL_SCORE, say=silence): """Simulate a game and return the final scores of both players, with Player 0's score first, and Player 1's score second. A strategy is a function that takes two total scores as arguments (the current player's score, and the opponent's score), and returns a number of dice that the current player will roll this turn. strategy0: The strategy function for Player 0, who plays first. strategy1: The strategy function for Player 1, who plays second. score0: Starting score for Player 0 score1: Starting score for Player 1 dice: A function of zero arguments that simulates a dice roll. goal: The game ends and someone wins when this score is reached. say: The commentary function to call at the end of the first turn. """ who = 0# Who is about to take a turn, 0 (first) or 1 (second) # BEGIN PROBLEM 5 "*** YOUR CODE HERE ***" while score0<goal and score1<goal: if next_player(who)==1: score0+=take_turn(strategy0(score0,score1), score1, dice, goal) a=hog_pile(score0,score1) score0+=a who=1 elif next_player(who)==0: score1+=take_turn(strategy1(score1,score0),score0,dice,goal) #这里如果继续的话可能会有score0>goal而游戏还没停止,所以应该增加判断 b=hog_pile(score1,score0) score1+=b who=0 # END PROBLEM 5 # (note that the indentation for the problem 6 prompt (***YOUR CODE HERE***) might be misleading) # BEGIN PROBLEM 6 "*** YOUR CODE HERE ***" # END PROBLEM 6 return score0, score1
Phase 2:Commentary
这个phase不重要吧,我就不改了(暴论
Problem 6
比较简单,不知为何,-u环节我的line2过不了,总报not quite。
Problem 7
…比较离谱
to be debug
执行了python3 hog_gui.py后发现bug:
底下的文字不会消失,本应该报历史最大新增,但却报的是当前的points,如
8 point(s)! That’s a record gain for Player 0! 8 point(s)! That’s a record gain for Player 1!
Phase3:Strategies
Problem 8
a new piece of Python syntax
We would like to write a function that accepts an arbitrary number of arguments, and then calls another function using exactly those arguments. Here’s how it works.
Instead of listing formal parameters for a function, you can write *args, which represents all of the arguments that get passed into the function. We can then call another function with these same arguments by passing these *args into this other function. For example:
1 2 3 4 5 6
>>>defprinted(f): defprint_and_return(*args): result=f(*args) print('Result:',result) return result return print_and_return
defmake_averaged(original_function, trials_count=1000): """Return a function that returns the average value of ORIGINAL_FUNCTION called TRIALS_COUNT times. To implement this function, you will have to use *args syntax, a new Python feature introduced in this project. See the project description. >>> dice = make_test_dice(4, 2, 5, 1) >>> averaged_dice = make_averaged(roll_dice, 1000) >>> averaged_dice(1, dice) 3.0 """ # BEGIN PROBLEM 8 "*** YOUR CODE HERE ***" defaverage(*args): dice_nums=1 sum=0 while dice_nums<=trials_count: sum+=original_function(*args) dice_nums+=1 returnsum/trials_count return average # END PROBLEM 8
defmax_scoring_num_rolls(dice=six_sided, trials_count=1000): """Return the number of dice (1 to 10) that gives the highest average turn score by calling roll_dice with the provided DICE a total of TRIALS_COUNT times. Assume that the dice always return positive outcomes. >>> dice = make_test_dice(1, 6) >>> max_scoring_num_rolls(dice) 1 """ # BEGIN PROBLEM 9 "*** YOUR CODE HERE ***" #要用到make_averaged和roll_dice(num_rolls,dice) max_ave,num=0,1 flag=1 while num<=10: a=make_averaged(roll_dice,trials_count) b=a(num,dice) if max_ave<b: max_ave=b flag=num num+=1 return flag # END PROBLEM 9
Problem 10
1 2 3 4 5 6 7 8 9 10
defpicky_piggy_strategy(score, opponent_score, cutoff=8, num_rolls=6): """This strategy returns 0 dice if that gives at least CUTOFF points, and returns NUM_ROLLS otherwise. """ # BEGIN PROBLEM 10 if picky_piggy(opponent_score)>=cutoff: return0 else: return num_rolls # END PROBLEM 10
Problem 11
1 2 3 4 5 6 7 8 9 10 11 12 13 14
defhog_pile_strategy(score, opponent_score, cutoff=8, num_rolls=6): """This strategy returns 0 dice when this would result in Hog Pile taking effect. It also returns 0 dice if it gives at least CUTOFF points. Otherwise, it returns NUM_ROLLS. """ # BEGIN PROBLEM 11 a=hog_pile(score+picky_piggy(opponent_score),opponent_score) if a!=0: #触发了 return0 elif picky_piggy(opponent_score)>=cutoff: return0 else: return num_rolls # END PROBLEM 11
The summation(n, term) function from the higher-order functions lecture adds up term(1) + ... + term(n). Write a similar function called product that returns term(1) * ... * term(n).
defaccumulate(merger, base, n, term): """Return the result of merging the first n terms in a sequence and base. The terms to be merged are term(1), term(2), ..., term(n). merger is a two-argument commutative 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 >>> # 2 + (1^2 + 1) + (2^2 + 1) + (3^2 + 1) >>> accumulate(lambda x, y: x + y + 1, 2, 3, square) 19 >>> # ((2 * 1^2 * 2) * 2^2 * 2) * 3^2 * 2 >>> accumulate(lambda x, y: 2 * x * y, 2, 3, square) 576 >>> accumulate(lambda x, y: (x + y) % 17, 19, 20, square) 16 """ "*** YOUR CODE HERE ***"
After implementing accumulate, show how summation and product can both be defined as function calls to accumulate.
Important: You should have a single line of code (which should be a return statement) in each of your implementations for summation_using_accumulate and product_using_accumulate, which the syntax check will check for.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
defsummation_using_accumulate(n, term): """Returns the sum: term(1) + ... + term(n), using accumulate. >>> summation_using_accumulate(5, square) 55 >>> summation_using_accumulate(5, triple) 45 """ "*** YOUR CODE HERE ***"
defproduct_using_accumulate(n, term): """Returns the product: term(1) * ... * term(n), using accumulate. >>> product_using_accumulate(4, square) 576 >>> product_using_accumulate(6, triple) 524880 """ "*** YOUR CODE HERE ***"
my answer:
1 2 3 4 5 6 7 8 9 10 11 12
defaccumulate(merger, base, n, term): a=1 while a<=n: base=merger(base,term(a)) a+=1 return base
This question is out of scope for 61A. You can try it if you want an extra challenge, but it’s just a puzzle that is not required or recommended at all. Almost all students will skip it, and that’s fine.
to be debug…
Lab2:Higher-Order Functions,Lambda Expressions
Q3:Lambdas and Currying
We can transform multiple-argument functions into a chain of single-argument, higher order functions by taking advantage of lambda expressions. For example, we can write a function f(x, y) as a different function g(x)(y). This is known as currying. It’s useful when dealing with functions that take only single-argument functions. We will see some examples of these later on.
Write a function lambda_curry2 that will curry any two argument function using lambdas. Refer to the textbook for more details about currying.
Your solution to this problem should fit entirely on the return line. You can try first writing a solution without the restriction, and then rewriting it into one line after.
If the syntax check isn’t passing: Make sure you’ve removed the line containing "***YOUR CODE HERE***" so that it doesn’t get treated as part of the function for the syntax check.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
deflambda_curry2(func): """ Returns a Curried version of a two-argument function FUNC. >>> from operator import add, mul, mod >>> curried_add = lambda_curry2(add) >>> add_three = curried_add(3) >>> add_three(5) 8 >>> curried_mul = lambda_curry2(mul) >>> mul_5 = curried_mul(5) >>> mul_5(42) 210 >>> lambda_curry2(mod)(123)(10) 3 """ "*** YOUR CODE HERE ***" return ______
Consider the following implementations of count_factors and count_primes:
The implementations look quite similar! Generalize this logic by writing a function count_cond, which takes in a two-argument predicate function condition(n, i). count_cond returns a one-argument function that takes in n, which counts all the numbers from 1 to n that satisfy condition when called.
defcount_cond(condition): """Returns a function with one parameter N that counts all the numbers from 1 to N that satisfy the two-argument predicate function Condition, where the first argument for Condition is N and the second argument is the number from 1 to N. >>> count_factors = count_cond(lambda n, i: n % i == 0) >>> count_factors(2) # 1, 2 2 >>> count_factors(4) # 1, 2, 4 3 >>> count_factors(12) # 1, 2, 3, 4, 6, 12 6 >>> is_prime = lambda n, i: count_factors(i) == 2 >>> count_primes = count_cond(is_prime) >>> count_primes(2) # 2 1 >>> count_primes(3) # 2, 3 2 >>> count_primes(4) # 2, 3 2 >>> count_primes(5) # 2, 3, 5 3 >>> count_primes(20) # 2, 3, 5, 7, 11, 13, 17, 19 8 """ "*** YOUR CODE HERE ***"
Use Ok to test your code:
1
python3 ok -q count_cond
my answer:
1 2 3 4 5 6 7 8 9 10
defcount_cond(condition): defcount_func(n): i=1 count=0 while i<=n: if condition(n,i): count+=1 i+=1 return count return count_func
Q7:Composite Identity Function
optional
Write a function that takes in two single-argument functions, f and g, and returns another function that has a single parameter x. The returned function should return True if f(g(x)) is equal to g(f(x)). You can assume the output of g(x) is a valid input for f and vice versa. Try to use the composer function defined below for more HOF practice.
defcomposer(f, g): """Return the composition function which given x, computes f(g(x)). >>> add_one = lambda x: x + 1 # adds one to x >>> square = lambda x: x**2 >>> a1 = composer(square, add_one) # (x + 1)^2 >>> a1(4) 25 >>> mul_three = lambda x: x * 3 # multiplies 3 to x >>> a2 = composer(mul_three, a1) # ((x + 1)^2) * 3 >>> a2(4) 75 >>> a2(5) 108 """ returnlambda x: f(g(x))
defcomposite_identity(f, g): """ Return a function with one parameter x that returns True if f(g(x)) is equal to g(f(x)). You can assume the result of g(x) is a valid input for f and vice versa. >>> add_one = lambda x: x + 1 # adds one to x >>> square = lambda x: x**2 >>> b1 = composite_identity(square, add_one) >>> b1(0) # (0 + 1)^2 == 0^2 + 1 True >>> b1(4) # (4 + 1)^2 != 4^2 + 1 False """ "*** YOUR CODE HERE ***"
Use Ok to test your code:
1
python3 ok -q composite_identity
my answer:
1 2 3 4 5 6 7
defcomposite_identity(f, g): defjudge(x): if composer(f,g)(x)==composer(g,f)(x): returnTrue else: returnFalse return judge
Q8:I Heard You Liked Functions…
optional
Define a function cycle that takes in three functions f1, f2, f3, as arguments. cycle will return another function that should take in an integer argument n and return another function. That final function should take in an argument x and cycle through applying f1, f2, and f3 to x, depending on what n was. Here’s what the final function should do to x for a few values of n:
n = 0, return x
n = 1, apply f1 to x, or return f1(x)
n = 2, apply f1 to x and then f2 to the result of that, or return f2(f1(x))
n = 3, apply f1 to x, f2 to the result of applying f1, and then f3 to the result of applying f2, or f3(f2(f1(x)))
n = 4, start the cycle again applying f1, then f2, then f3, then f1 again, or f1(f3(f2(f1(x))))
And so forth.
Hint: most of the work goes inside the most nested function.
defmake_keeper(n): """Returns a function which takes one parameter cond and prints out all integers 1..i..n where calling cond(i) returns True. >>> def is_even(x): ... # Even numbers have remainder 0 when divided by 2. ... return x % 2 == 0 >>> make_keeper(5)(is_even) 2 4 """ "*** YOUR CODE HERE ***" deffunc(cond): i=1 while i<=n: if cond(i): print(i) i+=1 return func
defunique_digits(n): """Return the number of unique digits in positive integer n. >>> unique_digits(8675309) # All are unique 7 >>> unique_digits(1313131) # 1 and 3 2 >>> unique_digits(13173131) # 1, 3, and 7 3 >>> unique_digits(10000) # 0 and 1 2 >>> unique_digits(101) # 0 and 1 2 >>> unique_digits(10) # 0 and 1 2 """ "*** YOUR CODE HERE ***" i,count=0,0 while i<10: if has_digit(n,i): count+=1 i+=1 return count
defhas_digit(n, k): """Returns whether K is a digit in N. >>> has_digit(10, 1) True >>> has_digit(12, 7) False """ "*** YOUR CODE HERE ***" while n!=0: if n%10==k: returnTrue else: n=n//10 returnFalse
defordered_digits(x): """Return True if the (base 10) digits of X>0 are in non-decreasing order, and False otherwise. >>> ordered_digits(5) True >>> ordered_digits(11) True >>> ordered_digits(127) True >>> ordered_digits(1357) True >>> ordered_digits(21) False >>> result = ordered_digits(1375) # Return, don't print >>> result False """ "*** YOUR CODE HERE ***" vis=x%10 while x!=0: x=x//10 if vis>=x%10: vis=x%10 else: returnFalse returnTrue
defmake_repeater(func, n): """Return the function that computes the nth application of func. >>> add_three = make_repeater(increment, 3) >>> add_three(5) 8 >>> make_repeater(triple, 5)(1) # 3 * 3 * 3 * 3 * 3 * 1 243 >>> make_repeater(square, 2)(5) # square(square(5)) 625 >>> make_repeater(square, 4)(5) # square(square(square(square(5)))) 152587890625 >>> make_repeater(square, 0)(5) # Yes, it makes sense to apply the function zero times! 5 """ "*** YOUR CODE HERE ***" deffunc_n(x): if n==0: return x elif n==1: return func(x) else: i,final_func=2,composer(func,func) while i<n: final_func=composer(func,final_func) i+=1 return final_func(x) return func_n
Q5:Apply Twice
1 2 3 4 5 6 7 8 9 10
defapply_twice(func): """ Return a function that applies func twice. func -- a function that takes one argument >>> apply_twice(square)(2) 16 """ "*** YOUR CODE HERE ***" return make_repeater(func,2)
defprotected_secret(password, secret, num_attempts): """ Returns a function which takes in a password and prints the SECRET if the password entered matches the PASSWORD given to protected_secret. Otherwise it prints "INCORRECT PASSWORD". After NUM_ATTEMPTS incorrect passwords are entered, the secret is locked and the function should print "SECRET LOCKED". >>> my_secret = protected_secret("correcthorsebatterystaple", "I love UCB", 2) >>> my_secret = my_secret("hax0r_1") # 2 attempts left INCORRECT PASSWORD >>> my_secret = my_secret("correcthorsebatterystaple") I love UCB >>> my_secret = my_secret("hax0r_2") # 1 attempt left INCORRECT PASSWORD >>> my_secret = my_secret("hax0r_3") # No attempts left SECRET LOCKED >>> my_secret = my_secret("correcthorsebatterystaple") SECRET LOCKED """ defget_secret(password_attempt): "*** YOUR CODE HERE ***" if num_attempts>0: if password_attempt==password: print(secret) return get_secret else: print("INCORRECT PASSWORD") num=num_attempts-1 return protected_secret(password,secret,num) else: print("SECRET LOCKED") return get_secret return get_secret
Disc 3:Recursive
Q1:Warm Up:Recursive Multiplication
Hint:5*3=5+(5*2)=5+5+(5*1)
1 2 3 4 5 6 7 8 9 10
defmultiply(m, n): """ Takes two positive integers and returns their product using recursion. >>> multiply(5, 3) 15 """ "*** YOUR CODE HERE ***" if n==1: return m else: return m+multiply(m,n-1)
defis_prime(n): """Returns True if n is a prime number and False otherwise. >>> is_prime(2) True >>> is_prime(16) False >>> is_prime(521) True """ "*** YOUR CODE HERE ***" defhelper(x): if x==n: returnTrue elif n%x==0or n==1: returnFalse elif x==n: returnTrue else: return helper(x+1) return helper(2)
Q5:Recursive Hailstone
fail to return the number of elements in the wequence…
defhailstone(n): """Print out the hailstone sequence starting at n, and return the number of elements in the sequence. >>> a = hailstone(10) 10 5 16 8 4 2 1 >>> a 7 """ "*** YOUR CODE HERE ***" if n%2==0and n!=1: print(n) return hailstone(n//2) elif n%2!=0and n!=1: print(n) return hailstone(n*3+1) elif n==1: print(n) return count_num(n)
Q6:Merge Numbers
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
defmerge(n1, n2): """ Merges two numbers by digit in decreasing order >>> merge(31, 42) 4321 >>> merge(21, 0) 21 >>> merge (21, 31) 3211 """ "*** YOUR CODE HERE ***" if n1==0: return n2 elif n2==0: return n1 elif n1%10>n2%10: return merge(n1,n2//10)*10+n2%10 else: return merge(n1//10,n2)*10+n1%10
defnum_eights(pos): """Returns the number of times 8 appears as a digit of pos. >>> num_eights(3) 0 >>> num_eights(8) 1 >>> num_eights(88888888) 8 >>> num_eights(2638) 1 >>> num_eights(86380) 2 >>> num_eights(12345) 0 >>> from construct_check import check >>> # ban all assignment statements >>> check(HW_SOURCE_FILE, 'num_eights', ... ['Assign', 'AnnAssign', 'AugAssign', 'NamedExpr']) True """ "*** YOUR CODE HERE ***" if pos//10!=0: if pos%10==8: return num_eights(pos//10)+1 else: return num_eights(pos//10) else: if pos%10==8: return1 else: return0
defmissing_digits(n): """Given a number a that is in sorted, non-decreasing order, return the number of missing digits in n. A missing digit is a number between the first and last digit of a that is not in n. >>> missing_digits(1248) # 3, 5, 6, 7 4 >>> missing_digits(19) # 2, 3, 4, 5, 6, 7, 8 7 >>> missing_digits(1122) # No missing numbers 0 >>> missing_digits(123456) # No missing numbers 0 >>> missing_digits(3558) # 4, 6, 7 3 >>> missing_digits(35578) # 4, 6 2 >>> missing_digits(12456) # 3 1 >>> missing_digits(16789) # 2, 3, 4, 5 4 >>> missing_digits(4) # No missing numbers between 4 and 4 0 >>> from construct_check import check >>> # ban while or for loops >>> check(HW_SOURCE_FILE, 'missing_digits', ['While', 'For']) True """ "*** YOUR CODE HERE ***" if n//10==0: return0 elif n%10>n//10%10: return missing_digits(n//10)+n%10-n//10%10-1 elif n%10==n//10%10: return missing_digits(n//10)
defsummation(n, term): """Return the sum of numbers 1 through n (including n) wíth term applied to each number. Implement using recursion! >>> summation(5, lambda x: x * x * x) # 1^3 + 2^3 + 3^3 + 4^3 + 5^3 225 >>> summation(9, lambda x: x + 1) # 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 54 >>> summation(5, lambda x: 2**x) # 2^1 + 2^2 + 2^3 + 2^4 + 2^5 62 >>> # Do not use while/for loops! >>> from construct_check import check >>> # ban iteration >>> check(HW_SOURCE_FILE, 'summation', ... ['While', 'For']) True """ assert n >= 1 "*** YOUR CODE HERE ***" if n==1: return term(n) else: return summation(n-1,term)+term(n)
Q3:Pascal’s Triangle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
defpascal(row, column): """Returns the value of the item in Pascal's Triangle whose position is specified by row and column. >>> pascal(0, 0) 1 >>> pascal(0, 5) # Empty entry; outside of Pascal's Triangle 0 >>> pascal(3, 2) # Row 3 (1 3 3 1), Column 2 3 >>> pascal(4, 2) # Row 4 (1 4 6 4 1), Column 2 6 """ "*** YOUR CODE HERE ***" if column>row: return0 elif column==0or row==0: return1 else: return pascal(row-1,column-1)+pascal(row-1,column)
Q4:Insect Combinatorics
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
defpaths(m, n): """Return the number of paths from one corner of an M by N grid to the opposite corner. >>> paths(2, 2) 2 >>> paths(5, 7) 210 >>> paths(117, 1) 1 >>> paths(1, 157) 1 """ "*** YOUR CODE HERE ***" if m==1or n==1: return1 else: return paths(m-1,n)+paths(m,n-1)
Q5:Couple
…感觉自己真傻
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
defcouple(s, t): """Return a list of two-element lists in which the i-th element is [s[i], t[i]]. >>> a = [1, 2, 3] >>> b = [4, 5, 6] >>> couple(a, b) [[1, 4], [2, 5], [3, 6]] >>> c = ['c', 6] >>> d = ['s', '1'] >>> couple(c, d) [['c', 's'], [6, '1']] """ assertlen(s) == len(t) "*** YOUR CODE HERE ***" return [[s[i],t[i]] for i inrange(0,len(s))]
Q6:Coordinates
optional
1 2 3 4 5 6 7 8 9
defcoords(fn, seq, lower, upper): """ >>> seq = [-4, -2, 0, 1, 3] >>> fn = lambda x: x**2 >>> coords(fn, seq, 1, 9) [[-2, 4], [1, 1], [3, 9]] """ "*** YOUR CODE HERE ***" return [[x,fn(x)] for x in seq if fn(x)>=lower and fn(x)<=upper]
Q7:Riffle Shuffle
optional
1 2 3 4 5 6 7 8 9 10 11
defriffle(deck): """Produces a single, perfect riffle shuffle of DECK, consisting of DECK[0], DECK[M], DECK[1], DECK[M+1], ... where M is position of the second half of the deck. Assume that len(DECK) is even. >>> riffle([3, 4, 5, 6]) [3, 5, 4, 6] >>> riffle(range(20)) [0, 10, 1, 11, 2, 12, 3, 13, 4, 14, 5, 15, 6, 16, 7, 17, 8, 18, 9, 19] """ "*** YOUR CODE HERE ***" return [deck[i//2+(len(deck)//2)*(i%2)] for i inrange(len(deck))]
Disc 4:Tree Recursion,Python Lists
Q1:Count Stair Ways
1 2 3 4 5 6 7 8 9 10 11 12 13
defcount_stair_ways(n): """Returns the number of ways to climb up a flight of n stairs, moving either 1 step or 2 steps at a time. >>> count_stair_ways(4) 5 """ "*** YOUR CODE HERE ***" if n==1: return1 elif n==2: return2 else: return count_stair_ways(n-1)+count_stair_ways(n-2)
defcount_k(n, k): """ Counts the number of paths up a flight of n stairs when taking up to and including k steps at a time. >>> count_k(3, 3) # 3, 2 + 1, 1 + 2, 1 + 1 + 1 4 >>> count_k(4, 4) 8 >>> count_k(10, 3) 274 >>> count_k(300, 1) # Only one step at a time 1 """ "*** YOUR CODE HERE ***" if n==1: return1 else: i,sum=1,0 while i<=k: sum+=count_k(n-i,k) i+=1 returnsum
Q5:Max Product
1 2 3 4 5 6 7 8 9 10 11 12 13 14
defmax_product(s): """Return the maximum product that can be formed using non-consecutive elements of s. >>> max_product([10,3,1,9,2]) # 10 * 9 90 >>> max_product([5,10,5,10,5]) # 5 * 5 * 5 125 >>> max_product([]) 1 """ if s==[]: return1 else: returnmax(max_product(s[1:]),s[0]*max_product(s[2:]))
defchoose(paragraphs, select, k): """Return the Kth paragraph from PARAGRAPHS for which SELECT called on the paragraph returns True. If there are fewer than K such paragraphs, return the empty string. Arguments: paragraphs: a list of strings select: a function that returns True for paragraphs that can be selected k: an integer >>> ps = ['hi', 'how are you', 'fine'] >>> s = lambda p: len(p) <= 4 >>> choose(ps, s, 0) 'hi' >>> choose(ps, s, 1) 'fine' >>> choose(ps, s, 2) '' """ # BEGIN PROBLEM 1 "*** YOUR CODE HERE ***" i,j=0,0 store_list=[] while i<len(paragraphs): if select(paragraphs[i]): store_list.insert(j,paragraphs[i]) i+=1 j+=1 else: i+=1 if k>=j: return'' else: return store_list[k] # END PROBLEM 1
defabout(topic): """Return a select function that returns whether a paragraph contains one of the words in TOPIC. Arguments: topic: a list of words related to a subject >>> about_dogs = about(['dog', 'dogs', 'pup', 'puppy']) >>> choose(['Cute Dog!', 'That is a cat.', 'Nice pup!'], about_dogs, 0) 'Cute Dog!' >>> choose(['Cute Dog!', 'That is a cat.', 'Nice pup.'], about_dogs, 1) 'Nice pup.' """ assertall([lower(x) == x for x in topic]), 'topics should be lowercase.' # BEGIN PROBLEM 2 "*** YOUR CODE HERE ***" defsel(para): i=0 para=remove_punctuation(para) para=lower(para) para=split(para) while i<len(para): if para[i] in topic: returnTrue else: i+=1 returnFalse return sel # END PROBLEM 2
defaccuracy(typed, reference): """Return the accuracy (percentage of words typed correctly) of TYPED when compared to the prefix of REFERENCE that was typed. Arguments: typed: a string that may contain typos reference: a string without errors >>> accuracy('Cute Dog!', 'Cute Dog.') 50.0 >>> accuracy('A Cute Dog!', 'Cute Dog.') 0.0 >>> accuracy('cute Dog.', 'Cute Dog.') 50.0 >>> accuracy('Cute Dog. I say!', 'Cute Dog.') 50.0 >>> accuracy('Cute', 'Cute Dog.') 100.0 >>> accuracy('', 'Cute Dog.') 0.0 >>> accuracy('', '') 100.0 """ typed_words = split(typed) reference_words = split(reference) # BEGIN PROBLEM 3 "*** YOUR CODE HERE ***" if typed==''and reference=='': return100.0 elif typed==''or reference=='': return0.0 else: ty=split(typed) ref=split(reference) i,count=0,0 iflen(ty)<=len(ref): while i<len(ty): if ty[i]==ref[i]: count+=1 i+=1 return100*count/len(ty) else: while i<len(ref): if ty[i]==ref[i]: count+=1 i+=1 return100*count/len(ty) # END PROBLEM 3
Problem 4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
defwpm(typed, elapsed): """Return the words-per-minute (WPM) of the TYPED string. Arguments: typed: an entered string elapsed: an amount of time in seconds >>> wpm('hello friend hello buddy hello', 15) 24.0 >>> wpm('0123456789',60) 2.0 """ assert elapsed > 0, 'Elapsed time must be positive' # BEGIN PROBLEM 4 "*** YOUR CODE HERE ***" vis=len(typed)/5 return vis*60/elapsed # END PROBLEM 4
defautocorrect(typed_word, valid_words, diff_function, limit): """Returns the element of VALID_WORDS that has the smallest difference from TYPED_WORD. Instead returns TYPED_WORD if that difference is greater than LIMIT. Arguments: typed_word: a string representing a word that may contain typos valid_words: a list of strings representing valid words diff_function: a function quantifying the difference between two words limit: a number >>> ten_diff = lambda w1, w2, limit: 10 # Always returns 10 >>> autocorrect("hwllo", ["butter", "hello", "potato"], ten_diff, 20) 'butter' >>> first_diff = lambda w1, w2, limit: (1 if w1[0] != w2[0] else 0) # Checks for matching first char >>> autocorrect("tosting", ["testing", "asking", "fasting"], first_diff, 10) 'testing' """ # BEGIN PROBLEM 5 "*** YOUR CODE HERE ***" if typed_word in valid_words: return typed_word else: i,j=0,0 vis=limit+1 while i<len(valid_words): a=diff_function(typed_word,valid_words[i],limit) if a<vis: vis=a j=i i+=1 if vis<=limit: return valid_words[j] else: return typed_word # END PROBLEM 5
嘛,google到了一种简单的方法:建立一个dictionary
1 2 3 4 5 6 7 8 9 10 11 12 13 14
defautocorrect(user_word, valid_words, diff_function, limit): """Returns the element of VALID_WORDS that has the smallest difference from USER_WORD. Instead returns USER_WORD if that difference is greater than LIMIT. """ # BEGIN PROBLEM 5 "*** YOUR CODE HERE ***" if user_word in valid_words: return user_word # Create dictionary with keys as iterables in valid_words list # and values as difference between them and user_word d = {v : diff_function(user_word, v, limit) for v in valid_words} returnmin(d, key=d.get) ifmin(d.values()) <= limit else user_word # END PROBLEM 5
deffeline_flips(start, goal, limit): """A diff function for autocorrect that determines how many letters in START need to be substituted to create GOAL, then adds the difference in their lengths and returns the result. Arguments: start: a starting word goal: a string representing a desired goal word limit: a number representing an upper bound on the number of chars that must change >>> big_limit = 10 >>> feline_flips("nice", "rice", big_limit) # Substitute: n -> r 1 >>> feline_flips("range", "rungs", big_limit) # Substitute: a -> u, e -> s 2 >>> feline_flips("pill", "pillage", big_limit) # Don't substitute anything, length difference of 3. 3 >>> feline_flips("roses", "arose", big_limit) # Substitute: r -> a, o -> r, s -> o, e -> s, s -> e 5 >>> feline_flips("rose", "hello", big_limit) # Substitute: r->h, o->e, s->l, e->l, length difference of 1. 5 """ # BEGIN PROBLEM 6 if limit<0: return1 iflen(start)==0orlen(goal)==0: returnabs(len(start)-len(goal)) else: if start[0]==goal[0]: return feline_flips(start[1:], goal[1:], limit) else: return feline_flips(start[1:], goal[1:], limit-1)+1 # END PROBLEM 6
defminimum_mewtations(start, goal, limit): """A diff function that computes the edit distance from START to GOAL. This function takes in a string START, a string GOAL, and a number LIMIT. Arguments: start: a starting word goal: a goal word limit: a number representing an upper bound on the number of edits >>> big_limit = 10 >>> minimum_mewtations("cats", "scat", big_limit) # cats -> scats -> scat 2 >>> minimum_mewtations("purng", "purring", big_limit) # purng -> purrng -> purring 2 >>> minimum_mewtations("ckiteus", "kittens", big_limit) # ckiteus -> kiteus -> kitteus -> kittens 3 """ if limit<0: # Fill in the condition # BEGIN "*** YOUR CODE HERE ***" return1 # END
eliflen(start)==0orlen(goal)==0: # Feel free to remove or add additional cases # BEGIN "*** YOUR CODE HERE ***" returnabs(len(start)-len(goal)) # END elif start[0]==goal[0]: return minimum_mewtations(start[1:], goal[1:], limit) else: add = minimum_mewtations(start,goal[1:],limit-1) # Fill in these lines remove = minimum_mewtations(start[1:],goal,limit-1) substitute = minimum_mewtations(start[1:],goal[1:],limit-1) # BEGIN "*** YOUR CODE HERE ***" returnmin(add,remove,substitute)+1 # END
defreport_progress(sofar, prompt, user_id, upload): """Upload a report of your id and progress so far to the multiplayer server. Returns the progress so far. Arguments: sofar: a list of the words input so far prompt: a list of the words in the typing prompt user_id: a number representing the id of the current user upload: a function used to upload progress to the multiplayer server >>> print_progress = lambda d: print('ID:', d['id'], 'Progress:', d['progress']) >>> # The above function displays progress in the format ID: __, Progress: __ >>> print_progress({'id': 1, 'progress': 0.6}) ID: 1 Progress: 0.6 >>> sofar = ['how', 'are', 'you'] >>> prompt = ['how', 'are', 'you', 'doing', 'today'] >>> report_progress(sofar, prompt, 2, print_progress) ID: 2 Progress: 0.6 0.6 >>> report_progress(['how', 'aree'], prompt, 3, print_progress) ID: 3 Progress: 0.2 0.2 """ # BEGIN PROBLEM 8 "*** YOUR CODE HERE ***" i,j,count=0,0,0 while i<len(sofar) and j<len(prompt): if sofar[i]==prompt[j]: count+=1 j+=1 i+=1 gress=count/len(prompt) d={'id':user_id,'progress':gress} upload(d) return gress # END PROBLEM 8
deftime_per_word(words, times_per_player): """Given timing data, return a match data abstraction, which contains a list of words and the amount of time each player took to type each word. Arguments: words: a list of words, in the order they are typed. times_per_player: A list of lists of timestamps including the time the player started typing, followed by the time the player finished typing each word. >>> p = [[75, 81, 84, 90, 92], [19, 29, 35, 36, 38]] >>> match = time_per_word(['collar', 'plush', 'blush', 'repute'], p) >>> get_words(match) ['collar', 'plush', 'blush', 'repute'] >>> get_times(match) [[6, 3, 6, 2], [10, 6, 1, 2]] """ # BEGIN PROBLEM 9 "*** YOUR CODE HERE ***" i=0 test=[] while i<len(times_per_player): p=times_per_player[i] j=0 while j<len(p)-1: p[j]=p[j+1]-p[j] j+=1 test.append(p[:len(p)-1]) i+=1 return match(words,test) # END PROBLEM 9
deffastest_words(match): """Return a list of lists of which words each player typed fastest. Arguments: match: a match data abstraction as returned by time_per_word. >>> p0 = [5, 1, 3] >>> p1 = [4, 1, 6] >>> fastest_words(match(['Just', 'have', 'fun'], [p0, p1])) [['have', 'fun'], ['Just']] >>> p0 # input lists should not be mutated [5, 1, 3] >>> p1 [4, 1, 6] """ player_indices = range(len(get_times(match))) # contains an *index* for each player word_indices = range(len(get_words(match))) # contains an *index* for each word # BEGIN PROBLEM 10 "*** YOUR CODE HERE ***" test=[[] for k in player_indices] for i in word_indices: times=[time(match,j,i) for j in player_indices] test[times.index(min(times))].append(word_at(match,i)) return test # END PROBLEM 10
Some feelings
明显感觉project2比project1简单不少,花的时间也少多了
希望是我python水平提高的原因吧
Lab 5:Python Lists, Trees
Q1:Factors List
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
deffactors_list(n): """Return a list containing all the numbers that divide `n` evenly, except for the number itself. Make sure the list is in ascending order. >>> factors_list(6) [1, 2, 3] >>> factors_list(8) [1, 2, 4] >>> factors_list(28) [1, 2, 4, 7, 14] """ all_factors = [] i=1 while i<n: if n%i==0: all_factors.append(i) i+=1 return all_factors
Q2:Flatten
Hint: you can check if something is a list by using the built-in type function. For example:
1 2 3 4
>>> type(3) == list False >>> type([1, 2, 3]) == list True
defflatten(s): """Returns a flattened version of list s. >>> flatten([1, 2, 3]) # normal list [1, 2, 3] >>> x = [1, [2, 3], 4] # deep list >>> flatten(x) [1, 2, 3, 4] >>> x # Ensure x is not mutated [1, [2, 3], 4] >>> x = [[1, [1, 1]], 1, [1, 1]] # deep list >>> flatten(x) [1, 1, 1, 1, 1, 1] >>> x [[1, [1, 1]], 1, [1, 1]] """ "*** YOUR CODE HERE ***" result=[] for i in s: iftype(i)==list: result+=flatten(i) else: result.append(i) return result
defcloser_city(lat, lon, city_a, city_b): """ Returns the name of either city_a or city_b, whichever is closest to coordinate (lat, lon). If the two cities are the same distance away from the coordinate, consider city_b to be the closer city. >>> berkeley = make_city('Berkeley', 37.87, 112.26) >>> stanford = make_city('Stanford', 34.05, 118.25) >>> closer_city(38.33, 121.44, berkeley, stanford) 'Stanford' >>> bucharest = make_city('Bucharest', 44.43, 26.10) >>> vienna = make_city('Vienna', 48.20, 16.37) >>> closer_city(41.29, 174.78, bucharest, vienna) 'Bucharest' """ "*** YOUR CODE HERE ***" city=make_city('city',lat,lon) if distance(city,city_a)>=distance(city,city_b): return get_name(city_b) else: return get_name(city_a)
defberry_finder(t): """Returns True if t contains a node with the value 'berry' and False otherwise. >>> scrat = tree('berry') >>> berry_finder(scrat) True >>> sproul = tree('roots', [tree('branch1', [tree('leaf'), tree('berry')]), tree('branch2')]) >>> berry_finder(sproul) True >>> numbers = tree(1, [tree(2), tree(3, [tree(4), tree(5)]), tree(6, [tree(7)])]) >>> berry_finder(numbers) False >>> t = tree(1, [tree('berry',[tree('not berry')])]) >>> berry_finder(t) True """ "*** YOUR CODE HERE ***" if label(t)=='berry': returnTrue else: for b in branches(t): if berry_finder(b): returnTrue returnFalse
defsprout_leaves(t, leaves): """Sprout new leaves containing the data in leaves at each leaf in the original tree t and return the resulting tree. >>> t1 = tree(1, [tree(2), tree(3)]) >>> print_tree(t1) 1 2 3 >>> new1 = sprout_leaves(t1, [4, 5]) >>> print_tree(new1) 1 2 4 5 3 4 5 >>> t2 = tree(1, [tree(2, [tree(3)])]) >>> print_tree(t2) 1 2 3 >>> new2 = sprout_leaves(t2, [6, 1, 2]) >>> print_tree(new2) 1 2 3 6 1 2 """ "*** YOUR CODE HERE ***" if is_leaf(t): return tree(label(t),[tree(b) for b in leaves]) else: return tree(label(t),[sprout_leaves(b,leaves) for b in branches(t)])
Disc 5:Trees, Data Abstraction, Sequences
Q2:Height
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
defheight(t): """Return the height of a tree. >>> t = tree(3, [tree(5, [tree(1)]), tree(2)]) >>> height(t) 2 >>> t = tree(3, [tree(1), tree(2, [tree(5, [tree(6)]), tree(1)])]) >>> height(t) 3 """ "*** YOUR CODE HERE ***" if is_leaf(t): return1 else: returnmax([height(b) for b in branches(t)]) #so cool
Q3:Maximum Path Sum
1 2 3 4 5 6 7 8 9 10 11 12
defmax_path_sum(t): """Return the maximum path sum of the tree. >>> t = tree(1, [tree(5, [tree(1), tree(3)]), tree(10)]) >>> max_path_sum(t) 11 """ "*** YOUR CODE HERE ***" if is_leaf(t): return label(t) else: returnmax([max_path_sum(b) for b in branches(t)])+label(t)
Q4:Find Path
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
deffind_path(t, x): """ >>> t = tree(2, [tree(7, [tree(3), tree(6, [tree(5), tree(11)])] ), tree(15)]) >>> find_path(t, 5) [2, 7, 6, 5] >>> find_path(t, 10) # returns None """ if x==label(t): return [label(t)] else: for b in branches(t): path=find_path(b,x) if path: result=[label(t)]+path return result
Q5:Map, Filter, Reduce
1 2 3 4 5 6 7 8 9 10
defmy_map(fn, seq): """Applies fn onto each element in seq and returns a list. >>> my_map(lambda x: x*x, [1, 2, 3]) [1, 4, 9] """ "*** YOUR CODE HERE ***" seq_new=[] for x in seq: seq_new.append(fn(x)) return seq_new
1 2 3 4 5 6 7 8 9 10 11
defmy_filter(pred, seq): """Keeps elements in seq only if they satisfy pred. >>> my_filter(lambda x: x % 2 == 0, [1, 2, 3, 4]) # new list has only even-valued elements [2, 4] """ "*** YOUR CODE HERE ***" seq_new=[] for x in seq: if pred(x): seq_new.append(x) return seq_new
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
defmy_reduce(combiner, seq): """Combines elements in seq using combiner. seq will have at least one element. >>> my_reduce(lambda x, y: x + y, [1, 2, 3, 4]) # 1 + 2 + 3 + 4 10 >>> my_reduce(lambda x, y: x * y, [1, 2, 3, 4]) # 1 * 2 * 3 * 4 24 >>> my_reduce(lambda x, y: x * y, [4]) 4 >>> my_reduce(lambda x, y: x + 2 * y, [1, 2, 3]) # (1 + 2 * 2) + 2 * 3 11 """ "*** YOUR CODE HERE ***" iflen(seq)==1: return seq[0] eliflen(seq)==2: return combiner(seq[0],seq[1]) else: return combiner(combiner(seq[0],seq[1]),my_reduce(combiner,seq[2:]))
Q6:Count palindromes
1 2 3 4 5 6 7 8
defcount_palindromes(L): """The number of palindromic words in the sequence of strings L (ignoring case). >>> count_palindromes(("Acme", "Madam", "Pivot", "Pip")) 2 """ returnlen(my_filter(lambda x:x.lower()==x[::-1].lower(),L))
Q7:Perfectly Balanced
似乎…有点问题
to be dubug
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
defsum_tree(t): """ Add all elements in a tree. >>> t = tree(4, [tree(2, [tree(3)]), tree(6)]) >>> sum_tree(t) 15 """ "*** YOUR CODE HERE ***" if is_leaf(t): return label(t) else: sum=label(t) for b in branches(t): sum+=sum_tree(b) returnsum
defbalanced(t): """ Checks if each branch has same sum of all elements and if each branch is balanced. >>> t = tree(1, [tree(3), tree(1, [tree(2)]), tree(1, [tree(1), tree(1)])]) >>> balanced(t) True >>> t = tree(1, [t, tree(1)]) >>> balanced(t) False >>> t = tree(1, [tree(4), tree(1, [tree(2), tree(1)]), tree(1, [tree(3)])]) >>> balanced(t) False """ "*** YOUR CODE HERE ***" store=[] for b in branches(t): store.append(sum_tree(b)) ifmax(store)==min(store): returnTrue else: returnFalse
defsum_tree(t): """ Add all elements in a tree. >>> t = tree(4, [tree(2, [tree(3)]), tree(6)]) >>> sum_tree(t) 15 """ "*** YOUR CODE HERE ***" if is_leaf(t): return label(t) else: sum=label(t) for b in branches(t): sum+=sum_tree(b) returnsum
Q8:Hailstone Tree
1
#orz,咕了
HW 4:Data Abstraction,Trees
Q2:Weights
1 2 3 4 5 6 7 8 9 10 11 12
defplanet(size): """Construct a planet of some size.""" assert size > 0 "*** YOUR CODE HERE ***" return ['planet',size]
defsize(w): """Select the size of a planet.""" assert is_planet(w), 'must call size on a planet' "*** YOUR CODE HERE ***" return w[1]
deftotals_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 >>> from construct_check import check >>> # checking for abstraction barrier violations by banning indexing >>> check(HW_SOURCE_FILE, 'totals_tree', ['Index']) True """ "*** YOUR CODE HERE ***" if is_planet(m): return tree(size(m)) else: assert is_mobile(m) return tree(total_weight(m),[totals_tree(end(left(m))),totals_tree(end(right(m)))])
defreplace_loki_at_leaf(t, lokis_replacement): """Returns a new tree where every leaf value equal to "loki" has been replaced with lokis_replacement. >>> yggdrasil = tree('odin', ... [tree('balder', ... [tree('loki'), ... tree('freya')]), ... tree('frigg', ... [tree('loki')]), ... tree('loki', ... [tree('sif'), ... tree('loki')]), ... tree('loki')]) >>> laerad = copy_tree(yggdrasil) # copy yggdrasil for testing purposes >>> print_tree(replace_loki_at_leaf(yggdrasil, 'freya')) odin balder freya freya frigg freya loki sif freya freya >>> laerad == yggdrasil # Make sure original tree is unmodified True """ "*** YOUR CODE HERE ***" if label(t)=='loki'and is_leaf(t): return tree(lokis_replacement) else: return tree(label(t),[replace_loki_at_leaf(b,lokis_replacement) for b in branches(t)])
ATTENTION: tree的结构为tree(label(t),branches=[]),所以可以直接用循环+递归:tree(label(t),[replace_loki_at_leaf(b,lokis_replacement) for b in branches(t)])
defhas_path(t, word): """Return whether there is a path in a tree where the entries along the path spell out a particular word. >>> greetings = tree('h', [tree('i'), ... tree('e', [tree('l', [tree('l', [tree('o')])]), ... tree('y')])]) >>> print_tree(greetings) h i e l l o y >>> has_path(greetings, 'h') True >>> has_path(greetings, 'i') False >>> has_path(greetings, 'hi') True >>> has_path(greetings, 'hello') True >>> has_path(greetings, 'hey') True >>> has_path(greetings, 'bye') False >>> has_path(greetings, 'hint') False """ assertlen(word) > 0, 'no path for empty word.' "*** YOUR CODE HERE ***" if label(t)==word andlen(word)==1: returnTrue elif label(t)==word[0]: for b in branches(t): if has_path(b,word[1:]): returnTrue returnFalse else: returnFalse
Q7:Preorder
optional
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
defpreorder(t): """Return a list of the entries in this tree in the order that they would be visited by a preorder traversal (see problem description). >>> numbers = tree(1, [tree(2), tree(3, [tree(4), tree(5)]), tree(6, [tree(7)])]) >>> preorder(numbers) [1, 2, 3, 4, 5, 6, 7] >>> preorder(tree(2, [tree(4, [tree(6)])])) [2, 4, 6] """ "*** YOUR CODE HERE ***" if is_leaf(t): return [label(t)] else: result=[label(t)] for b in branches(t): result+=preorder(b) #这里不能是=,如果赋值的话相当于最后result就等于最后那个分支加上去的值 return result
Q8:Interval Abstraction
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
definterval(a, b): """Construct an interval from a to b.""" assert a <= b, 'Lower bound cannot be greater than upper bound' return [a, b]
deflower_bound(x): """Return the lower bound of interval x.""" "*** YOUR CODE HERE ***" return x[0]
defupper_bound(x): """Return the upper bound of interval x.""" "*** YOUR CODE HERE ***" return x[1]
defmul_interval(x, y): """Return the interval that contains the product of any value in x and any value in y.""" p1 = lower_bound(x)*lower_bound(y) p2 = lower_bound(x)*upper_bound(y) p3 = upper_bound(x)*lower_bound(y) p4 = upper_bound(x)*upper_bound(y) return interval(min(p1, p2, p3, p4), max(p1, p2, p3, p4))
defsub_interval(x, y): """Return the interval that contains the difference between any value in x and any value in y.""" "*** YOUR CODE HERE ***" lower=lower_bound(x)-upper_bound(y) upper=upper_bound(x)-lower_bound(y) return interval(lower,upper)
defdiv_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 ***" assert lower_bound(y)>0or upper_bound(y)<0 reciprocal_y = interval(1 / upper_bound(y), 1 / lower_bound(y)) return mul_interval(x, reciprocal_y)
①提供的代码:
1 2 3 4 5 6 7 8
defmul_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)]
提供的代码会报错**’function’ object is not subscriptable**
The error “TypeError: ‘function’ object is not subscriptable” occurs when you try to access an item from a function. Functions cannot be indexed using square brackets.
即数据抽象要用其他函数去访问函数中的某个值,而不能直接用方括号索引函数
如果只改p1~p4的值,不改return,则会报错**’list’ object is not callable**
The Python “TypeError: ‘list’ object is not callable” occurs when we try to call a list as a function using parenthesis () . To solve the error, make sure to use square brackets when accessing a list at a specific index
defrepeated(t, k): """Return the first value in iterator T that appears K times in a row. Iterate through the items such that if the same iterator is passed into the function twice, it continues in the second call at the point it left off in the first. >>> s = iter([10, 9, 10, 9, 9, 10, 8, 8, 8, 7]) >>> repeated(s, 2) 9 >>> s2 = iter([10, 9, 10, 9, 9, 10, 8, 8, 8, 7]) >>> repeated(s2, 3) 8 >>> s = iter([3, 2, 2, 2, 1, 2, 1, 4, 4, 5, 5, 5]) >>> repeated(s, 3) 2 >>> repeated(s, 3) 5 >>> s2 = iter([4, 1, 6, 6, 7, 7, 8, 8, 2, 2, 2, 5]) >>> repeated(s2, 3) 2 """ assert k > 1 "*** YOUR CODE HERE ***" last_num,cnt=None,0 whileTrue: num=next(t) if last_num==Noneor num!=last_num: last_num,cnt=num,1 else: cnt+=1 if cnt==k: return num
defadd_this_many(x, el, s): """ Adds el to the end of s the number of times x occurs in s. >>> s = [1, 2, 4, 2, 1] >>> add_this_many(1, 5, s) >>> s [1, 2, 4, 2, 1, 5, 5] >>> add_this_many(2, 2, s) >>> s [1, 2, 4, 2, 1, 5, 5, 2, 2] """ "*** YOUR CODE HERE ***" i,count=0,0 while i<len(s): if x==s[i]: count+=1 i+=1 j=0 while j<count: s.append(el) j+=1 return
deffilter_iter(iterable, fn): """ >>> is_even = lambda x: x % 2 == 0 >>> list(filter_iter(range(5), is_even)) # a list of the values yielded from the call to filter_iter [0, 2, 4] >>> all_odd = (2*y-1 for y in range(5)) >>> list(filter_iter(all_odd, is_even)) [] >>> naturals = (n for n in range(1, 100)) >>> s = filter_iter(naturals, is_even) >>> next(s) 2 >>> next(s) 4 """ "*** YOUR CODE HERE ***" t=[] for b in iterable: if fn(b): t.append(b) returniter(t)
#用yield方法: deffilter_iter(iterable, fn): for b in iterable: if fn(b): yield b
defis_prime(n): """Returns True if n is a prime number and False otherwise. >>> is_prime(2) True >>> is_prime(16) False >>> is_prime(521) True """ defhelper(i): if i > (n ** 0.5): # Could replace with i == n returnTrue elif n % i == 0: returnFalse return helper(i + 1) return helper(2)
defprimes_gen(n): """Generates primes in decreasing order. >>> pg = primes_gen(7) >>> list(pg) [7, 5, 3, 2] """ if n<2: return if is_prime(n): yield n yieldfrom primes_gen(n-1)
defgen_perms(seq): """Generates all permutations of the given sequence. Each permutation is a list of the elements in SEQ in a different order. The permutations may be yielded in any order. >>> perms = gen_perms([100]) >>> type(perms) <class 'generator'> >>> next(perms) [100] >>> try: #this piece of code prints "No more permutations!" if calling next would cause an error ... next(perms) ... except StopIteration: ... print('No more permutations!') No more permutations! >>> sorted(gen_perms([1, 2, 3])) # Returns a sorted list containing elements of the generator [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]] >>> sorted(gen_perms((10, 20, 30))) [[10, 20, 30], [10, 30, 20], [20, 10, 30], [20, 30, 10], [30, 10, 20], [30, 20, 10]] >>> sorted(gen_perms("ab")) [['a', 'b'], ['b', 'a']] """ "*** YOUR CODE HERE ***" iftype(seq)!=list: seq=list(seq) iflen(seq)<=1: yield seq else: for perm in gen_perms(seq[1:]): for i inrange(len(seq)): yield perm[:i]+seq[:1]+perm[i:]
defpath_yielder(t, value): """Yields all possible paths from the root of t to a node with the label value 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(path_yielder(t1, 6)) [1, 2, 4, 6] >>> path_to_5 = path_yielder(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 = path_yielder(t2, 2) >>> sorted(list(path_to_2)) [[0, 2], [0, 2, 1, 2]] """ "*** YOUR CODE HERE ***" if label(t)==value: yield [value] for b in branches(t): for path in path_yielder(b,value): yield [label(t)]+path
Q3:Preorder
见hw04 Q7
Q4:Generate Preorder
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
defgenerate_preorder(t): """Yield the entries in this tree in the order that they would be visited by a preorder traversal (see problem description). >>> numbers = tree(1, [tree(2), tree(3, [tree(4), tree(5)]), tree(6, [tree(7)])]) >>> gen = generate_preorder(numbers) >>> next(gen) 1 >>> list(gen) [2, 3, 4, 5, 6, 7] """ "*** YOUR CODE HERE ***" yield label(t) for b in branches(t): yieldfrom generate_preorder(b)
defremainders_generator(m): """ Yields m generators. The ith yielded generator yields natural numbers whose remainder is i when divided by m. >>> import types >>> [isinstance(gen, types.GeneratorType) for gen in remainders_generator(5)] [True, True, True, True, True] >>> remainders_four = remainders_generator(4) >>> for i in range(4): ... print("First 3 natural numbers with remainder {0} when divided by 4:".format(i)) ... gen = next(remainders_four) ... for _ in range(3): ... print(next(gen)) First 3 natural numbers with remainder 0 when divided by 4: 4 8 12 First 3 natural numbers with remainder 1 when divided by 4: 1 5 9 First 3 natural numbers with remainder 2 when divided by 4: 2 6 10 First 3 natural numbers with remainder 3 when divided by 4: 3 7 11 """ "*** YOUR CODE HERE ***" defhelper(i): for x in naturals(): if x%m==i: yield x for j inrange(m): #这里是关键,否则会Timeout yield helper(j) """ 不用higher-order function也会报Timeout错误,怪 可能是没有用high-order function “封装”,使程序一直进行? def remainders_generator(m): for i in range(m): for x in naturals(): if x%m==i: yield x """
Lab 07:Object-Oriented Programming
Q2:Retirement
1 2 3 4 5 6 7 8 9
deftime_to_retire(self, amount): """Return the number of years until balance would grow to amount.""" assert self.balance > 0and amount > 0and self.interest > 0 "*** YOUR CODE HERE ***" i=1 whileTrue: if self.balance*(self.interest+1)**i>=amount: return i i+=1
classFreeChecking(Account): """A bank account that charges for withdrawals, but the first two are free! >>> ch = FreeChecking('Jack') >>> ch.balance = 20 >>> ch.withdraw(100) # First one's free 'Insufficient funds' >>> ch.withdraw(3) # And the second 17 >>> ch.balance 17 >>> ch.withdraw(3) # Ok, two free withdrawals is enough 13 >>> ch.withdraw(3) 9 >>> ch2 = FreeChecking('John') >>> ch2.balance = 10 >>> ch2.withdraw(3) # No fee 7 >>> ch.withdraw(3) # ch still charges a fee 5 >>> ch.withdraw(5) # Not enough to cover fee + withdraw 'Insufficient funds' """ withdraw_fee = 1 free_withdrawals = 2
"*** YOUR CODE HERE ***" defwithdraw(self,amount): if amount > self.balance: self.free_withdrawals-=1 return"Insufficient funds" if amount > self.max_withdrawal: self.free_withdrawals-=1 return"Can't withdraw that amount" if self.free_withdrawals>0: self.free_withdrawals-=1 self.balance = self.balance - amount else: self.balance=self.balance-amount-self.withdraw_fee if amount > self.balance: self.free_withdrawals-=1 return"Insufficient funds" if amount > self.max_withdrawal: self.free_withdrawals-=1 return"Can't withdraw that amount" return self.balance
classPlayer: def__init__(self, deck, name): """Initialize a Player object. A Player starts the game by drawing 5 cards from their deck. Each turn, a Player draws another card from the deck and chooses one to play. >>> test_card = Card('test', 100, 100) >>> test_deck = Deck([test_card.copy() for _ in range(6)]) >>> test_player = Player(test_deck, 'tester') >>> len(test_deck.cards) 1 >>> len(test_player.hand) 5 """ self.deck = deck self.name = name "*** YOUR CODE HERE ***" self.hand=[self.deck.draw() for _ inrange(5)]
defdraw(self): """Draw a card from the player's deck and add it to their hand. >>> test_card = Card('test', 100, 100) >>> test_deck = Deck([test_card.copy() for _ in range(6)]) >>> test_player = Player(test_deck, 'tester') >>> test_player.draw() >>> len(test_deck.cards) 0 >>> len(test_player.hand) 6 """ assertnot self.deck.is_empty(), 'Deck is empty!' "*** YOUR CODE HERE ***" self.hand.append(self.deck.draw())
defplay(self, card_index): """Remove and return a card from the player's hand at the given index. >>> from cards import * >>> test_player = Player(standard_deck, 'tester') >>> ta1, ta2 = TACard("ta_1", 300, 400), TACard("ta_2", 500, 600) >>> tutor1, tutor2 = TutorCard("t1", 200, 500), TutorCard("t2", 600, 400) >>> test_player.hand = [ta1, ta2, tutor1, tutor2] >>> test_player.play(0) is ta1 True >>> test_player.play(2) is tutor2 True >>> len(test_player.hand) 2 """ "*** YOUR CODE HERE ***" self.hand.pop(card_index)
defeffect(self, opponent_card, player, opponent): """ Discard the first 3 cards in the opponent's hand and have them draw the same number of cards from their deck. >>> from cards import * >>> player1, player2 = Player(player_deck, 'p1'), Player(opponent_deck, 'p2') >>> opponent_card = Card('other', 500, 500) >>> tutor_test = TutorCard('Tutor', 500, 500) >>> initial_deck_length = len(player2.deck.cards) >>> tutor_test.effect(opponent_card, player1, player2) p2 discarded and re-drew 3 cards! >>> len(player2.hand) 5 >>> len(player2.deck.cards) == initial_deck_length - 3 True """ "*** YOUR CODE HERE ***" # You should add your implementation above this. i,j=0,0 while i<3: opponent.hand.pop() i+=1 while j<3: opponent.hand.append(opponent.deck.draw()) j+=1 print('{} discarded and re-drew 3 cards!'.format(opponent.name))
defeffect(self, opponent_card, player, opponent): """ Adds the attack and defense of the opponent's card to all cards in the player's deck, then removes all cards in the opponent's deck that share an attack or defense stat with the opponent's card. >>> test_card = Card('card', 300, 300) >>> instructor_test = InstructorCard('Instructor', 500, 500) >>> opponent_card = test_card.copy() >>> test_deck = Deck([test_card.copy() for _ in range(8)]) >>> player1, player2 = Player(test_deck.copy(), 'p1'), Player(test_deck.copy(), 'p2') >>> instructor_test.effect(opponent_card, player1, player2) 3 cards were discarded from p2's deck! >>> [(card.attack, card.defense) for card in player1.deck.cards] [(600, 600), (600, 600), (600, 600)] >>> len(player2.deck.cards) 0 """ orig_opponent_deck_length = len(opponent.deck.cards) "*** YOUR CODE HERE ***" # You should add your implementation above this. for i_cards in player.deck.cards: i_cards.attack+=opponent_card.attack i_cards.defense+=opponent_card.defense for o_cards in opponent.deck.cards: if o_cards.attack==opponent_card.attack or o_cards.defense==opponent_card.defense: opponent.deck.cards.remove(o_cards)
discarded = orig_opponent_deck_length - len(opponent.deck.cards) if discarded: print('{} cards were discarded from {}\'s deck!'.format(discarded, opponent.name)) return
Project 03:Ants
Problem 2
Hint: Remember that when the __init__ method is called, the first parameter, self, is bound to the newly created object
Problem 8
好开心!!!尽管改了几次,但最终看到“20 test cases passed! No cases failed.”时巨兴奋
classPlace: """A Place holds insects and has an exit to another Place.""" is_hive = False
def__init__(self, name, exit=None): """Create a Place with the given NAME and EXIT. name -- A string; the name of this Place. exit -- The Place reached by exiting this Place (may be None). """ self.name = name self.exit = exit self.bees = [] # A list of Bees self.ant = None# An Ant self.entrance = None# A Place # Phase 1: Add an entrance to the exit # BEGIN Problem 2 "*** YOUR CODE HERE ***" if self.exit: exit.entrance=self # END Problem 2
defadd_insect(self, insect): """ Asks the insect to add itself to the current place. This method exists so it can be enhanced in subclasses. """ insect.add_to(self)
defremove_insect(self, insect): """ Asks the insect to remove itself from the current place. This method exists so it can be enhanced in subclasses. """ insect.remove_from(self)
def__str__(self): return self.name
classInsect: """An Insect, the base class of Ant and Bee, has health and a Place."""
damage = 0 is_waterproof=False # ADD CLASS ATTRIBUTES HERE
def__init__(self, health, place=None): """Create an Insect with a health amount and a starting PLACE.""" self.health = health self.place = place # set by Place.add_insect and Place.remove_insect
defreduce_health(self, amount): """Reduce health by AMOUNT, and remove the insect from its place if it has no health remaining. >>> test_insect = Insect(5) >>> test_insect.reduce_health(2) >>> test_insect.health 3 """ self.health -= amount if self.health <= 0: self.death_callback() self.place.remove_insect(self)
defaction(self, gamestate): """The action performed each turn. gamestate -- The GameState, used to access game state information. """
defdeath_callback(self): # overriden by the gui pass
defadd_to(self, place): """Add this Insect to the given Place By default just sets the place attribute, but this should be overriden in the subclasses to manipulate the relevant attributes of Place """ self.place = place
classAnt(Insect): """An Ant occupies a place and does work for the colony."""
implemented = False# Only implemented Ant classes should be instantiated food_cost = 0 is_container = False buffed=False # ADD CLASS ATTRIBUTES HERE
def__init__(self, health=1): """Create an Insect with a HEALTH quantity.""" super().__init__(health)
@classmethod defconstruct(cls, gamestate): """Create an Ant for a given GameState, or return None if not possible.""" if cls.food_cost > gamestate.food: print('Not enough food remains to place ' + cls.__name__) return return cls()
defcan_contain(self, other): returnFalse
defstore_ant(self, other): assertFalse, "{0} cannot contain an ant".format(self)
defremove_ant(self, other): assertFalse, "{0} cannot contain an ant".format(self)
defadd_to(self, place): if place.ant isNone: place.ant = self else: # BEGIN Problem 8 if place.ant.can_contain(self): #这个函数要不要改一下形式? place.ant.ant_contained=self elif self.can_contain(place.ant): self.ant_contained=place.ant place.ant=self #这里要不要把二者交换,也就是令self=place.ant? else: assert place.ant isNone, 'Two ants in {0}'.format(place) # END Problem 8 Insect.add_to(self, place)
defremove_from(self, place): if place.ant is self: place.ant = None elif place.ant isNone: assertFalse, '{0} is not in {1}'.format(self, place) else: place.ant.remove_ant(self) Insect.remove_from(self, place)
defbuff(self): """Double this ants's damage, if it has not already been buffed.""" # BEGIN Problem 12 "*** YOUR CODE HERE ***" ifnot self.buffed: self.damage*=2 self.buffed=True # END Problem 12
classHarvesterAnt(Ant): """HarvesterAnt produces 1 additional food per turn for the colony."""
name = 'Harvester' implemented = True # OVERRIDE CLASS ATTRIBUTES HERE food_cost=2 defaction(self, gamestate): """Produce 1 additional food for the colony. gamestate -- The GameState, used to access game state information. """ # BEGIN Problem 1 "*** YOUR CODE HERE ***" gamestate.food+=1 # END Problem 1
classThrowerAnt(Ant): """ThrowerAnt throws a leaf each turn at the nearest Bee in its range."""
name = 'Thrower' implemented = True damage = 1 max_range=3 min_range=5 # ADD/OVERRIDE CLASS ATTRIBUTES HERE food_cost=3 defnearest_bee(self): """Return the nearest Bee in a Place that is not the HIVE, connected to the ThrowerAnt's Place by following entrances. This method returns None if there is no such Bee (or none in range). """ # BEGIN Problem 3 and 4 current_place=self.place #Start from the current Place of the ThrowerAnt while current_place.entrance: #只要不是hive if current_place.bees: return random_bee(current_place.bees) current_place=current_place.entrance #感觉就是把题目的那几句话翻译出来 # END Problem 3 and 4
defthrow_at(self, target): """Throw a leaf at the TARGET Bee, reducing its health.""" if target isnotNone: target.reduce_health(self.damage)
defaction(self, gamestate): """Throw a leaf at the nearest Bee in range.""" self.throw_at(self.nearest_bee())
defrandom_bee(bees): """Return a random bee from a list of bees, or return None if bees is empty.""" assertisinstance(bees, list), "random_bee's argument should be a list but was a %s" % type(bees).__name__ if bees: return random.choice(bees)
############## # Extensions # ##############
classShortThrower(ThrowerAnt): """A ThrowerAnt that only throws leaves at Bees at most 3 places away."""
name = 'Short' food_cost = 2 # OVERRIDE CLASS ATTRIBUTES HERE # BEGIN Problem 4 implemented = True# Change to True to view in the GUI defnearest_bee(self): count=0 current_place=self.place while count<self.max_range and current_place.entrance: if current_place.bees: return random_bee(current_place.bees) current_place=current_place.entrance count+=1
# END Problem 4
classLongThrower(ThrowerAnt): """A ThrowerAnt that only throws leaves at Bees at least 5 places away."""
name = 'Long' food_cost = 2 # OVERRIDE CLASS ATTRIBUTES HERE # BEGIN Problem 4 implemented = True# Change to True to view in the GUI defnearest_bee(self): current_place=self.place while current_place.entrance.entrance.entrance.entrance.entrance: #妙在这里 if current_place.bees: return random_bee(current_place.bees) current_place=current_place.entrance
# END Problem 4
classFireAnt(Ant): """FireAnt cooks any Bee in its Place when it expires."""
name = 'Fire' damage = 3 food_cost = 5 # OVERRIDE CLASS ATTRIBUTES HERE # BEGIN Problem 5 implemented = True# Change to True to view in the GUI # END Problem 5
def__init__(self, health=3): """Create an Ant with a HEALTH quantity.""" super().__init__(health)
defreduce_health(self, amount): """Reduce health by AMOUNT, and remove the FireAnt from its place if it has no health remaining. Make sure to reduce the health of each bee in the current place, and apply the additional damage if the fire ant dies. """ # BEGIN Problem 5 "*** YOUR CODE HERE ***" current_place=self.place for bee in current_place.bees[:]: bee.reduce_health(amount) if amount>=self.health: #amount指蛰fireant的蜜蜂数量,此处指fireant的health为零 for bee in current_place.bees[:]: bee.reduce_health(self.damage) super().reduce_health(amount) #可以根据提示? else: super().reduce_health(amount) # END Problem 5
# BEGIN Problem 6 # The WallAnt class classWallAnt(Ant): name='Wall' food_cost=4 implemented=True def__init__(self, health=4): super().__init__(health) # END Problem 6
# BEGIN Problem 7 # The HungryAnt Class classHungryAnt(Ant): name='Hungry' implemented=True food_cost=4 chew_duration=3 def__init__(self,health=1): super().__init__(health) self.chew_countdown=0 defaction(self): if self.chew_countdown!=0: self.chew_countdown-=1 else: current_place=self.place iflen(current_place.bees)>0: self.chew_countdown=self.chew_duration bee=random_bee(current_place.bees) bee.reduce_health(bee.health) # END Problem 7
classContainerAnt(Ant): """ ContainerAnt can share a space with other ants by containing them. ant_contained: stores the ant it contains """ is_container = True
defcan_contain(self, other): # BEGIN Problem 8 "*** YOUR CODE HERE ***" ifnot other.is_container and self.ant_contained ==None: returnTrue # END Problem 8
defstore_ant(self, ant): # BEGIN Problem 8 "*** YOUR CODE HERE ***" self.ant_contained=ant # END Problem 8
defremove_ant(self, ant): if self.ant_contained isnot ant: assertFalse, "{} does not contain {}".format(self, ant) self.ant_contained = None
defremove_from(self, place): # Special handling for container ants (this is optional) if place.ant is self: # Container was removed. Contained ant should remain in the game place.ant = place.ant.ant_contained Insect.remove_from(self, place) else: # default to normal behavior Ant.remove_from(self, place)
defaction(self, gamestate): # BEGIN Problem 8 "*** YOUR CODE HERE ***" if self.ant_contained!=None: self.ant_contained.action(gamestate) # END Problem 8
classBodyguardAnt(ContainerAnt): """BodyguardAnt provides protection to other Ants."""
name = 'Bodyguard' food_cost = 4 # OVERRIDE CLASS ATTRIBUTES HERE # BEGIN Problem 8 implemented = True# Change to True to view in the GUI def__init__(self,health=2): super().__init__(health) # END Problem 8
# BEGIN Problem 9 # The TankAnt class classTankAnt(ContainerAnt): name='Tank' food_cost=6 damage=1 implemented=True def__init__(self,health=2): super().__init__(health) defaction(self,gamestate): current_place=self.place if self.ant_contained!=None: self.ant_contained.action(gamestate) for bee in current_place.bees[:]: bee.reduce_health(self.damage) # END Problem 9
classWater(Place): """Water is a place that can only hold waterproof insects."""
defadd_insect(self, insect): """Add an Insect to this place. If the insect is not waterproof, reduce its health to 0.""" # BEGIN Problem 10 "*** YOUR CODE HERE ***" super().add_insect(insect) ifnot insect.is_waterproof: insect.reduce_health(insect.health) # END Problem 10
# BEGIN Problem 11 # The ScubaThrower class classScubaThrower(ThrowerAnt): food_cost=6 is_waterproof=True name='Scuba' implemented=True
# END Problem 11
# BEGIN Problem 12
classQueenAnt(ScubaThrower): # You should change this line # END Problem 12 """The Queen of the colony. The game is over if a bee enters her place."""
name = 'Queen' food_cost = 7 is_queenant=True # OVERRIDE CLASS ATTRIBUTES HERE # BEGIN Problem 12 implemented = True# Change to True to view in the GUI # END Problem 12
@classmethod defconstruct(cls, gamestate): #有一定参考 """ Returns a new instance of the Ant class if it is possible to construct, or returns None otherwise. Remember to call the construct() method of the superclass! """ # BEGIN Problem 12 "*** YOUR CODE HERE ***" cls.is_queenant=QueenAnt.is_queenant if cls.food_cost > gamestate.food: print('Not enough food remains to place ' + cls.__name__) return elif cls.is_queenant: QueenAnt.is_queenant=False returnsuper().construct(gamestate) else: returnNone # END Problem 12
defaction(self, gamestate): #有一定参考 """A queen ant throws a leaf, but also doubles the damage of ants in her tunnel. """ # BEGIN Problem 12 "*** YOUR CODE HERE ***" #if not self.is_queenant: #self.reduce_health(self.health) #else: super().action(gamestate) behind=self.place.exit while behind: if behind.ant!=None: ifnot behind.ant.buffed: behind.ant.buff() if behind.ant.is_container and behind.ant.ant_contained: ifnot behind.ant.ant_contained.buffed: behind.ant.ant_contained.buff() behind=behind.exit
# END Problem 12
defreduce_health(self, amount): """Reduce health by AMOUNT, and if the QueenAnt has no health remaining, signal the end of the game. """ # BEGIN Problem 12 "*** YOUR CODE HERE ***" current_place=self.place for bee in current_place.bees[:]: bee.reduce_health(amount) if amount>=self.health: ants_lose() defremove_from(self,place): ''' if place.ant is self: return elif place.ant is None: assert False, '{0} is not in {1}'.format(self, place) else: place.ant.remove_ant(self) Insect.remove_from(self, place) ''' None#疑惑,为什么不能像上面那样写 # END Problem 12
classKeyboard: """A Keyboard takes in an arbitrary amount of buttons, and has a dictionary of positions as keys, and values as Buttons. >>> b1 = Button(0, "H") >>> b2 = Button(1, "I") >>> k = Keyboard(b1, b2) >>> k.buttons[0].key #dictionary的key 'H' >>> k.press(1) 'I' >>> k.press(2) # No button at this position '' >>> k.typing([0, 1]) 'HI' >>> k.typing([1, 0]) 'IH' >>> b1.times_pressed 2 >>> b2.times_pressed 3 """ def__init__(self, *args): self.buttons={} #dictionary for args in args: #为什么这个要这样写,悲 self.buttons[args.pos]=args
defpress(self, info): """Takes in a position of the button pressed, and returns that button's output.""" if info<=len(self.buttons): return self.buttons[info].key else: return''
deftyping(self, typing_input): """Takes in a list of positions of buttons pressed, and returns the total output.""" output='' for word in typing_input: output+=typing_input[index(word)] return output
def__init__(self, name, owner, lives=9): "*** YOUR CODE HERE ***" self.name=name self.owner=owner self.lives=lives
deftalk(self): """Print out a cat's greeting. >>> Cat('Thomas', 'Tammy').talk() Thomas says meow! """ "*** YOUR CODE HERE ***" print('{} says meow!'.format(self.name))
deflose_life(self): """Decrements a cat's life by 1. When lives reaches zero, is_alive becomes False. If this is called after lives has reached zero, print 'This cat has no more lives to lose.' """ "*** YOUR CODE HERE ***" if self.lives==0: print('This cat has no more lives to lose.')
Q4:NoisyCat
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
def__init__(self, name, owner, lives=9): # Is this method necessary? Why or why not? "*** YOUR CODE HERE ***" self.name=name self.owner=owner self.lives=lives
deftalk(self): """Talks twice as much as a regular cat. >>> NoisyCat('Magic', 'James').talk() Magic says meow! Magic says meow! """ "*** YOUR CODE HERE ***" for i inrange(2): print('{} says meow!'.format(self.name))
classCat(Pet): def__init__(self, name, owner, lives=9): "*** YOUR CODE HERE ***" self.name=name self.owner=owner self.lives=lives
# Insert other previously defined methods here
@classmethod defadopt_random_cat(cls, owner): """ Returns a new instance of a Cat with the given owner, a randomly chosen name and a random number of lives. >>> randcat = Cat.adopt_random_cat("Ifeoma") >>> isinstance(randcat, Cat) True >>> randcat.owner 'Ifeoma' """ cls.name=random.choice[] #这个函数用的不对 cls.lives=random.randint(1,10) return cls(name, owner, lives)
classVendingMachine: """A vending machine that vends some product for some price. >>> v = VendingMachine('candy', 10) >>> v.vend() 'Nothing left to vend. Please restock.' >>> v.add_funds(15) 'Nothing left to vend. Please restock. Here is your $15.' >>> v.restock(2) 'Current candy stock: 2' >>> v.vend() 'You must add $10 more funds.' >>> v.add_funds(7) 'Current balance: $7' >>> v.vend() 'You must add $3 more funds.' >>> v.add_funds(5) 'Current balance: $12' >>> v.vend() 'Here is your candy and $2 change.' >>> v.add_funds(10) 'Current balance: $10' >>> v.vend() 'Here is your candy.' >>> v.add_funds(15) 'Nothing left to vend. Please restock. Here is your $15.' >>> w = VendingMachine('soda', 2) >>> w.restock(3) 'Current soda stock: 3' >>> w.restock(3) 'Current soda stock: 6' >>> w.add_funds(2) 'Current balance: $2' >>> w.vend() 'Here is your soda.' """ "*** YOUR CODE HERE ***" def__init__(self,name,price): self.name=name self.price=price self.stock=0 self.balance=0 defvend(self): if self.stock<=0: print(f"'Nothing left to vend. Please restock.'") else: if self.balance<self.price: print(f"'You must add ${self.price-self.balance} more funds.'") elif self.balance>self.price: print(f"'Here is your {self.name} and ${self.balance-self.price} change.'") self.balance=0 self.stock-=1 else: print(f"'Here is your {self.name}.'") self.balance=0 self.stock-=1 return
defadd_funds(self,funds): if self.stock<=0: print(f"'Nothing left to vend. Please restock. Here is your ${funds}.'") else: self.balance+=funds print(f"'Current balance: ${self.balance}'") return
classMint: """A mint creates coins by stamping on years. The update method sets the mint's stamp to Mint.present_year. >>> mint = Mint() >>> mint.year 2021 >>> dime = mint.create(Dime) >>> dime.year 2021 >>> Mint.present_year = 2101 # Time passes >>> nickel = mint.create(Nickel) >>> nickel.year # The mint has not updated its stamp yet 2021 >>> nickel.worth() # 5 cents + (80 - 50 years) 35 >>> mint.update() # The mint's year is updated to 2101 >>> Mint.present_year = 2176 # More time passes >>> mint.create(Dime).worth() # 10 cents + (75 - 50 years) 35 >>> Mint().create(Dime).worth() # A new mint has the current year 10 >>> dime.worth() # 10 cents + (155 - 50 years) 115 >>> Dime.cents = 20 # Upgrade all dimes! >>> dime.worth() # 20 cents + (155 - 50 years) 125 """ present_year = 2021
def__init__(self): self.update()
defcreate(self, kind): "*** YOUR CODE HERE ***" return kind(self.year)
defupdate(self): "*** YOUR CODE HERE ***" self.year=Mint.present_year
classCoin: def__init__(self, year): self.year = year
defworth(self): "*** YOUR CODE HERE ***" return self.cents+max(0,Mint.present_year-self.year-50)
defstore_digits(n): """Stores the digits of a positive number n in a linked list. >>> s = store_digits(1) >>> s Link(1) >>> store_digits(2345) Link(2, Link(3, Link(4, Link(5)))) >>> store_digits(876) Link(8, Link(7, Link(6))) >>> # a check for restricted functions >>> import inspect, re >>> cleaned = re.sub(r"#.*\\n", '', re.sub(r'"{3}[\s\S]*?"{3}', '', inspect.getsource(store_digits))) >>> print("Do not use str or reversed!") if any([r in cleaned for r in ["str", "reversed"]]) else None >>> link1 = Link(3, Link(Link(4), Link(5, Link(6)))) """ "*** YOUR CODE HERE ***" res=Link.empty while n>0: rem=Link(n%10) #这里一定要是Link,不能是单独的数字 rem.rest=res res=rem n=n//10 return rem
defdeep_map_mut(fn, link): """Mutates a deep link by replacing each item found with the result of calling fn on the item. Does NOT create new Links (so no use of Link's constructor) Does not return the modified Link object. >>> link1 = Link(3, Link(Link(4), Link(5, Link(6)))) >>> # Disallow the use of making new Links before calling deep_map_mut >>> Link.__init__, hold = lambda *args: print("Do not create any new Links."), Link.__init__ >>> try: ... deep_map_mut(lambda x: x * x, link1) ... finally: ... Link.__init__ = hold >>> print(link1) <9 <16> 25 36> """ "*** YOUR CODE HERE ***" if link is Link.empty: #不能忘了link为empty的情况,否则递归无法完成 return else: ifisinstance(link.first,Link): deep_map_mut(fn,link.first) else: link.first=fn(link.first) deep_map_mut(fn,link.rest)
deftwo_list(vals, amounts): """ Returns a linked list according to the two lists that were passed in. Assume vals and amounts are the same size. Elements in vals represent the value, and the corresponding element in amounts represents the number of this value desired in the final linked list. Assume all elements in amounts are greater than 0. Assume both lists have at least one element. >>> a = [1, 3, 2] >>> b = [1, 1, 1] >>> c = two_list(a, b) >>> c Link(1, Link(3, Link(2))) >>> a = [1, 3, 2] >>> b = [2, 2, 1] >>> c = two_list(a, b) >>> c Link(1, Link(1, Link(3, Link(3, Link(2))))) """ "*** YOUR CODE HERE ***" vals.reverse() amounts.reverse() res=Link.empty for i inrange(len(vals)): for j inrange(amounts[i]): res=Link(vals[i],res) return res
Lab 08:Linked Lists, Mutable Trees
Q2:Convert Link
简单的recursive
1 2 3 4 5 6 7 8 9 10 11 12 13 14
defconvert_link(link): """Takes a linked list and returns a Python list with the same elements. >>> link = Link(1, Link(2, Link(3, Link(4)))) >>> convert_link(link) [1, 2, 3, 4] >>> convert_link(Link.empty) [] """ "*** YOUR CODE HERE ***" if link==Link.empty: return [] else: return [link.first]+convert_link(link.rest)
Q4:Square
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
deflabel_squarer(t): """Mutates a Tree t by squaring all its elements. >>> t = Tree(1, [Tree(3, [Tree(5)]), Tree(7)]) >>> label_squarer(t) >>> t Tree(1, [Tree(9, [Tree(25)]), Tree(49)]) """ "*** YOUR CODE HERE ***" #if t.is_leaf(): #t.label=t.label**2 #else: t.label=t.label**2 for b in t.branches: b=label_squarer(b) #return t
Q5:Cumulative Mul
1 2 3 4 5 6 7 8 9 10 11 12 13
defcumulative_mul(t): """Mutates t so that each node's label becomes the product of all labels in the corresponding subtree rooted at t. >>> t = Tree(1, [Tree(3, [Tree(5)]), Tree(7)]) >>> cumulative_mul(t) >>> t Tree(105, [Tree(15, [Tree(5)]), Tree(7)]) """ "*** YOUR CODE HERE ***" for b in t.branches: cumulative_mul(b) t.label*=b.label
Q6:Add Leaves
抄的别人的…
1 2 3 4 5 6 7 8 9 10 11
defadd_d_leaves(t, v): defhelper(t,v,depth): if t.is_leaf(): for i inrange(depth): t.branches.append(v) return for b in t.branches: helper(b,v,depth+1) for i inrange(depth): t.branches.append(Tree(v)) helper(t,v,0)
Disc 08:Linked Lists, Trees
均未跑版
Q3:Sum Nums
1 2 3 4 5
defsum_nums(s): if s.rest.empty: return s.first else: return s.first+sum_nums(s.rest)
defmultiply_lnks(lst_of_lnks): """ >>> a = Link(2, Link(3, Link(5))) >>> b = Link(6, Link(4, Link(2))) >>> c = Link(4, Link(1, Link(0, Link(2)))) >>> p = multiply_lnks([a, b, c]) >>> p.first 48 >>> p.rest.first 12 >>> p.rest.rest.rest is Link.empty True """ # Implementation Note: you might not need all lines in this skeleton code res = Link.empty for link in lst_of_lnks: if link.rest is Link.empty: res.rest=Link.empty link=link.rest res.first*=link.first nultiply_lnks(lst_of_lnks) return res
Q5:Flip Two
1 2 3 4 5 6 7 8 9
defflip_two(s): if s.rest.empty: return s else: store=s.first s.first=s.rest.first s.rest.first=store s.rest.rest=flip_two(s.rest.rest) return s
Q6:Make Even
1 2 3 4 5
defmake_even(t): if t.label%2==1: t.label+=1 for b in t.branches: b=make_even(b)
Q7:Leaves
1 2 3 4 5 6 7 8
defleaves(t): if t.is_leaf: return [t.label] else: res=[t.label] for b in t.branches: res.append(leaves(b)) return res
definsert_into_all(item, nested_list): """Return a new list consisting of all the lists in nested_list, but with item added to the front of each. You can assume that nested_list is a list of lists. >>> nl = [[], [1, 2], [3]] >>> insert_into_all(0, nl) [[0], [0, 1, 2], [0, 3]] """ "*** YOUR CODE HERE ***" forlistin nested_list: list.insert(0,item) return nested_list
defsubseqs(s): """Return a nested list (a list of lists) of all subsequences of S. The subsequences can appear in any order. You can assume S is a list. >>> seqs = subseqs([1, 2, 3]) >>> sorted(seqs) [[], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3], [3]] >>> subseqs([]) [[]] """ if s==[]: return [[]] else: res=insert_into_all(s[0],subseqs(s[1:])) return res+subseqs(s[1:])
defnon_decrease_subseqs(s): """Assuming that S is a list, return a nested list of all subsequences of S (a list of lists) for which the elements of the subsequence are strictly nondecreasing. The subsequences can appear in any order. >>> seqs = non_decrease_subseqs([1, 3, 2]) >>> sorted(seqs) [[], [1], [1, 2], [1, 3], [2], [3]] >>> non_decrease_subseqs([]) [[]] >>> seqs2 = non_decrease_subseqs([1, 1, 2]) >>> sorted(seqs2) [[], [1], [1], [1, 1], [1, 1, 2], [1, 2], [1, 2], [2]] """ defsubseq_helper(s, prev): ifnot s: return [[]] elif s[0] < prev: return subseq_helper(s[1:],prev) else: a = subseq_helper(s[1:],s[0]) b = subseq_helper(s[1:],prev) return insert_into_all(s[0], a) + b return subseq_helper(s, 0)
class Account: """A bank account that allows deposits and withdrawals. It tracks the current account balance and a transaction history of deposits and withdrawals.
>>> eric_account = Account('Eric') >>> eric_account.deposit(1000000) # depositing paycheck for the week 1000000 >>> eric_account.transactions [('deposit', 1000000)] >>> eric_account.withdraw(100) # make a withdrawal to buy dinner 999900 >>> eric_account.transactions [('deposit', 1000000), ('withdraw', 100)] >>> print(eric_account) #call to __str__ Eric's Balance: $999900 >>> eric_account.deposit(10) 999910 >>> eric_account #call to __repr__ Accountholder: Eric, Deposits: 2, Withdraws: 1 """
interest = 0.02
def __init__(self, account_holder): self.balance = 0 self.holder = account_holder "*** YOUR CODE HERE ***" self.deposits=0 self.withdraws=0 self.transactions=[]
def deposit(self, amount): """Increase the account balance by amount, add the deposit to the transaction history, and return the new balance. """ "*** YOUR CODE HERE ***" self.balance+=amount self.deposits+=1 self.transactions.append(('deposit', amount)) return self.balance
def withdraw(self, amount): """Decrease the account balance by amount, add the withdraw to the transaction history, and return the new balance. """ "*** YOUR CODE HERE ***" self.balance-=amount self.withdraws+=1 self.transactions.append(('withdraw', amount)) return self.balance
def __str__(self): "*** YOUR CODE HERE ***" return f'{self.holder}\'s Balance: ${self.balance}'
def __repr__(self): "*** YOUR CODE HERE ***" return f'Accountholder: {self.holder}, Deposits: {self.deposits}, Withdraws: {self.withdraws}'
deftrade(first, second): """Exchange the smallest prefixes of first and second that have equal sum. >>> a = [1, 1, 3, 2, 1, 1, 4] >>> b = [4, 3, 2, 7] >>> trade(a, b) # Trades 1+1+3+2=7 for 4+3=7 'Deal!' >>> a [4, 3, 1, 1, 4] >>> b [1, 1, 3, 2, 2, 7] >>> c = [3, 3, 2, 4, 1] >>> trade(b, c) 'No deal!' >>> b [1, 1, 3, 2, 2, 7] >>> c [3, 3, 2, 4, 1] >>> trade(a, c) 'Deal!' >>> a [3, 3, 2, 1, 4] >>> b [1, 1, 3, 2, 2, 7] >>> c [4, 3, 1, 4, 1] >>> d = [1, 1] >>> e = [2] >>> trade(d, e) 'Deal!' >>> d [2] >>> e [1, 1] """ m, n = 1, 1
equal_prefix = lambda: sum(first[:m])==sum(second[:n]) while m<=len(first) and n<=len(second) andsum(first[:m])!=sum(second[:n]): ifsum(first[:m])<sum(second[:n]): m += 1 else: n += 1
defcard(n): """Return the playing card numeral as a string for a positive n <= 13.""" asserttype(n) == intand n > 0and n <= 13, "Bad card n" specials = {1: 'A', 11: 'J', 12: 'Q', 13: 'K'} return specials.get(n, str(n))
defshuffle(cards): """Return a shuffled list that interleaves the two halves of cards. >>> shuffle(range(6)) [0, 3, 1, 4, 2, 5] >>> suits = ['H', 'D', 'S', 'C'] >>> cards = [card(n) + suit for n in range(1,14) for suit in suits] >>> cards[:12] ['AH', 'AD', 'AS', 'AC', '2H', '2D', '2S', '2C', '3H', '3D', '3S', '3C'] >>> cards[26:30] ['7S', '7C', '8H', '8D'] >>> shuffle(cards)[:12] ['AH', '7S', 'AD', '7C', 'AS', '8H', 'AC', '8D', '2H', '8S', '2D', '8C'] >>> shuffle(shuffle(cards))[:12] ['AH', '4D', '7S', '10C', 'AD', '4S', '7C', 'JH', 'AS', '4C', '8H', 'JD'] >>> cards[:12] # Should not be changed ['AH', 'AD', 'AS', 'AC', '2H', '2D', '2S', '2C', '3H', '3D', '3S', '3C'] """ assertlen(cards) % 2 == 0, 'len(cards) must be even' half = len(cards)//2 shuffled = [] for i inrange(half): shuffled.append(cards[i]) shuffled.append(cards[i+half]) return shuffled
definsert(link, value, index): """Insert a value into a Link at the given index. >>> link = Link(1, Link(2, Link(3))) >>> print(link) <1 2 3> >>> other_link = link >>> insert(link, 9001, 0) >>> print(link) <9001 1 2 3> >>> link is other_link # Make sure you are using mutation! Don't create a new linked list. True >>> insert(link, 100, 2) >>> print(link) <9001 1 100 2 3> >>> insert(link, 4, 5) Traceback (most recent call last): ... IndexError: Out of bounds! """ "*** YOUR CODE HERE ***" sto=link index_=0 while sto isnot Link.empty: if index_==index: current_link=Link(sto.first,sto.rest) sto.first=value sto.rest=current_link return index_+=1 sto=sto.rest raise IndexError('Out of bounds!')
defpop_first(self): """Remove the next item from self and return it. If self has exhausted its source, returns None.""" # BEGIN PROBLEM 1 current=self.current() self.index+=1 return current # END PROBLEM 1
defcurrent(self): """Return the current element, or None if none exists.""" whilenot self.more_on_line(): self.index=0 try: # BEGIN PROBLEM 1 self.current_line=next(self.source) # END PROBLEM 1 except StopIteration: self.current_line = () returnNone return self.current_line[self.index]
defscheme_read(src): """Read the next expression from SRC, a Buffer of tokens. >>> scheme_read(Buffer(tokenize_lines(['nil']))) nil >>> scheme_read(Buffer(tokenize_lines(['1']))) 1 >>> scheme_read(Buffer(tokenize_lines(['true']))) True >>> scheme_read(Buffer(tokenize_lines(['(+ 1 2)']))) Pair('+', Pair(1, Pair(2, nil))) """ if src.current() isNone: raise EOFError val = src.pop_first() # Get and remove the first token if val == 'nil': # BEGIN PROBLEM 2 "*** YOUR CODE HERE ***" return nil # END PROBLEM 2 elif val == '(': # BEGIN PROBLEM 2 "*** YOUR CODE HERE ***" return read_tail(src) # END PROBLEM 2 elif val == "'": # BEGIN PROBLEM 3 "*** YOUR CODE HERE ***" return Pair('quote', Pair(scheme_read(src), nil)) # END PROBLEM 3 elif val notin DELIMITERS: return val else: raise SyntaxError('unexpected token: {0}'.format(val))
defread_tail(src): """Return the remainder of a list in SRC, starting before an element or ). >>> read_tail(Buffer(tokenize_lines([')']))) nil >>> read_tail(Buffer(tokenize_lines(['2 3)']))) Pair(2, Pair(3, nil)) """ try: if src.current() isNone: raise SyntaxError('unexpected end of file') elif src.current() == ')': # BEGIN PROBLEM 2 "*** YOUR CODE HERE ***" src.pop_first() return nil # END PROBLEM 2 else: # BEGIN PROBLEM 2 "*** YOUR CODE HERE ***" return Pair(scheme_read(src), read_tail(src)) # END PROBLEM 2 except EOFError: raise SyntaxError('unexpected end of file')
Disc 11:Interpreters
Q2:New Procedure
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
defcalc_eval(exp): ifisinstance(exp, Pair): # Call expressions return calc_apply(calc_eval(exp.first), exp.rest.map(calc_eval)) elif exp in OPERATORS: # Names return OPERATORS[exp] else: # Numbers return exp deffloor_div(expr): "*** YOUR CODE HERE ***" dividend=expr.first expr=expr.rest while expr.rest!=nil: divisor=expr.first dividend//=divisor expr=expr.rest return dividend # Assume OPERATORS['//'] = floor_div is added for you in the code
defcalc_eval(exp): ifisinstance(exp, Pair): if expr.first=='and': # and expressions return eval_and(exp.rest) else: # Call expressions return calc_apply(calc_eval(exp.first), exp.rest.map(calc_eval)) elif exp in OPERATORS: # Names return OPERATORS[exp] else: # Numbers return exp
defeval_and(operands): "*** YOUR CODE HERE ***" ope=operands jud=True while ope!=nil: jud=calc_eval(ope.first) if jud==False: returnFalse ope=ope.rest return jud
bindings = {} defcalc_eval(exp): ifisinstance(exp, Pair): if exp.first=='and': # and expressions[paste your answer from the earlier] return eval_and(exp.rest) elif exp.first=='define': # define expressions return eval_define(exp.rest)
else: # Call expressions return calc_apply(calc_eval(exp.first), exp.rest.map(calc_eval)) elif exp in bindings: # Looking up variables "*** YOUR CODE HERE ***" return bindings[exp] elif exp in OPERATORS: # Looking up procedures return OPERATORS[exp] else: # Numbers return exp
defeval_define(expr): "*** YOUR CODE HERE ***" bindings[expr.first]=expr.rest.first return expr.first
defroman_numerals(text): """ Finds any string of letters that could be a Roman numeral (made up of the letters I, V, X, L, C, D, M). >>> roman_numerals("Sir Richard IIV, can you tell Richard VI that Richard IV is on the phone?") ['IIV', 'VI', 'IV'] >>> roman_numerals("My TODOs: I. Groceries II. Learn how to count in Roman IV. Profit") ['I', 'II', 'IV'] >>> roman_numerals("I. Act 1 II. Act 2 III. Act 3 IV. Act 4 V. Act 5") ['I', 'II', 'III', 'IV', 'V'] >>> roman_numerals("Let's play Civ VII") ['VII'] >>> roman_numerals("i love vi so much more than emacs.") [] >>> roman_numerals("she loves ALL editors equally.") [] """ return re.findall(r'\b([IVXLCDM]+)\b', text)
Q3:CS Classes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
defcs_classes(post): """ Returns strings that look like a Berkeley CS class, starting with "CS", followed by a number, optionally ending with A, B, or C and potentially with a space between "CS" and the number. Case insensitive. >>> cs_classes("Is it unreasonable to take CS61A, CS61B, CS70, and EE16A in the summer?") True >>> cs_classes("how do I become a TA for cs61a? that job sounds so fun") True >>> cs_classes("Can I take ECON101 as a CS major?") False >>> cs_classes("Should I do the lab lites or regular labs in EE16A?") False >>> cs_classes("What are some good CS upper division courses? I was thinking about CS 161 or CS 169a") True """ returnbool(re.search('[Cc][Ss][0-9]+[ABCabc]*', post)) orbool(re.search(r'[Cc][Ss]\s[0-9]+[ABCabc]*', post))
Q4:Time for Times
根据别人的提示去看了题目给的提示(没办法,英语不太好
(?:...), 表示我们想匹配但是不把 () 里的结果保存下来返回.
(? : …)?后面的那个问号表示可选择性
1 2 3 4 5 6 7 8 9 10 11 12
defmatch_time(text): """ >>> match_time("At 05:24AM, I had sesame bagels with cream cheese before my coffee at 7:23.") ['05:24AM', '7:23'] >>> match_time("At 23:59 I was sound asleep as the time turned to 00:00.") ['23:59', '00:00'] >>> match_time("Mix water in a 1:2 ratio with chicken stock.") [] >>> match_time("At 2:00 I pinged 127.0.0.1:80.") ['2:00'] """ return re.findall(r'(?:[01]?[0-9]|2[0-3]):[0-5][0-9](?:AM)?', text)
Q5:Most Common Area Code
区号:
十位电话号码的前三位
可能会用空格括起来,可能会与后面的数字有空格
1 2 3 4 5 6 7 8 9 10 11 12 13 14
defarea_codes(text): """ Finds all phone numbers in text and captures the area code. Phone numbers have 10 digits total and may have parentheses around the area code, and hyphens or spaces after the third and sixth digits. >>> area_codes('(111) 111 1111, 1234567890 and 123 345 6789 should be matched.') ['111', '123', '123'] >>> area_codes("1234567890 should, but 54321 and 654 456 78901 should not match") ['123'] >>> area_codes("no matches for 12 3456 7890 or 09876-54321") [] """ return re.findall(r'(?:\()?(\d{3})(?:\))?(?:\s|-)?\d{3}(?:\s|-)?\d{4}\b', text)
#下面这个求最常见的区号方法比较常规 defmost_common_code(text): """ Takes in an input string which contains at least one phone number (and may contain more) and returns the most common area code among all phone numbers in the input. If there are multiple area codes with the same frequency, return the first one that appears in the input text. >>> most_common_code('(501) 333 3333') '501' >>> input_text = ''' ... (123) 000 1234 and 12454, 098-123-0941, 123 451 0951 and 410-501-3021 has ... some phone numbers. ''' >>> most_common_code(input_text) '123' """ "*** YOUR CODE HERE ***" mylist=area_codes(text) mycount=0 max=0 mycode='' for code in mylist: mycount=mylist.count(code) if mycount>max: max=mycount mycode=code return mycode
注意list.count的使用
list.count(x)
Return the number of times x appears in the list.
Project 4:Scheme
Problem 1
把题目说的三种情况都写出来就可以了,注意第二种情况是调用lookup函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
defdefine(self, symbol, value): """Define Scheme SYMBOL to have VALUE.""" # BEGIN PROBLEM 1 "*** YOUR CODE HERE ***" self.bindings[symbol]=value # END PROBLEM 1
deflookup(self, symbol): """Return the value bound to SYMBOL. Errors if SYMBOL is not found.""" # BEGIN PROBLEM 1 "*** YOUR CODE HERE ***" if symbol in self.bindings: return self.bindings[symbol] # END PROBLEM 1 elif self.parent!=None: return self.parent.lookup(symbol) else: raise SchemeError('unknown identifier: {0}'.format(symbol))
Problem 2
可以记住把link化成list的方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
ifisinstance(procedure, BuiltinProcedure): # BEGIN PROBLEM 2 "*** YOUR CODE HERE ***" #第一步:把args转化为list args_list=[] while args: args_list.append(args.first) args=args.rest if procedure.expect_env: args_list.append(env) try: return procedure.py_func(*args_list) except TypeError: raise SchemeError('incorrect number of arguments')
一遍过的感觉真爽
Problem 3
1 2 3 4 5 6 7 8 9 10 11 12 13
# All non-atomic expressions are lists (combinations) ifnot scheme_listp(expr): raise SchemeError('malformed list: {0}'.format(repl_str(expr))) first, rest = expr.first, expr.rest if scheme_symbolp(first) and first in scheme_forms.SPECIAL_FORMS: return scheme_forms.SPECIAL_FORMS[first](rest, env) else: # BEGIN PROBLEM 3 "*** YOUR CODE HERE ***" operator=scheme_eval(first,env) operands=rest.map(lambda x:scheme_eval(x,env)) return scheme_apply(operator,operands,env) # END PROBLEM 3
Problem 4
1 2 3 4 5 6 7 8
if scheme_symbolp(signature): # assigning a name to a value e.g. (define x (+ 1 2)) validate_form(expressions, 2, 2) # Checks that expressions is a list of length exactly 2 # BEGIN PROBLEM 4 "*** YOUR CODE HERE ***" env.define(signature,scheme_eval(expressions.rest.first,env)) return signature # END PROBLEM 4
Problem 5
注意expressions的结构:
Pair(A, nil)
A is the quoted expression
1 2 3 4 5 6 7 8 9 10 11 12
defdo_quote_form(expressions, env): """Evaluate a quote form. >>> env = create_global_frame() >>> do_quote_form(read_line("((+ x 2))"), env) # evaluating (quote (+ x 2)) Pair('+', Pair('x', Pair(2, nil))) """ validate_form(expressions, 1, 1) # BEGIN PROBLEM 5 "*** YOUR CODE HERE ***" return expressions.first # END PROBLEM 5
defeval_all(expressions, env): """Evaluate each expression in the Scheme list EXPRESSIONS in Frame ENV (the current environment) and return the value of the last. >>> eval_all(read_line("(1)"), create_global_frame()) 1 >>> eval_all(read_line("(1 2)"), create_global_frame()) 2 >>> x = eval_all(read_line("((print 1) 2)"), create_global_frame()) 1 >>> x 2 >>> eval_all(read_line("((define x 2) x)"), create_global_frame()) 2 """ # BEGIN PROBLEM 6 if expressions==nil: returnNone res=nil while expressions!=nil: res=scheme_eval(expressions.first,env) expressions=expressions.rest return res # END PROBLEM 6
Problem 7
unlocked questions:
lambda_line = read_line(“(lambda (a b c) (+ a b c))”)
defmake_child_frame(self, formals, vals): """Return a new local frame whose parent is SELF, in which the symbols in a Scheme list of formal parameters FORMALS are bound to the Scheme values in the Scheme list VALS. Both FORMALS and VALS are represented as Pairs. Raise an error if too many or too few vals are given. >>> env = create_global_frame() >>> formals, expressions = read_line('(a b c)'), read_line('(1 2 3)') >>> env.make_child_frame(formals, expressions) <{a: 1, b: 2, c: 3} -> <Global Frame>> """ iflen(formals) != len(vals): raise SchemeError('Incorrect number of arguments to function call') # BEGIN PROBLEM 8 "*** YOUR CODE HERE ***" child_frame=Frame(self) for i inrange(len(formals)): child_frame.define(formals.first,vals.first) formals=formals.rest vals=vals.rest return child_frame # END PROBLEM 8
Problem 9
1 2 3 4 5
elifisinstance(procedure, LambdaProcedure): # BEGIN PROBLEM 9 "*** YOUR CODE HERE ***" expr=procedure.env.make_child_frame(procedure.formals,args) return eval_all(procedure.body,expr)
Problem 10
1 2 3 4 5 6 7 8 9
elifisinstance(signature, Pair) and scheme_symbolp(signature.first): # defining a named procedure e.g. (define (f x y) (+ x y)) # BEGIN PROBLEM 10 "*** YOUR CODE HERE ***" formals=signature.rest validate_formals(formals) env.define(signature.first,LambdaProcedure(formals,expressions.rest,env)) return signature.first # END PROBLEM 10
Problem 11
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
elifisinstance(procedure, MuProcedure): # BEGIN PROBLEM 11 "*** YOUR CODE HERE ***" child=env.make_child_frame(procedure.formals,args) return eval_all(procedure.body,child) # END PROBLEM 11 defdo_mu_form(expressions, env): """Evaluate a mu form.""" validate_form(expressions, 2) formals = expressions.first validate_formals(formals) # BEGIN PROBLEM 11 "*** YOUR CODE HERE ***" return MuProcedure(formals,expressions.rest) # END PROBLEM 11
defdo_cond_form(expressions, env): """Evaluate a cond form. >>> do_cond_form(read_line("((#f (print 2)) (#t 3))"), create_global_frame()) 3 """ while expressions isnot nil: clause = expressions.first validate_form(clause, 1) if clause.first == 'else': test = True if expressions.rest != nil: raise SchemeError('else must be last') else: test = scheme_eval(clause.first, env) if is_scheme_true(test): # BEGIN PROBLEM 13 "*** YOUR CODE HERE ***" if clause.rest==nil: return test else: return eval_all(clause.rest,env) else: # END PROBLEM 13 expressions = expressions.rest
Problem 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
defmake_let_frame(bindings, env): """Create a child frame of Frame ENV that contains the definitions given in BINDINGS. The Scheme list BINDINGS must have the form of a proper bindings list in a let expression: each item must be a list containing a symbol and a Scheme expression.""" ifnot scheme_listp(bindings): raise SchemeError('bad bindings list in let form') names = values = nil # BEGIN PROBLEM 14 "*** YOUR CODE HERE ***" while bindings!=nil: validate_form(bindings.first,2,2) names=Pair(bindings.first.first,names) values=Pair(scheme_eval(bindings.first.rest.first,env),values) bindings=bindings.rest validate_formals(names) # END PROBLEM 14 return env.make_child_frame(names, values)
Problem 15
1 2 3 4 5 6 7 8 9 10
(define (enumerate s) ; BEGIN PROBLEM 15 (define (helper index s) (if (null? s) nil (cons (list index (car s)) (helper (+ 1 index) (cdr s))) ) ) (helper 0 s) ) ; END PROBLEM 15