方案运行长度编码

时间:2017-09-23 08:53:13

标签: functional-programming scheme

问题是:

写一个函数(编码L),它取一个原子列表L和运行长度编码列表,使得输出是一个表格对的列表(值长度),其中第一个元素是一个值,第二个元素是一个值是编码列表中出现值的次数。

例如:

(encode '(1 1 2 4 4 8 8 8)) ---> ((1 2)(2 1)(4 2)(8 3))

这是我到目前为止的代码:

(define (encode lst)
  (cond 
    ((null? lst) '())
    (else ((append (list (car lst) (count lst 1)) 
                   (encode (cdr lst)))))))

(define (count lst n)
  (cond 
    ((null? lst) n)
    ((equal? (car lst) (car(cdr lst))) (count (cdr lst) (+ n 1)))
    (else (n)))))

所以我知道这不会起作用,因为我无法真正想到一种方法来有效地计算列表中特定原子的数量,因为我会迭代列表。此外,在继续计算列表中的下一个唯一原子之前,保存先前的(值长度)对。基本上,我的主要问题是提出一种方法来保持我在列表中看到的原子数量的计数来创建我的(值长度)对。

1 个答案:

答案 0 :(得分:1)

您需要一个辅助函数,该函数将count作为附加参数。您检查前两个元素是否相互对齐,如果匹配则是通过增加其余元素来递减,或者通过在递归调用中进行匹配并将计数重置为1来递归。

以下是您需要实施<??>部分的草图:

(define (encode lst)
  (define (helper lst count)
    (cond ((null? lst) <??>)
          ((null? (cdr lst)) <??>))
          ((equal? (car lst) (cadr lst)) <??>)
          (else (helper <??> <??>))))
  (helper lst 1))

;; tests
(encode '())              ; ==> ()
(encode '(1))             ; ==> ((1 1))
(encode '(1 1))           ; ==> ((1 2))
(encode '(1 2 2 3 3 3 3)) ; ==> ((1 1) (2 2) (3 4))

使用名为let 表达式的

这种在状态变量中使用带有状态变量的递归辅助过程的技术在Scheme中是如此常见,以至于有一种特殊的let形式可以让你更好地表达模式

(define (encode lst)
  (let helper ((lst lst) (count 1))
    (cond ((null? lst) <??>)
          ((null? (cdr lst)) <??>))
          ((equal? (car lst) (cadr lst)) <??>)
          (else (helper <??> <??>)))))

对您问题中代码的评论:它有多余的括号..

((append ....))表示调用(append ....)然后调用该结果,就好像它是一个函数一样。由于append会使列表像ERROR: application: expected a function, got a list一样失败。

(n)表示将n称为函数。请记住+只是一个变量,例如n。 Scheme中的函数和其他值之间没有区别,当你放置像(if (< v 3) + -)这样的表达式时,如果用括号括起来调用它((if (< v 3) + -) 5 3); ==> 8 or 2

,它需要求值。