分享一道伯克利 CS 61A 关于高阶函数的一道Python作业题(2)

来源:互联网 发布:2017商务笔记本 知乎 编辑:程序博客网 时间:2024/05/18 01:33

这里,我给出个人对于上一篇文章中题目的一种解答。

首先,对于 one two这两个函数的定义,这个对于很多人来说,应该是没有什么难度的。根据successor的定义,我们可以得到下面两个函数的定义

def zero(f):    return lambda x: xdef successor(n):    return lambda f: lambda x: f(n(f)(x))def one(f):    """Church numeral 1: same as successor(zero)"""    "*** YOUR CODE HERE ***"    return lambda x: f(zero(f)(x))def two(f):    """Church numeral 2: same as successor(successor(zero))"""    "*** YOUR CODE HERE ***"    return lambda x: f(one(f)(x))three = successor(two)



好了,接下来是真正的实验——church_to_int(n)函数。这里,有两种可能: 从 0 到 n 和 从 n 到 0。两种方法我都试过,不过从 0 到n 貌似出不来结果,如果你的解答是从 0 到 n 算出来的,麻烦告诉我一声。

那么,接下来让我们从twozero进行分析(当然,你可以选择直接分析successor,如果你没被他的定义搞晕的话)。

首先我们应该明白,two(f)返回的是一个函数,该函数有一个formal parameter x。然后,让我们更进一步,假定有这么一个变量x存在,然后two(f)(x) == Two。同样的,one(f)(x) == One, zero(f)(x) == Zero(注意我这里用了大写)。

那么将有

two(f)(x)  ->  f(One)one(f)(x)  ->  f(Zero)

到了这里,是不是觉得,好像发现了什么呢?至少,很有规律,不是吗?


对于每一个 Church number function,我们都将比他小1的函数的返回值,作为实参,再调用了一次f函数。也就是说,对于一个数值为n的函数,f会被调用n次(一般情况下是如此,后面我们将挑战这一权威)。说到这里,答案其实已经浮出了水面,如果你没有忘记题目额外给出的一个increment函数的话。

def increment(x):    return x + 1def church_to_int(n):    """Convert the Church numeral n to a Python integer.    >>> church_to_int(zero)    0    >>> church_to_int(one)    1    >>> church_to_int(two)    2    >>> church_to_int(three)    3    """    "*** YOUR CODE HERE ***"    return n(increment)(0)

是不是很惊讶,答案居然是如此的简洁(老实说,个人写出这个一行代码时,也是觉得挺震撼的,题目的设计者真是个天才)。每次调用increment的时候,都会 +1,我们执行了increment n次,也就得到了我们想要的int值。




对于add_church函数,直觉上,想要从 mn而得到m+n,我们只需要简单地从n使用successor递增m步即可(当然,你也可以先判断哪一个比较小,这里暂时忽略这个问题)。于是,便有了下面这个解答:

def add_church(m, n):    """Return the Church numeral for m + n, for Church numerals m and n.    >>> church_to_int(add_church(two, three))    5    >>> church_to_int(add_church(zero, three))    3    """    "*** YOUR CODE HERE ***"    num_m = church_to_int(m)    while num_m > 0:        n = successor(n)        num_m -= 1    return n    # there is a better solution below

不知道你对这个答案满意度如何,我呢,总觉得有些别扭。这里我们居然用了5 行代码!5这个数字也许不是很大,但比起上一个问题中的1行代码,确实有点太多了。不过,这里我先放一放,后面我们再来讨论这个问题。




好啦,先放下add_church这么一个疙瘩,我们来看看mul_church

在告诉你答案前,我觉得,还是先来复习一下小学乘法:

2×3 表示 2 个 3 或 3 个 2

不管怎么样,还是先急着这个吧。

在前面我们实现church_to_int(f)时,我们在每次调用f时执行了+1操作,最后得到了church 函数对应的 整数值。这里,我们可以如法炮制。不管,现在每次增加的是 m而不是1(这里判断m, n那个比较小没有任何意义)。沿着这个思路,我们可能会写出:

