示例:(反向列表(列表1 2 3 4))=> 4321注意:我不允许使用string-> num或num->字符串或反向。
因此消耗了列表并创建了反向编号(不再是列表)
我遇到了递归逻辑问题。
(define (reverse-list lofd)
(cond [(empty? lofd) empty]
[else (+ (* (exp 10 (something that starts at 0 and adds one extra everytime))
(first lofd))
(convert-to-decimal (rest lofd)))]))
我的代码启动并将第一个数字转换为num1 * 10 ^ 0,然后添加递归的数字。
我遇到的问题是如何使它在递归时指数为10 ^ 0然后上升到1,2,3 ......直到列表的长度减去1?我的逻辑/模板也是正确的吗?谢谢!
答案 0 :(得分:4)
强烈建议:在精神和信件中遵循Design Recipe for list structures。这个问题足够新颖,你不会轻易搞定。您需要Design Recipe步骤所需的额外支持。
在这种特定情况下,你真的需要一套很好的例子(测试用例)来帮助你,因为这个问题的解决方案并不是很明显。这很棘手,因为这个功能不是从列表到列表:它是从列表到数字,所以你必须有一个强大的套件来帮助你发现愚蠢的错误。
例如,该怎么办?
(check-expect (reverse-list empty) <fill-me-in>)
是?我们应该考虑空列表吗?这是一个奇怪的输入吗?这是否合情合理? 合同是否说我们必须处理空列表作为输入,还是可以保证它只接受非空列表?这是您需要预先解决的问题!你现在在代码中所拥有的东西当然不是正确的,因为你的合同类型......好吧,你没有正式表达合同,但是一旦你做了,你就会发现基本情况必须是不同的比你到目前为止写的还要多。
在引用的关于Design Recipe的链接中,第5部分至关重要:一旦掌握了函数模板,就需要了解自然递归计算的内容。使用具体的测试用例来帮助。通过查看代码,您可能已跳过此步骤,因为您编写的代码似乎没有考虑这样的问题:“自然递归计算的是什么?”
具体而言,如果我们这样做:
(reverse-list (list 1 2 3 4))
我们想要答案是什么?你自己说:
(reverse-list (list 1 2 3 4)) ==> 4321
考虑自然递归将是什么:
(reverse-list (list 2 3 4))
这有什么价值?我们知道它一定是
(reverse-list (list 2 3 4)) ==> 432
一旦你搞清楚了,就问问自己:自然递归的价值与原问题的答案有任何关系吗?
鉴于我们正试图解决:
(reverse-list (list 1 2 3 4)) ===> 4321
我们有1
(列表的第一部分)和432
(来自自然递归),我们可以将1
和432
放在一起某种方式获得4321
?
重复此操作以获取一些示例。少数人,我的意思是不止一个。 :)为这些例子具体做这件事,你的大脑将更好地拍摄模式匹配和推广,以弄清楚递归案例的代码必须是什么。
也就是说,一旦你有足够的练习来确定如何为具体案例找到正确的答案,那么去看看你是否可以用具体的价值表达你所做的事情,回到程序中的原始术语。例如如果你弄明白:
we want to get 4321 out of 1 and 432:
=> 1 + 10 * 432
... other examples you worked out...
让我们用前缀表示法重新表达这些:
we want to get 4321 out of 1 and 432:
=> (+ 1 (* 10 432))
... other examples you worked out...
哪些部分正在发生变化?哪些部分保持不变?第一个变化部分代表什么?第二个变化部分代表什么?那就是:
we want to get 4321 out of 1 and 432:
=> (+ 1 (* 10 432))
... other examples you worked out ...
we want to get (reverse-list lst) out of (first lst) and (reverse-list (rest lst))
==> ???
一旦看到模式,那么你已经找到了需要的代码用于递归案例。但请注意,你真的需要一套例子:试图概括出一个具体的例子是不足以让你的大脑看到模式。你的大脑需要通过计算多个例子来重复,才能开始看到模式。
答案 1 :(得分:1)
除了输入列表之外,您还需要传递另一个参数。如果需要,创建一个新的帮助程序(或内部过程,或名为let
等),以使其起作用。这两个参数将跟踪列表中的当前位置,以及当前的指数10.这些内容如下:
(define (reverse-list lofd n)
(cond [(empty? lofd) ; what do we return if the list is empty?
<???>] ; not the empty list! we're building a number
[else ; otherwise add this term, taking the
(<???> <???> ; current element times current 10^n and
(reverse-list <???> <???>))])) ; advance recursion over lofd and n
使用以下初始值调用该过程:
(reverse-list (list 1 2 3 4) 0)
=> 4321
答案 2 :(得分:1)
这是一个Scheme解决方案;它使用像null?,car和cdr这样的东西,它们具有历史重要性但不在你的“学习球拍”词汇中。也许它会说明一种方法。
(define (list->reverse-number l)
(if (null? l)
0
(+ (car l) (* 10 (list->reverse-number (cdr l)))))
如果您坚持尝试使用expt
,那么您可以尝试这样的事情(使用named-let,这可能超出您的水平):
(define (list->reverse-number l)
(let reversing ((l l) (n 0))
(if (null? l)
0
(+ (* (expt 10 n) (car l))
(reversing (cdr l) (+ n 1))))))
但我不知道上述内容是否有效。实际上,这也有效。