前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >日拱一卒,伯克利CS61A,休闲难度,小试牛刀

日拱一卒,伯克利CS61A,休闲难度,小试牛刀

作者头像
TechFlow-承志
发布2022-09-21 12:39:21
3220
发布2022-09-21 12:39:21
举报
文章被收录于专栏:TechFlow

作者 | 梁唐

出品 | 公众号:Coder梁(ID:Coder_LT)

大家好,日拱一卒,我是梁唐。

我们今天继续来肝伯克利CS61A,这一次的内容是作业6和作业7。和之前的作业相比,这次的题量少了很多,所以把它们放在了一起。题目不难,算是休闲场吧。

原作业说明:https://inst.eecs.berkeley.edu//~cs61a/sp18/hw/hw06/

Next Fibonacci Object

Fib类中实现next函数,value属性是斐波那契数列的值。

next方法返回一个Fib的实例,这个实例中的值是斐波那契数列下一个值。next函数的复杂度必须是常数。

提示:可以在next函数当中赋值valueprevious

我们先来看一下它给的样例:

代码语言:javascript
复制
    >>> start = Fib()
    >>> start
    0
    >>> start.next()
    1
    >>> start.next().next()
    1
    >>> start.next().next().next()
    2
    >>> start.next().next().next().next()
    3
    >>> start.next().next().next().next().next()
    5
    >>> start.next().next().next().next().next().next()
    8
    >>> start.next().next().next().next().next().next() # Ensure start isn't changed
    8

也就是说调用next之后返回的还是一个同样的对象,只不过这个对象当中的值不同。

斐波那契数列本身并不复杂,无论是通过迭代计算还是通过递归实现,都很简单。棘手的点通过函数返回实例的形式比较新颖,我们之前没见过。

再来看一下给我们提供的框架代码:

代码语言:javascript
复制
class Fib():
    """A Fibonacci number.
    """

    def __init__(self, value=0):
        self.value = value

    def next(self):
        "*** YOUR CODE HERE ***"
        

    def __repr__(self):
        return str(self.value)

我们可以看到,在Fib这个定义当中,目前只有value这个属性,根本没有previous属性,显然这个属性需要我们自己加。但老师又不让我们修改构造函数,所以就只能加在next函数里了。

不考虑边界情况的话,代码应该是这样的:

代码语言:javascript
复制
def next(self):
    ret = Fib(self.value + self.previous)
    self.previous = self.value
    return ret

这个思路是OK的,但实现肯定是错的,因为self.previous并没有定义。进一步思考可以发现,self.previous依赖上一次迭代,我们只需要把第一次迭代特殊处理,就可以解决这个问题。

所以最后的代码为:

代码语言:javascript
复制
class Fib():
    """A Fibonacci number.
    """

    def __init__(self, value=0):
        self.value = value

    def next(self):
        "*** YOUR CODE HERE ***"
        if self.value == 0:
            ret = Fib(1)
        else:
            ret = Fib(self.previous + self.value)
        self.previous = self.value
        return ret

    def __repr__(self):
        return str(self.value)

Vending Machine

创建一个自动贩卖机的类,可以模拟自动贩卖机的功能。注意自动贩卖机会返回一个字符串,描述当前的情况。

我们可以来看下测试样例:

代码语言:javascript
复制
>>> v = VendingMachine('candy', 10)
>>> v.vend()
'Machine is out of stock.'
>>> v.deposit(15)
'Machine is out of stock. Here is your $15.'
>>> v.restock(2)
'Current candy stock: 2'
>>> v.vend()
'You must deposit $10 more.'
>>> v.deposit(7)
'Current balance: $7'
>>> v.vend()
'You must deposit $3 more.'
>>> v.deposit(5)
'Current balance: $12'
>>> v.vend()
'Here is your candy and $2 change.'
>>> v.deposit(10)
'Current balance: $10'
>>> v.vend()
'Here is your candy.'
>>> v.deposit(15)
'Machine is out of stock. Here is your $15.'

