【问题标题】:What code do I need for recursive programming?递归编程需要什么代码?
【发布时间】:2017-04-18 06:16:22
【问题描述】:

目前我在 CS 的离散结构课程中,我们被分配了一个 Python 编程任务来学习递归。他给了我们三个模块,他希望我们实现代码以使函数给出 True 或 False 变量。这是他的代码:

class WrongTypeArgumentException( Exception ): pass

def car(lst):
    """
    The first of the 3 primitive functions: return the first element of a 
    sequence. 

    .. note:: The Law of Car: The `car` function is only defined for non-empty lists.

    :param lst: a non-empty sequence; passing an empty sequence will raise an exception.
    :type lst: tuple
    :returns: an object
    :rtype: object
    """
    if type(lst) is not tuple: 
        raise WrongTypeArgumentException("Argument is not a list.")
    if len(lst)==0:
        raise WrongTypeArgumentException("List has no element") 
    if len(lst)>=1:
        return lst[0]

def cdr( lst ):
    """ The second of the 3 primitive functions: return a sequence, minus the first element.

    .. note:: The Law of Cdr: The `cdr` function is only defined for non-empty lists; the `cdr` of any non-empty list is always another list.


    :param lst: a non-empty sequence; passing an empty sequence will raise an exception.
    :type lst: tuple
    :returns: a tuple; if the sequence has only one element, return an empty sequence.
    :rtype: tuple
    """
    if type(lst) is not tuple:
        raise WrongTypeArgumentException("Argument is not a list.")
    if len(lst)==0:
        raise WrongTypeArgumentException("Cannot cdr on an empty list.")
    if len(lst)==1:
        return ()
    return lst[1:]

def cons( a, lst):
""" The third of the 3 primitive functions: return the sequence created by 
adding element `a` to the sequence `lst`.

.. note:: The Law of Cons: the primitive `cons` takes two arguments; the 
second argument to `cons` must be a list; the result is a list.

:param a: an object
:param lst: a tuple
:type a: object
:type lst: tuple
:returns: the tuple resulting from adding parameter `a` in front of sequence 
`lst`.
:rtype: tuple
"""
if type(lst) is not tuple:
    raise WrongTypeArgumentException("Argument is not a list.")
return (a,) + lst



def copy_sequence( seq ):
    """ Return the copy of a sequence, recursively.

    :param seq: the sequence to be copied
    :type seq: tuple
    :returns: a tuple, identical to the sequence that has been passed in
    :rtype: tuple
    """ 
    if seq == ():
        return ()
    print('seq={} CONSing {} to copy_sequence( {} )'.format(seq, car(seq), 
    cdr(seq)))
    return cons( car(seq), copy_sequence( cdr( seq) ))

def reverse_sequence( seq ):
    """ Return a sequence, in the reverse order, recursively.

    :param seq: the sequence to be reversed.
    :type seq: tuple
    :returns: a tuple, with the same elements, in the reverse order.
    :rtype: tuple
    """ 

    ## A function in a function (= inner function), that recursively accumulates
    ## elements in the bag
    def reverse_sequence_recursive( seq, bag):

        if seq == ():
            return bag
        return reverse_sequence_recursive( cdr(seq), cons(car(seq), bag))

    # Calling the inner function, with an empty bag to start with   
    return reverse_sequence_recursive( seq, () )

这是我们应该实现的代码:

def count_sequence( seq ):
    """ Count the elements in a sequence, recursively. PROVIDE AN IMPLEMENTATION (TASK #1). This function should use **car** and **cdr**.

    :param seq: the sequence whose elements are to be counted
    :type seq: tuple
    :returns: the numbers of elements in the sequence
    :rtype: int
    """ 

def search_sequence( seq, item ):
    """ Search a sequence for the given item. PROVIDE AN IMPLEMENTATION (TASK 
    #2). This function should use **car** and **cdr**.

    :param seq: the sequence to be searched.
    :param item: the item to be searched
    :type seq: tuple
    :type item: str
    :returns: True if the item is contained in the sequence, False otherwise.
    :rtype: bool
    """ 
    ## YOUR CODE HERE #1. Base Case 2. Recursive Call 3. RC steps toward the 
    base case.  
    pass

最后,这是他提供的测试函数,以便实际测试我们的代码是否正确。