def mul_church(m, n):    num_m = church_to_int(m)    add_m = lambda x: x + num_m    return n(add_m)(0)

很遗憾,这个是错的。我们需要的是一个 church 函数,而不是一个数字。不过,这是一个很好的开端。我们需要返回一个高阶函数,该函数接收一个函数作为实参且church_to_int利用该传入的实参计算对应的整数值。

接下来需要一个小小的跳跃。以我们church_to_int的实现来看,难道你传一个increment给我,我就得乖乖用他来一步一步加1吗?!为什么我们不能自作主张,一步加m呢?!(还记得上面说过的吗?m×n就是 n 个 m 相加)根据这个思想,就有了下面这个解答,从解决问题的思想上,和上面的解答其实是一样的

def mul_church(m, n):    """Return the Church numeral for m * n, for Church numerals m and n.    >>> four = successor(three)    >>> church_to_int(mul_church(two, three))    6    >>> church_to_int(mul_church(three, four))    12    >>> church_to_int(successor(mul_church(three, four)))    13    """    "*** YOUR CODE HERE ***"    num_m = church_to_int(m)    add_m = lambda x: x + num_m    return lambda f: n(add_m)    # or just    # return lambda f: n(lambda x: x + num_m)




现在,让我们回到前面的 add_church(m, n)。上面给出的答案是,从 n开始,一步一步,得到了 m + n。但是,不管怎么说,这种做法总是不够优雅。得益于上面对mul_church(m, n)的思考,有这么一个想法,我们能够一步就将m加到n呢?答案是,可以。

def add_church(m, n):    """Return the Church numeral for m + n, for Church numerals m and n.    >>> church_to_int(add_church(two, three))    5    >>> church_to_int(add_church(zero, three))    3    """    "*** YOUR CODE HERE ***"    num_m = church_to_int(m)    return lambda f: lambda x: num_m + n(f)(x)

虽然较之前面的答案更为的复杂,但个人觉得,也还算优雅。这里需要注意的一点是,lambda f: lambda x: n(f)(x)就等价于 n。当我们计算其对应的整数值时,加上了额外的 num_m,于是也就得到了 m+n对应的整数值。




是不是觉得很兴奋?非常的有趣,不是吗?到了这里,综合我的解说和你的理解,我相信,你有能力做出最后的 pow_church(m, n)。来吧,尝试一下,不然我可就只能独享这大餐了。




0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孩子老爱玩不爱学习怎么办? 孩子不爱做题怎么办 看书静不下心怎么办 孩子不自觉学习怎么办 不自觉的孩子怎么办 不学习的孩子怎么办 电脑不受老师控制怎么办 儿子不尊重老师怎么办 小孩不喜欢吃蔬菜怎么办 小孩不愿练钢琴怎么办 孩子不喜欢幼儿园老师怎么办 孩子不主动思考怎么办 我初一不想读书怎么办 初中孩子不爱学习怎么办 初一就不想读书怎么办 孩子懒得写作业怎么办 初中学生讨厌学习怎么办? 小学不写作业怎么办 幼儿园小朋友不愿意上学怎么办 幼儿园孩子不愿意上学怎么办 宝宝不愿意上幼儿园怎么办 孩子不爱上幼儿园怎么办 宝宝不爱上幼儿园怎么办 宝宝不爱去幼儿园怎么办 幼儿园宝宝不爱写字怎么办 小孩贪玩不爱学习怎么办 老师对幼儿不好怎么办 小孩不愿写作业怎么办 小孩怕老师厌学怎么办 幼儿园怕老师厌学怎么办 孩子很怕老师怎么办 孩子怕外教老师怎么办 家长打老师老师怎么办 被学生骂了怎么办 老师经常打孩子怎么办 老师每天打孩子怎么办 小孩不想去幼儿园怎么办 宝宝不想上幼儿园怎么办 小孩不爱学英语怎么办 孩子抵触学英语怎么办 初三了英语不好怎么办