>>> w = VendingMachine('soda', 2)
>>> w.restock(3)
'Current soda stock: 3'
>>> w.restock(3)
'Current soda stock: 6'
>>> w.deposit(2)
'Current balance: $2'
>>> w.vend()
'Here is your soda.'

观察样例,可以发现一个点:

当贩卖机没有库存时,除了restock操作都会返回没有库存的提示,并且充值的话还会提示钱被返还。

除了这个特殊的点之外,其余就是一个简单的贩卖机的模拟。如果前面的作业都搞定了,到这里基本上可以说是小菜一碟了。

代码语言:javascript
复制
class VendingMachine:
    """A vending machine that vends some product for some price.
    """
    "*** YOUR CODE HERE ***"
    def __init__(self, item, price):
        self.item = item
        self.price = price
        self.stock = 0
        self.balance = 0

    def restock(self, amount):
        self.stock += amount
        return 'Current {} stock: {}'.format(self.item, self.stock)

    def deposit(self, amount):
        if self.stock == 0:
            return 'Machine is out of stock. Here is your ${}.'.format(amount)
        self.balance += amount
        return 'Current balance: ${}'.format(self.balance)

    def vend(self):
        if self.stock == 0:
            return 'Machine is out of stock.'
        if self.balance < self.price:
            return 'You must deposit ${} more.'.format(self.price - self.balance)
        else:
            ret = 'Here is your {}{}'.format(self.item, '.' if self.balance == self.price else ' and ${} change.'.format(self.balance - self.price))
            self.balance = 0
            self.stock -= 1
            return ret

Digits

实现digits类,能够以链表的形式展示n

我们来看这两个样例:

代码语言:javascript
复制
    >>> digits(0) is Link.empty
    True
    >>> digits(543)
    Link(5, Link(4, Link(3)))

这里的Link实现的是链表的功能,在课程当中曾经讲过。没有看过视频也没有关系,作业当中给出了完整的代码:

代码语言:javascript
复制
class Link:
    """A linked list.

    >>> s = Link(1)
    >>> s.first
    1
    >>> s.rest is Link.empty
    True
    >>> s = Link(2, Link(3, Link(4)))
    >>> s.second
    3
    >>> s.first = 5
    >>> s.second = 6
    >>> s.rest.rest = Link.empty
    >>> s                                    # Displays the contents of repr(s)
    Link(5, Link(6))
    >>> s.rest = Link(7, Link(Link(8, Link(9))))
    >>> s
    Link(5, Link(7, Link(Link(8, Link(9)))))
    >>> print(s)                             # Prints str(s)
    <5 7 <8 9>>
    """
    empty = ()

    def __init__(self, first, rest=empty):
        assert rest is Link.empty or isinstance(rest, Link)
        self.first = first
        self.rest = rest

    @property
    def second(self):
        return self.rest.first

    @second.setter
    def second(self, value):
        self.rest.first = value


    def __repr__(self):
        if self.rest is not Link.empty:
            rest_repr = ', ' + repr(self.rest)
        else:
            rest_repr = ''
        return 'Link(' + repr(self.first) + rest_repr + ')'

    def __str__(self):
        string = '<'
        while self.rest is not Link.empty:
            string += str(self.first) + ' '
            self = self.rest
        return string + str(self.first) + '>'

只要读懂了Link类的使用方法,代码并不难写,只是一个简单的迭代:

代码语言:javascript
复制
def digits(n):
    """Return the digits of n as a linked list.

    >>> digits(0) is Link.empty
    True
    >>> digits(543)
    Link(5, Link(4, Link(3)))
    """
    s = Link.empty
    while n > 0:
        n, last = n // 10, n % 10
        "*** YOUR CODE HERE ***"
        s = Link(last, s)
    return s

Miss Manners

创建一个类叫做MissManners,它能够提升我们对象的礼貌程度。