class PyLisp_unittest( unittest.TestCase ):
    sandwich = ("jelly","butter", "mustard", "bread", "pickles", "jam", 
    "cheese")

    def test_copy_sequence_0(self):
        """ Read empty tuple """
        sandwich = ()
        self.assertEqual( copy_sequence( sandwich ), ())

    def test_copy_sequence_1(self):
        """ Read single-element tuple"""
        sandwich = ('mustard',)
        self.assertEqual( copy_sequence( sandwich ), ('mustard',))

    def test_copy_sequence_2(self):
        """ Read 7-element tuple"""
        sandwich = ("jelly","butter", "mustard", "bread", "pickles", "jam", "cheese")
        self.assertEqual( copy_sequence( sandwich ), sandwich)


    def test_reverse_sequence_0(self):
        """ Reverse empty tuple """
        sandwich = ()
        self.assertEqual( reverse_sequence( sandwich ), ())

    def test_reverse_sequence_1(self):
        """ Reverse single-element tuple"""
        sandwich = ('mustard',)
        self.assertEqual( reverse_sequence( sandwich ), ('mustard',))

    def test_reverse_sequence_2(self):
        """ Reverse 7-element tuple"""
        sandwich = ("jelly","butter", "mustard", "bread", "pickles", "jam", "cheese")
        self.assertEqual( reverse_sequence( sandwich ), sandwich[::-1])

    def test_count_sequence_0(self):
        """ Count empty tuple """
        sandwich = ()
        self.assertEqual( count_sequence( sandwich ), 0)

    def test_count_sequence_1(self):
        """ Count single-element tuple"""
        sandwich = ('mustard',)
        self.assertEqual( count_sequence( sandwich ), 1)

    def test_count_sequence_2(self):
        """ Count 7-element tuple"""
        sandwich = ("jelly","butter", "mustard", "bread", "pickles", "jam", "cheese")
        self.assertEqual( count_sequence( sandwich ), 7)

    def test_search_sequence_0(self):
        """ Search empty tuple """
        sandwich = ()
        self.assertEqual( search_sequence( sandwich, 'ham' ), False)

    def test_search_sequence_size_1_1(self):
        """ Search  single-element tuple: successful search"""
        sandwich = ('mustard',)
        self.assertEqual( search_sequence( sandwich, 'mustard' ), True)

    def test_search_sequence_size_1_2(self):
        """ Search single-element tuple: unsuccessful search"""
        sandwich = ('mustard',)
        self.assertEqual( search_sequence( sandwich, 'ham' ), False)

    def test_search_sequence_size_7_1(self):
        """ Search 7-element tuple: successful search"""
        sandwich = ("jelly","butter", "mustard", "bread", "pickles", "jam", 
        "cheese")
        self.assertEqual( search_sequence( sandwich, 'pickles'), True)

    def test_search_sequence_size_7_2(self):
        """ Search 7-element tuple: unsuccessful search"""
        sandwich = ("jelly","butter", "mustard", "bread", "pickles", "jam", 
        "cheese")
        self.assertEqual( search_sequence( sandwich, 'pear'), False)

他没有就这些材料做过任何演讲,也没有人 100% 确定该做什么。我尝试与同行导师会面,他并没有真正提供太多帮助,只是重新讨论了序列的教科书定义,而不是如何实现代码。所以我想我在问代码会是什么样子。我需要在count_sequence(seq)search_sequence(seq, item): 函数中添加什么。谢谢!!!

【问题讨论】:

    标签: python function recursion sequence computer-science


    【解决方案1】:

    你被要求实现的东西是微不足道的,所以不要惊慌。

    count_sequence(seq)
    

    这是两者中较容易的。如果seq 为空,则返回零。您可以在讲师的其他函数中找到 empty 的示例测试,例如 copy_sequence()

    如果 seq 不为空,则返回 1 加上在 seq 的尾部 (cdr()) 上递归调用 count_sequence() 的结果。就是这样。

    这可以通过一个if 语句来实现,该语句的主体中包含一个return 语句,涵盖了两种情况之一。 if 语句后跟 return 语句,涵盖另一种情况。

    search_sequence(seq, item)
    

    这只是稍微多一点的代码。如果seq 为空,则这次返回False,因为它是一个布尔(谓词)函数。如果它不为空,请将 itemseq 的第一项 (car()) 进行比较。如果相同,返回True

    否则,返回在同一 item 上递归调用 search_sequence() 的结果,但返回 seq 的余数 (cdr())。这个递归调用的真假就是答案,你不需要检查它,只需返回它。

    这里有三种情况,因此可以使用两个if 语句来实现,每个语句返回一个值,最后一个return 语句涵盖第三种情况。

    【讨论】:

    • 您不必逐字逐句,只需了解代码的外观即可。
    • @MacKenzyReynolds,我已经添加了代码可能是什么样子的想法。我的解释包含的字符比代码解决方案多六倍——它们真的很琐碎。
    • 好的。无论如何谢谢。我想我会继续问,当我以您指定的方式添加代码时,我确实收到了这个错误。回溯(最后一次调用):文件“C:\Users\MacKenzy\Desktop\pylisp_skeleton.py”,第 204 行,在 test_count_sequence_2 self.assertEqual(count_sequence(sandwich), 7) count_sequence(cdr(seq)+1) TypeError :只能将元组(不是“int”)连接到元组
    • @MacKenzyReynolds,我说,“1 加上 ... 在 seq 的 ...cdr() 上调用 count_sequence() 的结果”。您所做的是在 1 加上 seq 的 cdr() 的结果上调用 count_sequence()不一样。您应该能够判断这不是正确的方法,因为cdr() 可以返回任何类型,所以简单地加 1 是不正确的,因为cdr() 可能不会返回数字.但是count_sequence() 总是返回一个数字。
    猜你喜欢
    • 2012-04-24
    • 2012-08-04
    • 1970-01-01
    • 2022-11-21
    • 2015-01-13
    • 2022-01-20
    • 2018-07-13
    • 1970-01-01
    • 2018-05-31
    相关资源
    最近更新 更多