方案中字符列表的递归

时间:2014-10-21 19:04:05

标签: scheme

我在一个页面中发现了递归问题,其中包含以下内容:

如果一个人输入一个两个连续字母相同的字符串,它应该在它们之间加一个5。例如,如果我输入“hello”

它应该打印“hel5lo”

我在Scheme中完成了以下程序:

(define (function listT)
  (if (empty? listT)
      '()
      (begin
        (if (eq? (car listT) (car (cdr listT)))
            (display 5)
            (display (car listT))
        )))
  (function (cdr listT)))

并测试:

(功能'('h'e' l'l'o))

我遇到的问题是

car: contract violation
  expected: pair?
  given: ()

我想这是因为在某个时刻(汽车(cdr listT))将面临一个空列表,之前已尝试过条件,但仍有一些问题。

是否可以仅使用cdr和car的字符列表进行递归?我的意思是不是使用新的变量,字符串,使用反向或循环?

任何帮助?

由于

4 个答案:

答案 0 :(得分:4)

当列表中只剩下一个字符时会发生这种情况; (cdr listT)将是空列表'(),并且空列表的car未定义。

因此,您需要检查cdr是否为空,例如:

(define (f str)
  (let loop ((lst (string->list str)) (res '()))
    (if (null? lst)
        (list->string (reverse res))
        (let ((c (car lst)))
          (loop (cdr lst) 
                (cons c
                      (if (and (not (null? res)) (char=? c (car res)))
                          (cons #\5 res)
                          res)))))))

或者,不是向前看一个字符,而是转过你的逻辑并跟踪最后一个字符,这个字符被初始化为某个值,在每种情况下都会有所不同(不像第一个解决方案那样优雅):< / p>

(define (f str)
  (list->string
   (let loop ((prev #f) (lst (string->list str)))
     (if (null? lst)
         '()
         (let ((c (car lst)))
           (if (equal? c prev)
               (cons #\5 (cons c (loop c (cdr lst))))
               (cons c (loop c (cdr lst)))))))))

[编辑或者,使用明确的内部程序:

(define (f str)
  (define (inner prev lst)
    (if (null? lst)
        '()
        (let ((c (car lst)))
          (if (equal? c prev)
              (cons #\5 (cons c (inner c (cdr lst))))
              (cons c (inner c (cdr lst)))))))
  (list->string (inner #f (string->list str))))

测试:

> (f  "hello")
"hel5lo"
> (f "helo")
"helo"
> (f "heloo")
"helo5o"

旁注:不要双引号:

> '('h 'e 'l 'l 'o)
'('h 'e 'l 'l 'o)
> (car '('h 'e 'l 'l 'o))
''h

这可能不是你所期望的。代替:

> '(h e l l o)
'(h e l l o)
> (car '(h e l l o))
'h

> (list 'h 'e 'l 'l 'o)
'(h e l l o)
> (car (list 'h 'e 'l 'l 'o))
'h

另请注意,这些是符号,而由于您从字符串开始,您需要字符:

> (string->list "hello")
'(#\h #\e #\l #\l #\o)

编辑2

我看到你仍然在努力解决我的问题。这是一个应该尽可能少的解决方案,我希望是这样的:

(define (f lst (prev #f))
  (unless (null? lst)
    (when (equal? (car lst) prev) (display "5"))
    (display (car lst))
    (f (cdr lst) (car lst))))

甚至

(define (f lst)
  (unless (null? lst)
    (display (car lst))
    (when (and (not (null? (cdr lst))) (equal? (car lst) (cadr lst)))
      (display "5"))
    (f (cdr lst))))

测试:

> (f '(h e l l o))
hel5lo
> (f '(h e l o))
helo
> (f '(h e l o o))
helo5o

答案 1 :(得分:1)

我找到了一个解决方案:

(define (func lisT)
  (if (empty? (cdr lisT))
      (display (car lisT))
      (begin
        (if (eq? (car lisT) (car (cdr lisT)))
            (begin
              (display (car lisT))
              (display 5)
             )
            (display (car lisT))
        )
        (func (cdr lisT))
        )
  ))

答案 2 :(得分:0)

这是一个只包含一个顶级递归函数的解决方案:

(define (insert list item)
  (if (< (length list) 2)                    ;; not enough elements to compare?
      list                                   ;; then just return the input
      (let ((first (car list))               ;; capture the first element,
            (second (cadr list))             ;; the second element,
            (rest (insert (cdr list) item))) ;; and the recursively processed tail
          (cons first                        ;; construct a list with the first element
                (if (eq? first second)       ;; compare the first two and return either
                    (cons item rest)         ;; the item before the rest
                    rest)))))                ;; or just the rest

它将列表和要插入每两个连续相同元素之间的项目作为输入。它不会显示任何内容,而是返回另一个包含插入结果的列表。例如,

(insert '(1 2 2 3 3 3 2 2 1) 0)

结果

(1 2 0 2 3 0 3 0 3 2 0 2 1)

这有望解决您的问题并为进一步的实验奠定基础。

答案 3 :(得分:0)

这是从列表到列表的简单功能:

(define (add5s s)
    (cond ((null? s) s)
        ((null? (cdr s)) s)
        ((equal? (car s) (cadr s)) (cons (car s) (cons 5 (add5s (cdr s)))))
        (else (cons (car s) (add5s (cdr s))))
    )
)

列表:

  1. 为空
  2. 有一个元素
  3. 以两个相等的元素开头
  4. 以两个不相等的元素开头
  5. 在连续相等元素之间放置5的列表分别为:

    1. 列表
    2. 列表
    3. 第一个元素后跟一个5,然后是其余部分,其中5个放在连续的相等元素之间
    4. 第一个元素后跟其余部分,连续相等元素之间放置5个
    5. Scheme字符串不是字符列表或符号列表。如果要输入和输出字符串,则应使用相应的字符串运算符。或者编写一个定义这个函数的函数,用string-&gt;输入字符串列表调用它,并输出list-&gt;这个结果列表的字符串。或者像这样的函数,但是在string-&gt;的输入字符串列表上分支,并输出list-&gt;这个函数返回的字符串。

      (目前还不清楚要编写什么代码。你说&#34;输入一个字符串&#34;,但你的&#34;经过测试的代码是一个以列表作为参数的函数,而不是从一个端口读取。你说&#34;放一个5&#34;但你打印参数列表元素或5通过display到一个端口,而不是返回一个参数类型的值你举一个例子来传递一个参数,这个参数是一个带引号的符号列表,而不仅仅是符号,更不用说符号了。(如果你想传递一个符号列表,那么使用&#39;(hello)或(list&#39; h&#39; l&#39; o)。)准确说出要生成的内容,例如,具有什么参数,返回值和对端口的影响的函数。)