MissManners对象的构造函数接受另外一个对象object,它有一个函数,叫做ask。通过ask函数可以调用object中的方法,但前提是必须在调用之前用上please表示礼貌。

我们还可以将多个MissManners对象合成在一起,这样的话我们必须要加上多个please才能调用到底层的对象。具体可以参考样例。

提示

使用getattr函数和hasattr函数来以字符串的形式获取对象中的函数,你可以上网搜索相关的样例

在你的实现当中,需要用到*args,它表示接收任意多个参数,我们在之前的作业当中曾经用过

我们可以先来看一下样例:

代码语言:javascript
复制
>>> v = VendingMachine('teaspoon', 10)
>>> v.restock(2)
'Current teaspoon stock: 2'

>>> m = MissManners(v)
>>> m.ask('vend')
'You must learn to say please first.'
>>> m.ask('please vend')
'You must deposit $10 more.'
>>> m.ask('please deposit', 20)
'Current balance: $20'
>>> m.ask('now will you vend?')
'You must learn to say please first.'
>>> m.ask('please hand over a teaspoon')
'Thanks for asking, but I know not how to hand over a teaspoon.'
>>> m.ask('please vend')
'Here is your teaspoon and $10 change.'

>>> double_fussy = MissManners(m) # Composed MissManners objects
>>> double_fussy.ask('deposit', 10)
'You must learn to say please first.'
>>> double_fussy.ask('please deposit', 10)
'Thanks for asking, but I know not how to deposit.'
>>> double_fussy.ask('please please deposit', 10)
'Thanks for asking, but I know not how to please deposit.'
>>> double_fussy.ask('please ask', 'please deposit', 10)
'Current balance: $10'

其实整个的逻辑并不复杂,我们在创建MissManners时需要传入一个对象。之后我们通过字符串的形式调用对象,但必须要加上敬语please

所以我们可以先来判断字符串的开头是否包含please,如果不包含,直接返回。如果包含,解析出please之后的内容,它就是我们要调用的object中的函数名。可以通过hasattr函数来判断object中是否有这个函数,如果存在,即返回调用结果,否则返回提示语。

VendingMachine类也在之前的作业当中出现过,如果不清楚原理,下面也给出了完整代码。

代码语言:javascript
复制
class VendingMachine:
    """A vending machine that vends some product for some price.
    """
    def __init__(self, product, price):
        self.product = product
        self.price = price
        self.stock = 0
        self.balance = 0

    def restock(self, n):
        self.stock += n
        return 'Current {0} stock: {1}'.format(self.product, self.stock)

    def deposit(self, n):
        if self.stock == 0:
            return 'Machine is out of stock. Here is your ${0}.'.format(n)
        self.balance += n
        return 'Current balance: ${0}'.format(self.balance)

    def vend(self):
        if self.stock == 0:
            return 'Machine is out of stock.'
        difference = self.price - self.balance
        if difference > 0:
            return 'You must deposit ${0} more.'.format(difference)
        message = 'Here is your {0}'.format(self.product)
        if difference != 0:
            message += ' and ${0} change'.format(-difference)
        self.balance = 0
        self.stock -= 1
        return message + '.'

class MissManners:
    """A container class that only forwards messages that say please.
    """
    def __init__(self, obj):
        self.obj = obj

    def ask(self, message, *args):
        magic_word = 'please '
        if not message.startswith(magic_word):
            return 'You must learn to say please first.'
        "*** YOUR CODE HERE ***"
        left_message = message[len(magic_word):]
        if hasattr(self.obj, left_message):
            return getattr(self.obj, left_message)(*args)
        else:
            return 'Thanks for asking, but I know not how to {}.'.format(left_message)

总体上来说,没有什么难度,就是hasattrgetattr这两个方法的常规用法。

好了,关于这两次作业就先聊到这里,感谢大家的阅读。

喜欢本文的话不要忘记三连~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Coder梁 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Next Fibonacci Object
  • Vending Machine
  • Digits
  • Miss Manners
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档