[CS61A] Lecture 4. Higher-Order Functions & Project 1: The Game of Hog

Lecture

Lecture 4. Higher-Order Functions

本节课介绍了高阶函数的概念与用法,主要包含如下内容:

  1. 从斐波那契数列说起,定义fib函数并使用迭代法解答。
  2. 面积公式,介绍正方形、五边形以及圆形的面积公式,它们的共同点是面积公式都可以变为:半径x半径x面积系数 的形式,因此将函数抽象成一个通用函数。
  3. 求和公式,西格玛求和公式可以通过一个包含序列长度n和元素计算函数term的方式表达,就此引入高阶函数的概念。
  4. 局部函数:在非全局作用域中定义的函数,例如make_adder函数接受一个整数n,返回用来+n的函数adder。
  5. 高阶函数:将函数作为参数或返回值的函数。
  6. 匿名函数:lambda函数,没有绑定名称的函数。
  7. return关键词:表示函数的结束,函数有两种返回的方法,一种是当满足条件时返回,另一个是判断所有不满足的条件后返回。
  8. 控制语句if、else,控制表达式and、or、x if a else b。

Q&A:lambda函数

Project 1: The Game of Hog

Phase 1: Rules of the Game

该项目要求充分运用python中控制与高阶函数相关的知识,实现一个hog游戏。

Problem 0 (0 pt)

要求在dice.py文件中实现一个公平的骰子。实际上是个判断题,判断多个骰子函数中哪个才是真正公平的骰子,答案是a) six_sided()。

执行测试用例:

$ python3 ok -q 00 -u
Question 0 > Suite 1 > Case 1
? 4
? 1
? 2
? 4
---------------------------------------------------------------------
Question 0 > Suite 2 > Case 1
? 0

Problem 1 (2 pt)

要求在hog.py中实现roll_dice函数。

roll_dice函数:

def roll_dice(num_rolls, dice=six_sided):
"""Simulate rolling the DICE exactly NUM_ROLLS > 0 times. Return the sum of
the outcomes unless any of the outcomes is 1. In that case, return 1. num_rolls: The number of dice rolls that will be made.
dice: A function that simulates a single dice roll outcome.
"""
# These assert statements ensure that num_rolls is a positive integer.
assert type(num_rolls) == int, 'num_rolls must be an integer.'
assert num_rolls > 0, 'Must roll at least once.'
# BEGIN PROBLEM 1
res = [dice() for _ in range(num_rolls)]
return 1 if 1 in res else sum(res)
# END PROBLEM 1

执行测试用例:

$ python3 ok -q 01 -u
Question 1 > Suite 1 > Case 1
? 10
---------------------------------------------------------------------
Question 1 > Suite 1 > Case 2
? 1
---------------------------------------------------------------------
Question 1 > Suite 1 > Case 3
? 1
---------------------------------------------------------------------
Question 1 > Suite 1 > Case 5
? 1
? 6
---------------------------------------------------------------------
Question 1 > Suite 1 > Case 6
? 54
$ python3 ok -q 01
Test summary
59 test cases passed! No cases failed.

Problem 2 (4 pt)

要求实现oink_points函数。

oink_points函数:

def oink_points(player_score, opponent_score):
"""Return the points scored by player due to Oink Points. player_score: The total score of the current player.
opponent_score: The total score of the other player.
"""
ones = opponent_score%10
tens = opponent_score//10%10
return max(2*tens-ones, 1)

执行测试用例:

$ python3 ok -q 02 -u
Question 2 > Suite 1 > Case 1
? 1
---------------------------------------------------------------------
Question 2 > Suite 1 > Case 2
? 12
---------------------------------------------------------------------
Question 2 > Suite 1 > Case 3
? 1
$ python3 ok -q 02
Test summary
34 test cases passed! No cases failed.

Problem 3 (2 pt)

要求实现take_turn函数。

take_turn函数:

def take_turn(num_rolls, player_score, opponent_score, dice=six_sided, goal=GOAL_SCORE):
"""Simulate a turn rolling NUM_ROLLS dice,
which may be 0 in the case of a player using Oink Points.
Return the points scored for the turn by the current player. num_rolls: The number of dice rolls that will be made.
player_score: The total score of the current player.
opponent_score: The total score of the opponent.
dice: A function that simulates a single dice roll outcome.
goal: The goal score of the game.
"""
# Leave these assert statements here; they help check for errors.
assert type(num_rolls) == int, 'num_rolls must be an integer.'
assert num_rolls >= 0, 'Cannot roll a negative number of dice in take_turn.'
assert num_rolls <= 10, 'Cannot roll more than 10 dice.'
assert max(player_score, opponent_score) < goal, 'The game should be over.'
# BEGIN PROBLEM 3
if num_rolls==0:
return oink_points(player_score, opponent_score)
return roll_dice(num_rolls, dice)
# END PROBLEM 3

