CS61A 课程项目 Hog, Phase3: Strategies

提示:本文内容来源于UCB CS61A课程,详情请点击CS 61A: Structure and Interpretation of Computer Programs


前言

本文收录在文章CS61A 课程 Project1 The Game of Hog


提示:以下是本篇文章正文内容,下面代码除课程提供外均为本人自主完成,仅供参考

Phase3: Strategies

Problem 08

本节要求实现函数make_averaged,该函数是一个以函数original_function为参数的高阶函数

其返回另一个与函数original_function参数相同的函数,二者的不同之处在于,作为返回值的函数返回的是重复调用original_function的平均值,此函数应调用 original_function 共 trials_count 次并返回结果的平均值。

要求该函数可以接收任意数量的参数,参数应记作*args(而不是将参数序列列表化),如下示例

>>> def printed(f):
...     def print_and_return(*args):
...         result = f(*args)
...         print('Result:', result)
...         return result
...     return print_and_return
>>> printed_pow = printed(pow)
>>> printed_pow(2, 8)
Result: 256
256
>>> printed_abs = printed(abs)
>>> printed_abs(-10)
Result: 10
10

项目介绍要求认真阅读make_averaged函数的docstring:

"""Return a function that returns the average value of ORIGINAL_FUNCTION when called.

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(dice, 1000)
>>> averaged_dice()
3.0
"""

提供了测试脚本检测学生是否理解函数需求

$ python3 ok -q 08 -u --local
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unlocking tests

At each "? ", type what you would expect the output to be.
Type exit() to quit

---------------------------------------------------------------------
Question 8 > Suite 1 > Case 1
(cases remaining: 7)

Q: What makes make_averaged a higher order function?
Choose the number of the correct choice:
0) It uses the *args keyword
1) It returns a function
2) It takes in a function as an argument
3) It both takes in a function as an argument and returns a function
? 3
-- OK! --

---------------------------------------------------------------------
Question 8 > Suite 1 > Case 2
(cases remaining: 6)

Q: How many arguments does the function passed into make_averaged take?
Choose the number of the correct choice:
0) An arbitrary amount, which is why we need to use *args to call it
1) Two
2) None
? 0
-- OK! --

---------------------------------------------------------------------
Question 8 > Suite 2 > Case 1
(cases remaining: 5)

>>> from hog import *
>>> dice = make_test_dice(3, 1, 5, 6)
>>> averaged_dice = make_averaged(dice, 1000)
>>> # Average of calling dice 1000 times
>>> averaged_dice()
? 3.75
-- OK! --

---------------------------------------------------------------------
Question 8 > Suite 2 > Case 2
(cases remaining: 4)

>>> from hog import *
>>> dice = make_test_dice(3, 1, 5, 6)
>>> averaged_roll_dice = make_averaged(roll_dice, 1000)
>>> # Average of calling roll_dice 1000 times
>>> # Enter a float (e.g. 1.0) instead of an integer
>>> averaged_roll_dice(2, dice)
? 6.0
-- OK! --

---------------------------------------------------------------------
OK! All cases for Question 8 unlocked.

函数的实现如下:

def make_averaged(original_function, trials_count=1000):
    """Return a function that returns the average value of ORIGINAL_FUNCTION when called.

    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(dice, 1000)
    >>> averaged_dice()
    3.0
    """
    # BEGIN PROBLEM 8
    "*** YOUR CODE HERE ***"
    def average(*args):
        average = 0
        for i in range(trials_count):
            average += original_function(*args)
        return average / trials_count
    return average
    # END PROBLEM 8

以上实现符合评分脚本要求

$ python3 ok -q 08 --local
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Running tests

---------------------------------------------------------------------
Test summary
    7 test cases passed! No cases failed.

Problem 09

该部分要求实现函数max_scoring_num_rolls,该函数需要两个参数,一个骰子类型(如六面骰),以为测试次数

该函数的功能为,测试投掷骰子数量不同(1-10)时的平均得分(每个数量所对应的测试进行trial_counts次)

要求实现时要用make_averaged函数和roll_dice函数来完成

注:多个投掷数量取得相同的得分时,要返回数量较少的那一个

课程提供了提问脚本检查学生是否彻底理解函数的功能

$ python3 ok -q 09 -u --local
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unlocking tests

At each "? ", type what you would expect the output to be.
Type exit() to quit

