一、merge in disc03
Write a procedure merge(n1, n2) which takes numbers with digits in decreasing order and returns a single number with all of the digits of the two, in decreasing order. Any number merged with 0 will be that number (treat 0 as having no digits). Use recursion.
Hint: If you can figure out which number has the smallest digit out of both, then we know that the resulting number will have that smallest digit, followed by the merge of the two numbers with the smallest digit removed.
代码:(主要是我没留意给出的数字都是降序,所以卡了半天)
def merge(n1, n2):
""" Merges two numbers
>>> merge(31, 42)
4321
>>> merge(21, 0)
21
>>> merge (21, 31)
3211
"""
if n1 == 0:
return n2
elif n2 == 0:
return n1
elif n1%10 >= n2%10:
return merge(n1, n2//10)*10 + n2%10
elif n1%10 <= n2%10:
return merge(n1//10, n2)*10 + n1%10
二、cycle in lab02:
Define a function
cycle
that takes in three functionsf1
,f2
,f3
, as arguments.cycle
will return another function that should take in an integer argumentn
and return another function. That final function should take in an argumentx
and cycle through applyingf1
,f2
, andf3
tox
, depending on whatn
was. Here's what the final function should do tox
for a few values ofn
:
n = 0
, returnx
n = 1
, applyf1
tox
, or returnf1(x)
n = 2
, applyf1
tox
and thenf2
to the result of that, or returnf2(f1(x))
n = 3
, applyf1
tox
,f2
to the result of applyingf1
, and thenf3
to the result of applyingf2
, orf3(f2(f1(x)))
n = 4
, start the cycle again applyingf1
, thenf2
, thenf3
, thenf1
again, orf1(f3(f2(f1(x))))
- And so forth.
Hint: most of the work goes inside the most nested function.
代码:(这里我主要是不想设一个变量,通过判断该变量除以3之后的余数来做,所以卡壳了一会儿)
def cycle(f1, f2, f3):
"""Returns a function that is itself a higher-order function.
>>> def add1(x):
... return x + 1
>>> def times2(x):
... return x * 2
>>> def add3(x):
... return x + 3
>>> my_cycle = cycle(add1, times2, add3)
>>> identity = my_cycle(0)
>>> identity(5)
5
>>> add_one_then_double = my_cycle(2)
>>> add_one_then_double(1)
4
>>> do_all_functions = my_cycle(3)
>>> do_all_functions(2)
9
>>> do_more_than_a_cycle = my_cycle(4)
>>> do_more_than_a_cycle(2)
10
>>> do_two_cycles = my_cycle(6)
>>> do_two_cycles(1)
19
"""
"*** YOUR CODE HERE ***"
def times(n):
def apply(x):
if n == 0:
return x
else:
return cycle(f2, f3, f1)(n - 1)(f1(x))
return apply
return times
三、max_subseq in lab04
A subsequence of a number is a series of (not necessarily contiguous) digits of the number. For example, 12345 has subsequences that include 123, 234, 124, 245, etc. Your task is to get the maximum subsequence below a certain length.
def max_subseq(n, t): """ Return the maximum subsequence of length at most t that can be found in the given number n. For example, for n = 20125 and t = 3, we have that the subsequences are 2 0 1 2 5 20 21 22 25 01 02 05 12 15 25 201 202 205 212 215 225 012 015 025 125 and of these, the maxumum number is 225, so our answer is 225. >>> max_subseq(20125, 3) 225 >>> max_subseq(20125, 5) 20125 >>> max_subseq(20125, 6) # note that 20125 == 020125 20125 >>> max_subseq(12345, 3) 345 >>> max_subseq(12345, 0) # 0 is of length 0 0 >>> max_subseq(12345, 1) 5 """ "*** YOUR CODE HERE ***"
There are two key insights for this problem:
- You need to split into the cases where the ones digit is used and the one where it is not. In the case where it is, we want to reduce
t
since we used one of the digits, and in the case where it isn't we do not.- In the case where we are using the ones digit, you need to put the digit back onto the end, and the way to attach a digit
d
to the end of a numbern
is10 * n + d
.
老实说这题着实难倒我了,想了半天,最后借助着the recursive leap of faith,竟然真的就做出来了。思路就是把问题根据是否使用了最后一个数分成两种情况。
代码:
def max_subseq(n, t):
if t == 0 or n ==0:
return 0
elif t == 1:
return max(n%10,max_subseq(n//10,1))
else:
case_with_last = max_subseq(n//10, t-1)*10 + n%10
case_without_last = max_subseq(n//10,t)
return max(case_without_last,case_with_last)
四、count_k in disc04
Consider a special version of the count_stairways problem, where instead of taking 1 or 2 steps, we are able to take up to and including k steps at a time.
Write a function count_k that figures out the number of paths for this scenario. Assume n and k are positive.
就是爬楼梯问题的进阶版。一开始我想的也是把问题分解成存在爬了k步和不存在爬了k步两种情况 ,爬了k步又分为第一步爬了k步和第一步没有爬k步,但这样的话就是f(n,k-1) + f(n-k, k) + f(n-k+1, k),然后就发现就算第一步没有爬k步,也有可能爬了k-1,k-2,k-3,...,2,1步的情况,根本写不出来,就又卡住了。卡了半天才知道去用遍历。
代码:
def count_k(n, k):
"""
>>> 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
"""
if n == 0:
return 1
elif n < 0:
return 0
total = 0
for i in range(1, k+1):
total += count_k(n-i,k)
return total
五、max_product
Write a function that takes in a list and returns the maximum product that can be formed using nonconsecutive elements of the list. The input list will contain only numbers greater than or equal to 1.
因为要求的是使用相隔开的元素,所以最开头两个数字,要么用到第一个,要么用到第二个,然后类推就行了。
代码:
def max_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 len(s) == 4:
return max(s[0]*s[2], s[1]*s[3])
elif len(s) == 3:
return max(s[0]*s[2], s[1])
elif len(s) == 2:
return max(s[0], s[1])
elif len(s) == 1:
return s[0]
elif len(s) == 0:
return 1
else:
with0 = s[0] * max_product(s[2:])
with1 = s[1] * max_product(s[3:])
return max(with1, with0)