cs61a学习笔记 Homework 1: Functions, Control

目录

Q1: A Plus Abs B

Python's operator module contains two-argument functions such as add and sub for Python's built-in arithmetic operators. For example, add(2, 3) evalutes to 5, just like the expression 2 + 3.
a + |b| = \begin{cases} a + b, & b \ge 0 \\ a - b, & b < 0 \end{cases}
An expression describes a computation and evaluates to a value. && All expressions can use function call notation 中缀表达式和函数调用表达式在某种程度上是等价的

from operator import add, sub

def a_plus_abs_b(a, b):
    """Return a+abs(b), but without calling abs.

    >>> a_plus_abs_b(2, 3)
    5
    >>> a_plus_abs_b(2, -3)
    5
    >>> a_plus_abs_b(-1, 4)
    3
    >>> a_plus_abs_b(-1, -4)
    3
    """
    if b < 0:
        f = sub
    else:
        f = add
    return f(a, b)

Q2: 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.
可以使用min和max 函数 有两种思路,最简单是计算三者各自平方的和再减去最大那个数的平方就是最小的两个数各自平方的和了,另一种思路是考虑到3选2任意两个平方的组合,因为交换位置并不影响结果,所以有3中,而最小的两个数各自的平方肯定是所有组合中最小的

def two_of_three(i, j, k):
    """Return m*m + n*n, where m and n are the two smallest members of the
    positive numbers i, j, and k.

    >>> 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 i*i + j*j + k*k - max(i, j, k) * max(i, j, k)
    # 总共有三种组合 找到里面最小的两个肯定是最小的
    return min(i*i + j*j, i*i+k*k, j*j+k*k)

Q3: Largest Factor

Write a function that takes an integer n that is greater than 1 and returns the largest integer that is smaller than n and evenly divides n.
显然 最大的那个因数肯定是逆序第一个能整除n的,判断是否整除等价于模运算是否为0 if b evenly divides a, use the expression a % b == 0, which can be read as, "the remainder when dividing a by b is 0."由于while loop和for loop是等价的,可以不同的实现(while 处理不知道具体次数的loop比较好,for则相反), 还有一种暴力枚举的思路是用列表存储[2, n-1]的所有满足条件的因数,遍历得到最大的那个。

def largest_factor(n):
    """Return the largest factor of n that is smaller than n.

    >>> largest_factor(15) # factors are 1, 3, 5
    5
    >>> largest_factor(80) # factors are 1, 2, 4, 5, 8, 10, 16, 20, 40
    40
    >>> largest_factor(13) # factors are 1, 13
    1
    """
    "*** YOUR CODE HERE ***"
    # 倒着数第一个能整除的肯定是最大的因数
    # while loop 和 for lop是等价的
    i = n - 1
    # 范围 [2, n -1]
    """
    while(i >= 1):

        if n % i == 0:
            return i
        i -= 1
    """
    for i in range(n-1, 0, -1):
        if n % i == 0:
            return i

Q4: 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:
T(n) = \begin{cases} \frac{n}{2}, & n \text{ 为偶数} \\ 3n + 1, & n \text{ 为奇数} \end{cases}
最主要的问题就是如何不重不漏的用if-else划分问题的空间,该问题把整数分为奇数和偶数两类,而1包括在奇数里面。通过一个无限循环去模拟直到满足条件跳出即可,print(n)在每次loop开始前打印比较合适,使用计数器记录当进入某个满足条件的分支。

Note that if n == 1 initially, then the sequence is one step long.
Hint: If you see 4.0 but want just 4, try using floor division // instead of regular division /.

def hailstone(n):
    """Print the hailstone sequence starting at n and return its
    length.

    >>> a = hailstone(10)
    10
    5
    16
    8
    4
    2
    1
    >>> a
    7
    >>> b = hailstone(1)
    1
    >>> b
    1
    """
    "*** YOUR CODE HERE ***"
    count = 0
    while True:
        # print(n)
        if n % 2 == 0:
            count += 1
            n = n // 2
        else:
            if n == 1:
                count += 1
                break
            else:
                count += 1
                n = n * 3 + 1

    return count

Hailstone sequences can get quite long! Try 27. What's the longest you can find?
可以使用记忆化搜索去优化问题,这里朴素的使用暴力枚举并用字典去记录某个数和它对应的冰雹序列长度。具体可以了解下斐波那契数列的递归,记忆化搜索和动态规划。

# 是否可以将数字当作下标和对应长度做一个映射,然后统计在某个范围内序列长度最大的那个冰雹数
def count_longest_hailstone_number(limit):
    result = {}
    for i in range(1, limit + 1):
        result[i] = hailstone(i)

    # 找到最大长度的值
    max_length = max(result.values())
    for key, value in result.items():
        if value == max_length:
            return key   # 返回最大长度对应的数字

    return None     # 没有找到返回None

整除的一些等价定义

一、基本定义
a \mid b \iff \exists k \in \mathbb{Z},\; b = ak

a 整除 b ⇔ 存在整数 k,使得 b = a·k

二、否定形式(不整除)
a \nmid b \iff \forall k \in \mathbb{Z},\; b \ne ak
三、等价“除法表示”
a \mid b \iff \frac{b}{a} \in \mathbb{Z}

核心直觉:

能不能整除 = 看商是不是整数

四、余数形式(非常重要)
a \mid b \iff b \bmod a = 0

或者等价写成:

b = aq + r,\quad 0 \le r < a,\quad a \mid b \iff r = 0
五、集合论视角(很高级但很清晰)
a \mid b \iff b \in a\mathbb{Z}

含义:

b 属于 a 的整数倍集合

六、线性代数/结构视角(抽象一点)
a \mid b \iff b \in \langle a \rangle
七、线性组合推广(重要)
a \mid b \iff \exists x \in \mathbb{Z},\; b - ax = 0

这就是:

“线性方程有整数解”

八、组合统一写法(最常用三件套)
a \mid b \iff \exists k \in \mathbb{Z},\; b = ak \iff \frac{b}{a} \in \mathbb{Z} \iff b \bmod a = 0

整除其实是三种等价语言:

视角 表达
乘法 b = ak
除法 b/a 是整数
余数 b mod a = 0

gcd-lcm lattice 结构

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容