---------------------------------------------------------------------
Question 9 > Suite 1 > Case 1
(cases remaining: 8)

Q: If multiple num_rolls are tied for the highest scoring
average, which should you return?
Choose the number of the correct choice:
0) The highest num_rolls
1) A random num_rolls
2) The lowest num_rolls
? 2
-- OK! --

---------------------------------------------------------------------
Question 9 > Suite 2 > Case 1
(cases remaining: 7)

>>> from hog import *
>>> dice = make_test_dice(3)   # dice always returns 3
>>> max_scoring_num_rolls(dice, trials_count=1000)

? 10
-- OK! --

---------------------------------------------------------------------
Question 9 > Suite 3 > Case 1
(cases remaining: 4)

>>> from hog import *
>>> dice = make_test_dice(2)     # dice always rolls 2
>>> max_scoring_num_rolls(dice, trials_count=1000)
? 10
-- OK! --


>>> from hog import *
>>> dice = make_test_dice(1, 2)  # dice alternates 1 and 2
>>> max_scoring_num_rolls(dice, trials_count=1000)
? 1
-- OK! --


---------------------------------------------------------------------
OK! All cases for Question 9 unlocked.

函数的实现如下

def max_scoring_num_rolls(dice=six_sided, trials_count=1000):
    """Return the number of dice (1 to 10) that gives the highest average turn
    score by calling roll_dice with the provided DICE over TRIALS_COUNT times.
    Assume that the dice always return positive outcomes.

    >>> dice = make_test_dice(1, 6)
    >>> max_scoring_num_rolls(dice)
    1
    """
    # BEGIN PROBLEM 9
    "*** YOUR CODE HERE ***"
    max_num, max_average = None, 0

    for i in range(1, 11):
        this_average = make_averaged(roll_dice, trials_count)(i, dice)
        if max_average < this_average:
            max_num, max_average = i, this_average
    return max_num
    # END PROBLEM 9

符合评分脚本要求

$ python3 ok -q 09 --local
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Running tests

---------------------------------------------------------------------
Test summary
    8 test cases passed! No cases failed.

Problem 10

一种策略,利用Free Bacon规则,在最有利时选择不抛骰子,此部分要求实现bacon_strategy函数

该函数在不抛骰子时可以得到至少cutoff分数时返回0,否则返回num_rolls

注:默认策略函数不知晓当前玩家在上一轮中取得的分数,因此不能预测由于规则Feral Hog所获得的额外分数。即一个策略不考虑规则Feral Hog,也不考虑规则Swine Swap

$ python3 ok -q 10 -u --local
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unlocking tests

At each "? ", type what you would expect the output to be.
Type exit() to quit

---------------------------------------------------------------------
Question 10 > Suite 1 > Case 1
(cases remaining: 106)

>>> from hog import *
>>> bacon_strategy(0, 9, cutoff=8, num_rolls=5)
? 5
-- OK! --

---------------------------------------------------------------------
Question 10 > Suite 1 > Case 2
(cases remaining: 105)

>>> from hog import *
>>> bacon_strategy(9, 0, cutoff=6, num_rolls=5)
? 0
-- OK! --

---------------------------------------------------------------------
Question 10 > Suite 1 > Case 3
(cases remaining: 104)

>>> from hog import *
>>> bacon_strategy(50, 2, cutoff=9, num_rolls=5)
? 5
-- OK! --

---------------------------------------------------------------------
Question 10 > Suite 1 > Case 4
(cases remaining: 103)

>>> from hog import *
>>> bacon_strategy(32, 0, cutoff=5, num_rolls=4)
? 0
-- OK! --

---------------------------------------------------------------------
Question 10 > Suite 1 > Case 5
(cases remaining: 102)

>>> from hog import *
>>> bacon_strategy(20, 1, cutoff=1, num_rolls=4)
? 0
-- OK! --

---------------------------------------------------------------------

OK! All cases for Question 10 unlocked.

函数的实现如下:

def bacon_strategy(score, opponent_score, cutoff=8, num_rolls=6):
    """This strategy rolls 0 dice if that gives at least CUTOFF points, and
    rolls NUM_ROLLS otherwise.
    """
    # BEGIN PROBLEM 10
    if free_bacon(opponent_score) >= cutoff:
        return 0
    return num_rolls  # Replace this statement
    # END PROBLEM 10

满足评分脚本要求

$ python3 ok -q 10 --local
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Running tests