执行测试用例:

$ python3 ok -q 03 -u
Question 3 > Suite 1 > Case 1
? 9
---------------------------------------------------------------------
Question 3 > Suite 1 > Case 2
? 1
---------------------------------------------------------------------
Question 3 > Suite 1 > Case 3
? 7
---------------------------------------------------------------------
Question 3 > Suite 1 > Case 4
? 1
$ python3 ok -q 03
Test summary
10 test cases passed! No cases failed.

Problem 4 (1 pt)

要求实现pigs_on_prime函数。

pigs_on_prime函数:

def pigs_on_prime(player_score, opponent_score):
"""Return the points scored by the current player due to Pigs on Prime. player_score: The total score of the current player.
opponent_score: The total score of the other player.
"""
# BEGIN PROBLEM 4
if not is_prime(player_score):
return 0
additional_score = 1
while not is_prime(player_score+additional_score):
additional_score+=1
return additional_score
# END PROBLEM 4

执行测试用例:

$ python3 ok -q 04 -u
Question 4 > Suite 1 > Case 1
? 0
---------------------------------------------------------------------
Question 4 > Suite 1 > Case 2
? 4
---------------------------------------------------------------------
Question 4 > Suite 1 > Case 3
? 0
---------------------------------------------------------------------
Question 4 > Suite 1 > Case 4
? 2
---------------------------------------------------------------------
Question 4 > Suite 1 > Case 5
? 2
$ python3 ok -q 04
Test summary
105 test cases passed! No cases failed.

Phase 2: Playing the Game

Problem 5 (5 pt)

要求实现play函数。

play函数:

def play(strategy0, strategy1, score0=0, score1=0, dice=six_sided,
goal=GOAL_SCORE, say=silence):
"""Simulate a game and return the final scores of both players, with Player
0's score first, and Player 1's score second. A strategy is a function that takes two total scores as arguments (the
current player's score, and the opponent's score), and returns a number of
dice that the current player will roll this turn. strategy0: The strategy function for Player 0, who plays first.
strategy1: The strategy function for Player 1, who plays second.
score0: Starting score for Player 0
score1: Starting score for Player 1
dice: A function of zero arguments that simulates a dice roll.
goal: The game ends and someone wins when this score is reached.
say: The commentary function to call every turn.
"""
who = 0 # Who is about to take a turn, 0 (first) or 1 (second)
leader = None # To be used in problem 7
# BEGIN PROBLEM 5
while score0 < goal and score1 < goal:
if who == 0:
score0 += take_turn(strategy0(score0, score1), score0, score1, dice, goal)
score0 += pigs_on_prime(score0, score1)
else:
score1 += take_turn(strategy1(score1, score0), score1, score0, dice, goal)
score1 += pigs_on_prime(score1, score0)
who = next_player(who)
# END PROBLEM 5
# (note that the indentation for the problem 7 prompt (***YOUR CODE HERE***) might be misleading)
# BEGIN PROBLEM 7
"*** YOUR CODE HERE ***"
# END PROBLEM 7
return score0, score1

执行测试用例:

$ python3 ok -q 05 -u
Question 5 > Suite 1 > Case 1
? 2
---------------------------------------------------------------------
Question 5 > Suite 1 > Case 2
? 1
---------------------------------------------------------------------
Question 5 > Suite 1 > Case 3
? 3
---------------------------------------------------------------------
Question 5 > Suite 2 > Case 1
? 106
? 10
---------------------------------------------------------------------
Question 5 > Suite 2 > Case 2
? 15
? 0
---------------------------------------------------------------------
Question 5 > Suite 3 > Case 1
? 87
? 108
$ python3 ok -q 05
Test summary
111 test cases passed! No cases failed.

Problem 6 (2 pt)

要求实现announce_lead_changes函数。

announce_lead_changes函数:

