scheme string-append?递归以复制字符串

时间:2014-10-29 21:10:42

标签: scheme racket

设计一个名为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))) 

但在这种情况下如何申请?感谢。

2 个答案:

答案 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子句的蹦床。它:

    1. 在字符列表上开始递归调用。
    2. 将递归调用返回的字符列表转换回字符串。
    3. 附加原始字符串。这允许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最初替换机器代码的事实,并且可以调整为更接近金属。