设计一个名为string-dup的程序,它使用String和一个数字n并返回一个字符串,该字符串是s次的串联,每个s的实例之间有空格,即
(string-dup" a" 3)=> " a a a" 不使用复制但我想我们可以使用string-append。
到目前为止我得到了
(define (string-dup s n)
(cond
[(zero? n) ""]
[else
(cond
[(= n 1 ) s]
[(> n 1 )(string-dup (string-append s " ") (sub1 n))])]))
然而,这只允许我有一个字符串" a"。我知道在列表中你可以做什么
(cons s (string-cp s (sub1 n)))
但在这种情况下如何申请?感谢。
答案 0 :(得分:2)
对string-dup
的递归调用需要是string-append
的参数,而不是相反。{这是一个更正(和重构)的版本:
(define (string-dup s n)
(cond
[(< n 1) ""]
[(= n 1) s]
[else (string-append s " " (string-dup s (sub1 n)))]))
答案 1 :(得分:1)
当性能很重要时(例如n
很大),直接使用字符列表可能会显着提高速度。下面的函数faster-string-dup
:
第1-5行执行基本的条件分支,如接受的答案。
第6行开始关闭else
子句中的两个本地值。
第7-8行将s1
定义为string
转换为字符列表appended
到包含单个字符#\space
的列表。
第9-14行定义尾递归函数next
。它需要两个参数:一个整数n
和一个字符列表acc
并返回一个字符列表。
第15行是else
子句的蹦床。它:
s1
以空格结束而不是从空格开始。这与我们对问题的直观理解更加一致 - 我们为每个复制添加字符串和空格。1: (define (faster-string-dup s n) 2: (cond 3: [(< n 1) ""] 4: [(= n 1) s] 5: [else 6: (letrec 7: ((s1 (append (string->list s) 8: (list #\space))) 9: (next (lambda (n acc) 10: (if (> n 2) 11: 12: (next (sub1 n) 13: (append s1 acc)) 14: acc)))) 15: (string-append (list->string (next n s1)) s))]))
从命令行使用Racket 6.1进行时间比较,其中:
string-dup
是接受的答案
duplications
是10,000
dump
只是一个可变的变量,可以防止大量的丝网印刷。
与接受的答案相比,显示出更快的执行速度。
-->(time (set! dump (string-dup "string" duplications)))
cpu time: 1125 real time: 1129 gc time: 262
-->(time (set! dump (faster-string-dup "string" duplications)))
cpu time: 3 real time: 2 gc time: 0
Scheme和其他Lisps通过促进更高级别的编程提供的功能有时会掩盖Lisps最初替换机器代码的事实,并且可以调整为更接近金属。