def announce_lead_changes(score0, score1, last_leader=None):
"""A commentary function that announces when the leader has changed. >>> leader, message = announce_lead_changes(5, 0)
>>> print(message)
Player 0 takes the lead by 5
>>> leader, message = announce_lead_changes(5, 12, leader)
>>> print(message)
Player 1 takes the lead by 7
>>> leader, message = announce_lead_changes(8, 12, leader)
>>> print(leader, message)
1 None
>>> leader, message = announce_lead_changes(8, 13, leader)
>>> leader, message = announce_lead_changes(15, 13, leader)
>>> print(message)
Player 0 takes the lead by 2
"""
# BEGIN PROBLEM 6
if score0 == score1:
leader = None
changes = 0
elif score0 < score1:
leader = 1
changes = score1-score0
else:
leader = 0
changes = score0-score1
return leader, f'Player {leader} takes the lead by {changes}' if leader != last_leader and leader != None else None
# END PROBLEM 6

执行测试用例:

$ python3 ok -q 06 -u
Question 6 > Suite 1 > Case 1
? 1
---------------------------------------------------------------------
Question 6 > Suite 1 > Case 2
? 0
---------------------------------------------------------------------
Question 6 > Suite 1 > Case 3
? 0
$ python3 ok -q 06
Test summary
4 test cases passed! No cases failed.

Problem 7 (2 pt)

要求更新play函数,

函数:

def play(strategy0, strategy1, score0=0, score1=0, dice=six_sided,
goal=GOAL_SCORE, say=silence):
"""Simulate a game and return the final scores of both players, with Player
0's score first, and Player 1's score second. A strategy is a function that takes two total scores as arguments (the
current player's score, and the opponent's score), and returns a number of
dice that the current player will roll this turn. strategy0: The strategy function for Player 0, who plays first.
strategy1: The strategy function for Player 1, who plays second.
score0: Starting score for Player 0
score1: Starting score for Player 1
dice: A function of zero arguments that simulates a dice roll.
goal: The game ends and someone wins when this score is reached.
say: The commentary function to call every turn.
"""
who = 0 # Who is about to take a turn, 0 (first) or 1 (second)
leader = None # To be used in problem 7
# BEGIN PROBLEM 5
while score0 < goal and score1 < goal:
if who == 0:
score0 += take_turn(strategy0(score0, score1), score0, score1, dice, goal)
score0 += pigs_on_prime(score0, score1)
else:
score1 += take_turn(strategy1(score1, score0), score1, score0, dice, goal)
score1 += pigs_on_prime(score1, score0)
who = next_player(who)
# END PROBLEM 5
# (note that the indentation for the problem 7 prompt (***YOUR CODE HERE***) might be misleading)
# BEGIN PROBLEM 7
leader, message = say(score0, score1, leader)
print(message) if message else 0
# END PROBLEM 7
return score0, score1

执行测试用例:

$ python3 ok -q 07 -u
Question 7 > Suite 1 > Case 1
? 0
---------------------------------------------------------------------
Question 7 > Suite 2 > Case 3
(line 1)? 5 0
(line 2)? 5 5
(line 3)? 8 5
---------------------------------------------------------------------
Question 7 > Suite 2 > Case 4
(line 1)? 1 7
(line 2)? 2 7
(line 3)? 3 12
(line 4)? 4 12
(line 5)? 5 19
---------------------------------------------------------------------
Question 7 > Suite 3 > Case 1
(line 1)? 4 0
(line 2)? 4 12
(line 3)? 7 12
(line 4)? 7 24
---------------------------------------------------------------------
Question 7 > Suite 3 > Case 2
(line 1)? 3
(line 2)? 10
(line 3)? 14
(line 4)? 19
---------------------------------------------------------------------
Question 7 > Suite 3 > Case 3
(line 1)? * 3
(line 2)? ** 0
(line 3)? * 3
(line 4)? ** 3
(line 5)? * 7
(line 6)? ** 3
$ python3 ok -q 07
Test summary
9 test cases passed! No cases failed.

Phase 3: Strategies of the Game

Problem 8 (2 pt)

实现make_averaged函数。

make_averaged函数:

def make_averaged(original_function, total_samples=1000):
"""Return a function that returns the average value of ORIGINAL_FUNCTION
called TOTAL_SAMPLES times. To implement this function, you will have to use *args syntax, a new Python
feature introduced in this project. See the project description. >>> dice = make_test_dice(4, 2, 5, 1)
>>> averaged_dice = make_averaged(roll_dice, 1000)
>>> averaged_dice(1, dice)
3.0
"""
# BEGIN PROBLEM 8
def inner(*args):
return sum([original_function(*args) for _ in range(total_samples)])/total_samples
return inner
# END PROBLEM 8

