CS61A学习记录 Day 1

def fastest_words(game):
    """Return a list of lists of which words each player typed fastest.

    Arguments:
        game: a game data abstraction as returned by time_per_word.

    >>> p0 = [5, 1, 3]
    >>> p1 = [4, 1, 6]
    >>> fastest_words(game(['Just', 'have', 'fun'], [p0, p1]))
    [['have', 'fun'], ['Just']]
    """
    player_indices = range(len(all_times(game)))  # contains an *index* for each player
    word_indices = range(len(all_words(game)))    # contains an *index* for each word
    # BEGIN PROBLEM 10
    "*** YOUR CODE HERE ***"
    """
    对于每个word,检索当前index的所有player中耗时min的player_index,对应的list添加上words_at(index)
    """
    fastest_words_list = [[] for _ in word_indices]
    times = all_times(game)
    for i in word_indices:
        min_word_index = min(player_indeices, key = lambda x: times[x][i]) #这句话很关键 注意如何挑选出list中value最小值的index 将整个index通过range(len())形式遍历
        fastest_words_list[min_word_index].append(words_at(game, i))
    return fastest_words_list

记录一下cs61A学习过程中的有趣代码

运行命令行

python -i xxx.py #正常运行代码(也会运行doctest 但是不会具体显示测试情况 fail也会报错)

python -m doctest -v xxx.py #运行代码+显示doctest测试情况

python ok -q --suite x --case y --local #使用ok测试代码(不需要具体case就把--suite x --case y去除)

python ok -q xxx(函数名) #用doctest测试单个函数
每个test除了数值外可选的回答:
Function
Infinite
Nothing
Error

Lecture 4 High Order Function

lambda + inverse函数,对于函数f,如果存在非负整数x使f(x) ==y,则输出g函数,使g(y)->x

def search(f):
   x = 0
   while True:
      if f(x): #执行时相当于调用了lambda: f(x) == y,return f(x) == y,该语句可以等效为if f(x) ==y:
         return x
      x = x + 1

def inverse(f):
   """Reverse g(y) such that g(f(x)) -> x

   >>> from math import sqrt
   >>> square = inverse(sqrt)
   >>> square(16)
   256
   """
   return lambda y: search(lambda x: f(x) == y)

Exam prep01

比较复杂的一种写法


"""
相当于一个for循环,输入n, k, 判断  k % 2 ==0 or ... or k % n ==0
"""
def div_by_primes_under(n):
   """
   >>> div_by_primes_under(10)(11)
   False
   >>> div_by_primes_under(10)(121)
   False
   >>> div_by_primes_under(10)(12)
   True
   >>> div_by_primes_under(5)(1)
   False
   """
   checker = lambda x: False
   i = 2
   while i <= n:
      if not checker(i): # 简便了一下k % 2 ==0 or ... or k % n ==0,例如i = 4时, x % 4必有x % 2,此时不需要更新checker,该判断条件不要也可以
         checker = (lambda f, i: lambda x: x % i == 0 or f(x))(checker, i)
      i = i + 1
   return checker

def div_by_primes_under_no_lambda(n):
   """
   >>> div_by_primes_under_no_lambda(10)(11)
   False
   >>> div_by_primes_under_no_lambda(10)(121)
   False
   >>> div_by_primes_under_no_lambda(10)(12)
   True
   >>> div_by_primes_under_no_lambda(5)(1)
   False
   """
   def checker(x):
      return False
   i = 2
   while i <= n:
      if not checker(i):
        def outer(f, i):
            def inner(x):
                return x % i == 0 or f(x)
        return inner
      i = i + 1
   return checker
def three_memory(n):
   """
   >>> f = three_memory('first')
   >>> f = f('first')
   Not found
   >>> f = f('second')
   Not found
   >>> f = f('third')
   Not found
   >>> f = f('second') # 'second' was not input three calls ago
   Not found
   >>> f = f('second') # 'second' was input three calls ago
   Found
   >>> f = f('third') # 'third' was input three calls ago
   Found
   >>> f = f('third') # 'third' was not input three calls ago
   Not found
   """
   def f(x, y, z):
        def g(i):
            if i == x:
                print('Found')
            else:
                print('Not found')
            return f(y, z, i)
        return g
    return f('None', 'None', n)

Lecture 9 Tree Recursion

Linear recursion:每次递归仅执行一次递归调用

Tree recursion:每次递归执行多次调用,使每一个树枝有多个分支

这篇博客写得很详细【菜gou的CS61A学习笔记7 Tree Recursion】_cs61a tree-CSDN博客

"""
cascade(123):
123
12
1
12
123

"""

