Composing Programs 2.3 Sequence - 01

伯克利CS 61A的笔记,用的2020 Fall版本

2.3.3 Sequence Processing

2.3.3.1 List Comprehensions

Many sequence processing operations can be expressed by evaluating a fixed expression for each element in a sequence and collecting the resulting values in a result sequence.

In Python, a list comprehension is an expression that performs such a computation.

格式:[<map expression> for <name> in <sequence expression> if <filter expression>]

>>> odds = [1, 3, 5, 7, 9]
>>> [x+1 for x in odds]
[2, 4, 6, 8, 10]
>>> [x for x in odds if 25 % x == 0]
[1, 5]

To evaluate a list comprehension, Python evaluates the <sequence expression>, which must return an iterable value.

Then, for each element in order, the element value is bound to <name>, the filter expression is evaluated, and if it yields(得到) a true value, the map expression is evaluated.

The values of the map expression are collected into a list.

2.3.3.2 Aggregation

A third common pattern in sequence processing is to aggregate all values in a sequence into a single value. 函数sum, min,max等就是这样的例子。

下面的例子求完全数(perfect number),A perfect number is a positive integer that is equal to the sum of its divisors.

>>> def divisors(n):
        return [1] + [x for x in range(2, n) if n % x == 0]
>>> divisors(4)
[1, 2]
>>> divisors(12)
[1, 2, 3, 4, 6]
>>> [n for n in range(1, 1000) if sum(divisors(n)) == n]
[6, 28, 496]

也可以用上面定义的divisors函数来求解这个问题:给定一个矩形的面积,求边长为整数的矩形的最小周长(finding the minimum perimeter of a rectangle with integer side lengths, given its area.)。

>>> def width(area, height):
        assert area % height == 0
        return area // height

>>> def perimeter(width, height):
        return 2 * width + 2 * height

>>> def minimum_perimeter(area):
        heights = divisors(area)
        perimeters = [perimeter(width(area, h), h) for h in heights]
        return min(perimeters)

>>> area = 80
>>> width(area, 5)
16
>>> perimeter(16, 5)
42
>>> perimeter(10, 8)
36
>>> minimum_perimeter(area)
36
>>> [minimum_perimeter(n) for n in range(1, 10)]
[4, 6, 8, 8, 12, 10, 16, 12, 12]

2.3.3.3 Higher-Order Functions

通用的函数模式可以抽象为高阶函数,那么通用的对sequence(序列)的处理方法(函数)也可以抽象为高阶函数(Higher-Order Functions)。

>>> def apply_to_all(map_fn, s):
        return [map_fn(x) for x in s]

>>> def keep_if(filter_fn, s):
        return [x for x in s if filter_fn(x)]

>>> def reduce(reduce_fn, s, initial):
        reduced = initial
        for x in s:
            reduced = reduce_fn(reduced, x)
        return reduced

>>> reduce(mul, [2, 4, 8], 1)
64

用高阶函数找完全数(perfect number)。

>>> def divisors_of(n):
        divides_n = lambda x: n % x == 0
        return [1] + keep_if(divides_n, range(2, n))

>>> divisors_of(12)
[1, 2, 3, 4, 6]

>>> from operator import add
>>> def sum_of_divisors(n):
        return reduce(add, divisors_of(n), 0)
>>> def perfect(n):
        return sum_of_divisors(n) == n
>>> keep_if(perfect, range(1, 1000))
[1, 6, 28, 496]

2.3.3.4 Conventional Names

In the computer science community, the more common name for apply_to_all is map and the more common name for keep_if is filter. 名字 map 比 apply_to_all 更常用,filter 比 keep_if 更常用。

In Python, the built-in map and filter are generalizations of these functions that do not return lists. python里面有内置map和filter,而且不返回列表。 

The reduce function is built into the functools module of the Python standard library. reduce函数内置在python标准库的functools模块。

>>> apply_to_all = lambda map_fn, s: list(map(map_fn, s))
>>> keep_if = lambda filter_fn, s: list(filter(filter_fn, s))
>>> from functools import reduce
>>> from operator import mul
>>> def product(s):
        return reduce(mul, s)
>>> product([1, 2, 3, 4, 5])
120

2.3.4   Sequence Abstraction

切片

>>> digits[0:2]
[1, 8]
>>> digits[1:]
[8, 2, 8]

 

一些题目

1. Maximum Subsequence

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 number n is 10 * n + d.
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 ***"
    if t == 0 or n == 0:
        return 0
    else:
        use_last = max_subseq(n // 10, t - 1) * 10 + n % 10
        not_use_last = max_subseq(n // 10, t)
        return max(use_last, not_use_last)

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值