执行测试用例:

$ python3 ok -q 08 -u
Question 8 > Suite 1 > Case 1
? 3
---------------------------------------------------------------------
Question 8 > Suite 1 > Case 2
? 0
---------------------------------------------------------------------
Question 8 > Suite 2 > Case 1
? 3.75
---------------------------------------------------------------------
Question 8 > Suite 2 > Case 2
? 6.0
$ python3 ok -q 08
Test summary
7 test cases passed! No cases failed.

Problem 9 (2 pt)

实现max_scoring_num_rolls函数。

max_scoring_num_rolls函数:

def max_scoring_num_rolls(dice=six_sided, total_samples=1000):
"""Return the number of dice (1 to 10) that gives the highest average turn score
by calling roll_dice with the provided DICE a total of TOTAL_SAMPLES times.
Assume that the dice always return positive outcomes. >>> dice = make_test_dice(1, 6)
>>> max_scoring_num_rolls(dice)
1
"""
# BEGIN PROBLEM 9
new_roll_dice = make_averaged(roll_dice, total_samples)
return max([(new_roll_dice(i, dice), i) for i in range(1, 11)], key=lambda x: x[0])[1]
# END PROBLEM 9

执行测试用例:

$ python3 ok -q 09 -u
Question 9 > Suite 1 > Case 1
? 2
---------------------------------------------------------------------
Question 9 > Suite 2 > Case 1
? 10
---------------------------------------------------------------------
Question 9 > Suite 3 > Case 1
? 10
---------------------------------------------------------------------
Question 9 > Suite 3 > Case 2
? 1
---------------------------------------------------------------------
Question 9 > Suite 3 > Case 3
? 1
$ python3 ok -q 09
Test summary
10 test cases passed! No cases failed.

Problem 10 (1 pt)

要求实现oink_points_strategy函数。

oink_points_strategy函数:

def oink_points_strategy(score, opponent_score, threshold=8, num_rolls=6):
"""This strategy returns 0 dice if that gives at least THRESHOLD points, and
returns NUM_ROLLS otherwise.
"""
# BEGIN PROBLEM 10
return 0 if oink_points(score, opponent_score) >= threshold else num_rolls
# END PROBLEM 10

执行测试用例:

$ python3 ok -q 10 -u
Question 10 > Suite 1 > Case 1
? 0
---------------------------------------------------------------------
Question 10 > Suite 1 > Case 2
? 5
---------------------------------------------------------------------
Question 10 > Suite 1 > Case 3
? 0
---------------------------------------------------------------------
Question 10 > Suite 1 > Case 4
? 4
---------------------------------------------------------------------
Question 10 > Suite 1 > Case 5
? 0
$ python3 ok -q 10
Test summary
106 test cases passed! No cases failed.

Problem 11 (1 pt)

要求实现pigs_on_prime_strategy函数。

pigs_on_prime_strategy函数:

def pigs_on_prime_strategy(score, opponent_score, threshold=8, num_rolls=6):
"""This strategy returns 0 dice when this would result in Pigs on Prime taking
effect. It also returns 0 dice if it gives at least THRESHOLD points.
Otherwise, it returns NUM_ROLLS.
"""
# BEGIN PROBLEM 11
additional = oink_points(score, opponent_score)
return 0 if pigs_on_prime(score+additional, opponent_score) != 0 or additional >= threshold else num_rolls
# END PROBLEM 11

执行测试用例:

$ python3 ok -q 11 -u
Question 11 > Suite 1 > Case 1
? 0
---------------------------------------------------------------------
Question 11 > Suite 1 > Case 2
? 6
---------------------------------------------------------------------
Question 11 > Suite 1 > Case 3
? 0
---------------------------------------------------------------------
Question 11 > Suite 1 > Case 4
? 6
$ python3 ok -q 11
Test summary
105 test cases passed! No cases failed.

Optional: Problem 12 (0 pt)

要求实现final_strategy函数,该题为开放题,思考怎样结合oink_points或pigs_on_prime策略,让玩家赢的概率才能够更大。

参考资料

CS61A Project 1: The Game of Hog:https://cs61a.org/proj/hog/