"""第一种写法"""
def cascade(n):
    if n < 10:
        print(n)
    else:
        print(n)
        cascade(n // 10)
        print(n)

"""更简洁点的写法"""
def cascade_new(n):
    print(n)
    if n >= 10:
        print(n)
        cascade(n // 10)
        print(n)        

"""与cascade作用相反"""
def inverse_cascade(n):
    grow(n)
    print(n)
    shrink(n)

def f_then_g(f, g, n):
    if n:
        f(n)
        g(n)

grow = lambda n: f_then_g(grow, print, n//10)
shrink = lambda n: f_then_g(print, shrink, n//10)
斐波那契数列
def fabonaci(n):
    if n == 0:
        return 0
    if n == 1:
        return 1
    else:
        return fabonaci(n - 1) + fabonaci(n - 2)
汉诺塔问题
"""
三根柱子的汉诺塔问题
对于n个disks移动问题,分解成先把第n - 1个disk移动到剩余的空闲位,然后把第n个disk从起点移到终点,再把第n - 1个disk从空闲位移动回来
"""

def move_disk(disk_number, from_peg, to_peg):
    print("Move disk" + str(disk_number) + "from peg" + str(from_peg) + "to peg" + str(to_peg))

def solve_hano(n, start_peg, end_peg):
    if n == 1:
        move_disk(n, start_peg, end_peg)
    else:
        spare_peg = 6 - start_peg - end_peg
        solve_hano(n-1, start_peg, spare_peg)    #在这一步,信任前面的n-1个disc被挪到了spare_peg
        move_disk(n, start_peg, end_peg)
        solve_hano(n-1, spare_peg, end_peg)

"""
汉诺塔的另一种写法,来自hw03
"""


def print_move(origin, destination):
    """Print instructions to move a disk."""
    print("Move the top disk from rod", origin, "to rod", destination)


def move_stack(n, start, end):
    """Print the moves required to move n disks on the start pole to the end
    pole without violating the rules of Towers of Hanoi.

    n -- number of disks
    start -- a pole position, either 1, 2, or 3
    end -- a pole position, either 1, 2, or 3

    There are exactly three poles, and start and end must be different. Assume
    that the start pole has at least n disks of increasing size, and the end
    pole is either empty or has a top disk larger than the top n start disks.

    >>> move_stack(1, 1, 3)
    Move the top disk from rod 1 to rod 3
    >>> move_stack(2, 1, 3)
    Move the top disk from rod 1 to rod 2
    Move the top disk from rod 1 to rod 3
    Move the top disk from rod 2 to rod 3
    >>> move_stack(3, 1, 3)
    Move the top disk from rod 1 to rod 3
    Move the top disk from rod 1 to rod 2
    Move the top disk from rod 3 to rod 2
    Move the top disk from rod 1 to rod 3
    Move the top disk from rod 2 to rod 1
    Move the top disk from rod 2 to rod 3
    Move the top disk from rod 1 to rod 3
    """
    assert 1 <= start <= 3 and 1 <= end <= 3 and start != end, "Bad start/end"
    "*** YOUR CODE HERE ***"
    if n == 1:
        print_move(start, end)
    else:
        move_stack(n - 1, start, 6 - start - end)
        move_stack(1, start, end)
        move_stack(n - 1, 6 - start - end, end)
"""
counting_partition: 对输入数n,划分为几个数相加,其中的最大数不超过k
问题分解n, 最大数k - 1分解以及 n - k,最大数k分解
"""

def counting_partition(n, k):
    if n == 0:
        return 1    #n = 0时return 1,因为调用它的上一层(n, n)即n + 0一种划分,到底了
    elif n < 0:
        return 0    #递归越界
    elif k == 0:
        return 0    #无法进行划分
    else:
        return counting_partition(n, k - 1) + counting_partition(n - k, k)
"""
计算change能有多少种分为25, 10, 5, 1 coin的方法
和counting_partition的写法很类似
"""

def get_next_coin(coin):
    if n == 1:
        return 5
    elif n == 5:
        return 10
    elif n == 10:
        return 25
    else:
        return None

# 当每次循环所需要传递(跟踪)的参数大于1时,则需要在该recursion函数内部定义一个helper函数
# 通过原函数来初始化helper函数,在helper函数内完成recursion
def count_coins(change):
    def count(change, smallestCoin):
        if change == 0:
            return 1
        elif change < 0 or smallestCoin == None:    #可以优化为elif smallestCoin == None or change < smallestCoin:
            return 0
        else:
            return count(change, get_next_coin(smallestCoin)) + count(change - smallestCoin, smallestCoin)
    return count(change, 1)
"""
count_coins的另一种写法
从最大的coin开始往下分,tree的一支是使用largestCoin(则对剩余的coin继续分割),另一支是不使用最大的coin,使用下一层更小的coin分割
"""

def largest_coin(coin):
    if coin >= 25:
        return 25
    elif coin >= 10:
        return 10
    elif coin >= 5:
        return 5
    elif coin >= 1:
        return 1
    else:
        return None

def get_next_coin(coin):
    """Return the next coin. 
    >>> get_next_coin(1)
    5
    >>> get_next_coin(5)
    10
    >>> get_next_coin(10)
    25
    >>> get_next_coin(2) # Other values return None
    """
    if coin == 25:
        return 10
    elif coin == 10:
        return 5
    elif coin == 5:
        return 1

def count_coins(change):
    """Return the number of ways to make change using coins of value of 1, 5, 10, 25.
    >>> count_coins(15)
    6
    >>> count_coins(10)
    4
    >>> count_coins(20)
    9
    >>> count_coins(100) # How many ways to make change for a dollar?
    242
    >>> from construct_check import check
    >>> # ban iteration
    >>> check(HW_SOURCE_FILE, 'count_coins', ['While', 'For'])                                          
    True
    """
    "*** YOUR CODE HERE ***"
    # def count(change, smallestCoin):
    #     if change == 0:
    #         return 1
    #     elif smallestCoin == None or change < smallestCoin:
    #         return 0
    #     return count(change, get_next_coin(smallestCoin)) + count(change - smallestCoin, smallestCoin)
    # return count(change, 1)
    def count(change, largestCoin):
        print("DEBUG: change, largestCoin", change, largestCoin)
        if change == 0 or largestCoin == 1:
            # print("DEBUG: change, largestCoin", change, largestCoin)
            return 1
        elif change < 0:
            # print("DEBUG: change, largestCoin", change, largestCoin)
            return 0
        return count(change, get_next_coin(largestCoin)) + count(change - largestCoin, largestCoin)
    return count(change, largest_coin(change))

Lambda函数实现自己递归:需要在lambda函数内部将lambda函数作为参数传入

"""
传入参数n,返回值n!
"""
from operator import sub, mul

"""
>>> from operator import sub, mul
>>> fact = lambda n: 1 if n == 1 else mul(1, fact(sub(n, 1)))
>>> fact(5)
120
"""


def make_anonymous_factorial():
    """Return the value of an expression that computes factorial.

    >>> make_anonymous_factorial()(5)
    120
    >>> from construct_check import check
    >>> # ban any assignments or recursion
    >>> check(HW_SOURCE_FILE, 'make_anonymous_factorial', ['Assign', 'AugAssign', 'FunctionDef', 'Recursion'])
    True
    """
    """
    本来我写的,这样写有个问题是最后mul(n, f(n - 1))这里f没有define,所以应该将f本身也作为参数传递下去
    return (lambda f: lambda n: 1 if n == 1 else mul(n, f(n - 1)))(lambda n: 1 if n == 1 else mul(n, f(n - 1)))"""
    return (lambda f: lambda n: 1 if n == 1 else mul(n, f(f, n - 1)))(lambda f, n: 1 if n == 1 else mul(n, f(f, n - 1)))
Lecture 10
pairs = [[1, 2], [3, 4], [4, 5], [5, 5], [10, 10]]

same_count = 0

for x, y in pairs:
    if x == y:
        same_count += 1

print(same_count)
"""
    将输入的两个数(数本身就是降序的),每个位数降序排列组合成一个数
   还有一种写法是,先判断两个数哪个更大,递归条件是偏小的n//10 < 0,
   然后将偏小数的每一位插入偏大数的位数中
   或者比较个位数,个位数偏小的数n // 10,传递下去(本种写法)
"""
def merge(n1, n2):
   """ Merges two numbers by digit in decreasing order
   >>> merge(31, 42)
   4321
   >>> merge(21, 0)
   21
   >>> merge (21, 31)
   3211
   """
   def helper(result, n1, n2):
      if (n1 == 0 and n2 < 10) or (n1 < 10 and n2 == 0):
         return result * 10 + n2 if n1 == 0 else result * 10 + n1
      else:
         last_digit_1 = n1 % 10
         last_digit_2 = n2 % 10
         if last_digit_1 <= last_digit_2:
            result = result * 10 + last_digit_1
            return helper(result, n1 // 10, n2)
         else:
            result = result * 10 + last_digit_2
            return helper(result, n1, n2 // 10)
   if n1 == 0 or n2 == 0:
      return n2 if not n1 else n1
   return helper(0, n1, n2)
print(merge (531, 0))
"""
经典爬楼梯问题,一次爬一级或者两级
"""
def count_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 ***"
   def helper(n, step):
      if n == 0:
         return 1
      elif n == 1:
         return helper(n - 1, 1)
      elif n < 0:
         return 0
      else:
         return helper(n - 1, 1) + helper(n - 2, 2)
   return helper(n, 0)
"""
这里的问题区别于之前的count_partition在于,不需要记录每一个step(每一个k的值),因为前面的step值不影响后面的step值,step值都是从1到k任意的,所以需要for i in range(1, k + 1)循环,使n - i从n - 1到n - k
"""
def count_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 == 0:
      return 1
   elif n == 1:
      return 1
   elif n < 0:
      return 0
   else:
      return count_stair_ways(n - 1) + count_stair_ways(n - 2)



def count_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 == 0:
       return 1
   elif n < 0:
       return 0
   else:
       total = 0
       for i in range(1, k + 1):
           total += count_k(n - i, k)    #这里不是加count(n - i, i)否则会限制了每一次能跨的步数k
       return total

Lecture 10
"""
字符串反转
reverse("word") = drow
reverse("word") = reverse("ord") + "w"
...
reverse("d") = "d"
"""
def reverse_string(str):
    if len(str) == 1:
        return str
    else:
        return reverse_string(str[1:]) + str[0]
Lecture 11
"""
Prof强调了在创建对象的时候一定要用constructor,以及在进行computational 函数的构建时
一定要用selector,而不是直接计算,避免violating abstraction barriers
"""

def rational(n, d):
    def select(name):
        if name == 'n':
            return n
        elif name == 'd':
            return d
    return select

def numerator(x):
    return x('n')    #相当于select('n')

def denumerator(x):
    return x('d')    #相当于select('d')
def fastest_words(game):
    """Return a list of lists of which words each player typed fastest.

    Arguments:
        game: a game data abstraction as returned by time_per_word.

    >>> p0 = [5, 1, 3]
    >>> p1 = [4, 1, 6]
    >>> fastest_words(game(['Just', 'have', 'fun'], [p0, p1]))
    [['have', 'fun'], ['Just']]
    """
    player_indices = range(len(all_times(game)))  # contains an *index* for each player
    word_indices = range(len(all_words(game)))    # contains an *index* for each word
    # BEGIN PROBLEM 10
    "*** YOUR CODE HERE ***"
    """
    对于每个word,检索当前index的所有player中耗时min的player_index,对应的list添加上words_at(index)
    """
    fastest_words_list = [[] for _ in player_indices]
    times = all_times(game)
    for i in word_indices:
        min_time_player_index = min(player_indices, key = lambda x: times[x][i])    #这行很重要 意味着将你需要pick的list放入 然后在key中制定lambda函数以制定min的规则
        fastest_words_list[min_time_player_index].append(word_at(game, i))
    return fastest_words_list
    # END PROBLEM 10

Cats


def pawssible_patches(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
    >>> pawssible_patches("cats", "scat", big_limit)       # cats -> scats -> scat
    2
    >>> pawssible_patches("purng", "purring", big_limit)   # purng -> purrng -> purring
    2
    >>> pawssible_patches("ckiteus", "kittens", big_limit) # ckiteus -> kiteus -> kitteus -> kittens
    3
    """
    #由于这个函数实际上只在乎次数,不在乎具体将字母换成什么字母,所以只需要判断有多少位被执行了base行为
    if limit < 0:
        # BEGIN
        return 0
        # 需要让循环在limit = 0后终止,但这里return 值为多少无所谓 因为通常是在not start or not goal这个判断句下return真实操作值
        # 但是不能在limit = 0时终止return 1,因为这里如果limit > 0
        # END
    if not start or not goal:  # 如果两个中只要有一个为空,则需要修改的次数直接为两者之差
        # BEGIN
        return abs(len(start) - len(goal))
        # END
    elif start[0] == goal[0]:
        return pawssible_patches(start[1:], goal[1:], limit)
    else:
        # 相当于是每次都虚执行add remove substitute
        add = pawssible_patches(start, goal[1:], limit - 1)
        # print("DEBUG: add", add)
        remove = pawssible_patches(start[1:], goal, limit - 1)
        # print("DEBUG:remove", remove)
        substitute = pawssible_patches(start[1:], goal[1:], limit - 1)
        # print("DEBUG:substitute", substitute)
        return min(add, remove, substitute) + 1     #这里+1意思是执行了add remove substitute中三个行为中的一个
        # BEGIN
        "*** YOUR CODE HERE ***"

        # END

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值