---------------------------------------------------------------------
Test summary
    106 test cases passed! No cases failed.

Problem 11

该策略利用了Swine Swap规则,该策略总是选择不投掷(在不投掷会触发有益交换的条件下),或总是选择避免不投掷(在不投掷会导致有害交换的条件下)

在除了以上两种情况外,该策略与Problem 10 中完成的策略保持一致

与上一个实现的策略相同,默认策略函数不知晓当前玩家在上一轮中取得的分数,因此不能预测由于规则Feral Hog所获得的额外分数

课程提供了提问脚本用于确保学生理解函数的作用

$ python3 ok -q 11 -u --local
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unlocking tests

At each "? ", type what you would expect the output to be.
Type exit() to quit

---------------------------------------------------------------------
Question 11 > Suite 1 > Case 1
(cases remaining: 107)

>>> from hog import *
>>> swap_strategy(1, 19, 8, 6)
? 6
-- OK! --

---------------------------------------------------------------------
Question 11 > Suite 1 > Case 2
(cases remaining: 106)

>>> from hog import *
>>> swap_strategy(30, 54, 7, 6)
? 0
-- OK! --

---------------------------------------------------------------------
Question 11 > Suite 1 > Case 3
(cases remaining: 105)

>>> from hog import *
>>> swap_strategy(1, 19, 100, 6)
? 6
-- OK! --

---------------------------------------------------------------------
Question 11 > Suite 1 > Case 4
(cases remaining: 104)

>>> from hog import *
>>> swap_strategy(24, 1, 1, 6)
? 0
-- OK! --

---------------------------------------------------------------------
Question 11 > Suite 1 > Case 5
(cases remaining: 103)

>>> from hog import *
>>> swap_strategy(13, 18, 10, 6)
? 6
-- OK! --

---------------------------------------------------------------------
Question 11 > Suite 1 > Case 6
(cases remaining: 102)

>>> from hog import *
>>> swap_strategy(13, 18, 1, 6)
? 0
-- OK! --

---------------------------------------------------------------------

OK! All cases for Question 11 unlocked.

函数的实现如下:

def swap_strategy(score, opponent_score, cutoff=8, num_rolls=6):
    """This strategy rolls 0 dice when it triggers a beneficial swap. It also
    rolls 0 dice if it gives at least CUTOFF points and does not trigger a
    non-beneficial swap. Otherwise, it rolls NUM_ROLLS.
    """
    # BEGIN PROBLEM 11
    free_bacon_score = free_bacon(opponent_score) + score
    if is_swap(free_bacon_score, opponent_score):
        if free_bacon_score < opponent_score:
            return 0
        elif free_bacon_score > opponent_score:
            return num_rolls
    return bacon_strategy(score, opponent_score, cutoff, num_rolls)  # Replace this statement
    # END PROBLEM 11

上述实现满足评分脚本要求

$ python3 ok -q 11 --local
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Running tests

---------------------------------------------------------------------
Test summary
    107 test cases passed! No cases failed.

Problem 12(可选)

假设对手的策略为总是投掷4枚骰子,要求学生设计一个最终策略,以后的较大的胜率,提示如下

  • swap_strategy是一个优秀的默认策略
  • 追求以超过100分的分数获胜没有意义,因此可以尝试减少投掷骰子的数量来降低触发Pig Out规则的概率
  • 尝试通过投掷至少1个骰子来触发有益交换
  • 谨慎选择num_rolls``和cutoff```参数

课程提供了用于测试final_strategy胜率的工具(但是要认证,没办法了,只能用run_experiments检测以下算了)

先尝试一下将交换策略设置为默认策略

def final_strategy(score, opponent_score):
    """Write a brief description of your final strategy.

    *** YOUR DESCRIPTION HERE ***
    """
    # BEGIN PROBLEM 12
    return swap_strategy(score, opponent_score)  # Replace this statement
    # END PROBLEM 12
$ python3 hog.py -r
final_strategy win rate: 0.718

本身胜率挺高的,接下来按照提示尝试降低参数num_rolls的值以降低风险

试了几个参数发现胜率居然降低了,然后发现swap_strategy中参数num_rolls参数的值和对手策略always_roll中参数的值一致时是最保险的,调低胜率大幅度下跌,调高增长的不多且风险变高了,因此该参数的值最好与对手的一致

其余的提示没啥思路,准备学一学人工智能之后再回来看一看

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值