cs61a公开课视频:https://www.bilibili.com/video/BV1s3411G7yM

[CS61A] Lecture 4. Higher-Order Functions & Project 1: The Game of Hog的更多相关文章

  1. [CS61A] Lecture 5&6&7. Environments & Design & Functions Examples & Homework 2: Higher Order Functions

    [CS61A] Lecture 5&6&7. Environments & Design & Functions Examples & Homework 2: ...

  2. 46 Simple Python Exercises-Higher order functions and list comprehensions

    26. Using the higher order function reduce(), write a function max_in_list() that takes a list of nu ...

  3. [CS61A] Lecture 1&2&3. Introduction&Functions&Control

    [CS61A] Lecture 1&2&3. Introduction&Functions&Control 前言 CS61A是加州大学伯克利分校一门计算机专业课程,用于 ...

  4. [React] Higher Order Components (replaces Mixins)

    Higher order components will allow you to apply behaviors to multiple React components. So the idea ...

  5. [React] Implement a Higher Order Component with Render Props

    When making a reusable component, you'll find that people often like to have the API they're most fa ...

  6. [Redux] Understand Redux Higher Order Reducers

    Higher Order Reducers are simple reducer factories, that take a reducer as an argument and return a ...

  7. [React Intl] Use a react-intl Higher Order Component to format messages

    In some cases, you might need to pass a string from your intl messages.js file as a prop to a compon ...

  8. [React] Cleanly Map Over A Stateless Functional Component with a Higher Order Component

    In this lesson we'll create a Higher Order Component (HOC) that takes care of the key property that ...

  9. [RxJS] Flatten a higher order observable with concatAll in RxJS

    Besides switch and mergeAll, RxJS also provides concatAll as a flattening operator. In this lesson w ...

随机推荐

  1. Spring(四)-声明式事务

    Spring-04 声明式事务 1.事务的定义 事务就是由一组逻辑上紧密关联的多个工作单元(数据库操作)而合并成一个整体,这些操作要么都执行,要么都不执行. 2.事务的特性:ACID 1)原子性A : ...

  2. php统计IP PV和今日访问量统计方法

    php引用,在wordpress主题中 $getroot=$_SERVER['DOCUMENT_ROOT']; require_once("$getroot/countstart.php&q ...

  3. 在 Windows 搭建 SVN 服务

    以下内容为本人的学习笔记,如需要转载,请声明原文链接微信公众号「englyf」https://www.cnblogs.com/englyf/p/16671311.html 最近公司给配了台新电脑,配置 ...

  4. vue3中defineComponent 的作用

    vue3中,新增了 defineComponent ,它并没有实现任何的逻辑,只是把接收的 Object 直接返回,它的存在是完全让传入的整个对象获得对应的类型,它的存在就是完全为了服务 TypeSc ...

  5. MySQL常用函数整理,建议收藏!

    常见函数 字符串函数 数字函数 日期函数 聚合函数 流程控制函数 一.字符串函数 concat(s1,s2...,sn) --将s1,s2...,sn连接成字符串,如果该函数中的任何参数为 null, ...

  6. ProxySQL(5):线程、线程池、连接池

    文章转载自:https://www.cnblogs.com/f-ck-need-u/p/9281909.html ProxySQL的线程 ProxySQL由多个模块组成,是一个多线程的daemon类程 ...

  7. git pull提示如下信息时候的操作

    执行git pull时提示信息如下: There is no tracking information for the current branch. Please specify which bra ...

  8. win10系统应用商店打开后无法联网 代码: 0x80131500 的解决办法

    官方提供的建议网址: https://answers.microsoft.com/zh-hans/windows/forum/all/代码/cbbe7aaf-8f66-4779-89c8-3c74f5 ...

  9. 复现禅道V16.5的SQL注入(CNVD-2022-42853)

    漏洞详情 禅道V16.5未对输入的account参数内容作过滤校验,导致攻击者拼接恶意SQL语句执行. 环境搭建 环境下载:禅道V16.5 下载后双击运行,进入目录运行start.exe 直接访问即可 ...

  10. 1_Maven

    一. 引言 1.1 项目管理问题 项目中jar包资源越来越多, jar包的管理越来越沉重 1.1.1 繁琐 要为每个项目手动导入所需的jar, 需要搜集全部的jar 1.1.2 复杂 项目中的jar如 ...