【发布时间】:2015-10-11 01:04:11
【问题描述】:
我一直在努力做到这一点,但我实际上无法做到这一点令人沮丧。我什至对发布我编写的代码感到尴尬。我是递归新手,所以我需要一些帮助。 我正在尝试做的是像这样定义一个函数星:
> (star 5)
*
**
***
****
*****
它应该在下一行打印*,然后是**,依此类推,直到你输入的数字。 一个经典的初学者练习,但在带有递归的 Racket 中要困难得多。谢谢。
【问题讨论】:
我一直在努力做到这一点,但我实际上无法做到这一点令人沮丧。我什至对发布我编写的代码感到尴尬。我是递归新手,所以我需要一些帮助。 我正在尝试做的是像这样定义一个函数星:
> (star 5)
*
**
***
****
*****
它应该在下一行打印*,然后是**,依此类推,直到你输入的数字。 一个经典的初学者练习,但在带有递归的 Racket 中要困难得多。谢谢。
【问题讨论】:
您没有发布您尝试的解决方案,所以我只能给您一些提示,希望您自己得出答案;只需填写空白;)。
如果我们把问题分成两部分会更容易。首先,弄清楚如何创建一个重复另一个字符串n 次的字符串——让我们为此编写一个辅助过程:
(define (repeat s n)
(cond ((zero? n) <???>) ; base case
(else
(string-append s
(repeat s <???>))))) ; advance recursion
请注意,我们还可以使用make-string 来获得更简单的答案,如@ThrowawayAccount3Million 的答案所示。无论如何,结果应该是这样的:
(repeat "*" 3)
=> "***"
现在我们只需要在我们的star 过程中在正确的位置调用它:
(define (star n)
(cond ((not (zero? n))
(star <???>) ; advance recursion
(displayln (repeat <???> <???>))))) ; call helper
就是这样!
(star 5)
=> *
**
***
****
*****
【讨论】:
仅使用递归从 1 迭代到 5:
(let loop ((n 1))
(cond ((> n 5)
(void))
(else
(displayln ...)
(loop (+ 1 n)))))
上面相当于定义了一个名为loop的函数,然后调用它,像这样:
(define (loop n)
(cond ((> n 5)
(void))
(else
(displayln ...)
(loop (+ 1 n)))))
(loop 1)
这可以出现在另一个函数的主体内:
(define (stars num-stars)
(define (loop ...
要打印 n 颗星:
(displayln (make-string n #\*))
Racket 不是原始的 Scheme,它有自己的循环结构,您也可以使用它:
(for ((n (in-range 1 6)))
(displayln ...))
还有一个库实现了 Common Lisp/Maclisp 中的 loop 构造(也有 Chicken Scheme 和 EMACS Lisp 的实现):
(require (planet jphelps/loop)) ;; Download, install, and
;; use the library.
(loop for n from 1 to 5
do (displayln ...))
【讨论】:
这是编写带有递归函数调用的循环的一种方法:
(define (loop from to f done)
(if (< from to)
(begin
(f from)
(loop (+ from 1) to f done))
(done)))
如果from 小于to,则循环使用参数from 调用函数f,然后使用from+1 调用loop。如果from 等于to,则循环完成并调用函数done。
Example:
> (loop 0 5 display newline)
01234
让我们定义一个显示单个星的助手:
(define (display-star _)
(display "*"))
我们现在可以定义display-stars,它显示n 星号并通过打印换行符结束。
(define (display-stars n)
(loop 0 n display-star newline))
原来的问题现在可以这样解决了:
> (loop 1 6 display-stars void)
*
**
***
****
*****
完整的程序:
#lang racket
(define (loop from to f done)
(if (< from to)
(begin
(f from)
(loop (+ from 1) to f done))
(done)))
(define (display-stars n)
(loop 0 n display-star newline))
(loop 1 6 display-stars void)
使用循环构造for的替代解决方案:
> (for ([i (in-range 1 6)])
(for ([j i])
(display "*"))
(newline))
*
**
***
****
*****
【讨论】: