2012-10-03 42 views
1

我似乎無法弄清楚如何編寫此功能。我試圖寫一個函數expand是獲得一個列表lst的形式'(a (2 b) (3 c))的參數,並進行評估,以'(a b b c c c)用球拍實現擴展功能

回答

3

這看起來像功課,所以我不會給你一個直接的答案。相反,我會給你一些正確的方向。最有用的提示是,你應該將問題分成兩個程序,一個用於處理「外部」列表,另一個用於生成在內部子列表中編碼的重複。

注意這兩個過程是相互遞歸的(例如,它們互相呼叫)。 expand程序遍歷列表,而repeat程序重複遍歷重複次數。這是建議的解決方案的總體結構,填充了空白:

; input: lst - list to be processed 
; output: list in the format requested 
(define (expand lst) 
    (cond ((null? lst)    ; if the list is null 
     '())     ; then return null 
     ((not (pair? (car lst))) ; if the first element of the list is an atom 
     (cons <???> <???>))  ; cons the atom and advance the recursion 
     (else     ; if the first element of the list is a list 
     <???>)))    ; call `repeat` with the right params 


; input: n - number of repetitions for the first element in the list 
;  lst - list, its first element is of the form (number atom) 
; output: n repetitions of the atom in the first element of lst 
(define (repeat n lst) 
    (if (zero? n)   ; if the number of repetitions is zero 
     (expand (cdr lst)) ; continue with expand's recursion 
     (cons <???>  ; else cons the atom in the first element and 
      <???>)))  ; advance the recursion with one less repetition 
+0

重複功能流程列表中的單個元素:第一個。當我們在'expand'中首先調用它時,我們沿着整個列表以及存儲在第一個元素中的'n'次數傳遞。在'expand'的遞歸步驟中,我們將在第一個元素中找到的符號(a,b,c等)放在一起,然後繼續遞歸 - 遞減'n'到下一步,直到最後它達到零,我們回到'擴大'。 –

+0

最後一部分幾乎是正確的:你正確傳遞數字'n',但你需要傳遞'lst',而不僅僅是第一個元素 –

+0

我還沒有讓自己清楚,對不起:(我們是傳遞整個list_,只是我們確信第一個元素是''(2 a)'的形式。所以不,第一個???在'repeat'中是'(cadar lst)' –

0

由於這三年前得到的回答是,我不認爲我的家庭作業幫助。只想指出這兩個函數真的不是need是相互遞歸的。作爲replicate是一個相當普遍的功能,我建議:

(define (replicate what n) 
    (if (zero? n) 
     (list) 
     (cons what (replicate what (- n 1))))) 

(define (my-expand xs) 
    (if (empty? xs) 
     (list) 
     (let ((x (first xs))) 
     (if (list? x) 
      (let ((the-number (first x)) 
        (the-symbol (cadr x))) 
       (flatten (cons (replicate the-symbol the-number) 
        (my-expand (rest xs))))) 
      (cons x (my-expand (rest xs))))))) 

當然最好是使用兩個列表並進行壓平在最後,是這樣的:

(define (my-expand xs) 
    (define (inner-expander xs ys) 
    (if (empty? xs) (flatten (reverse ys)) 
     (let ((x (first xs))) 
     (if (list? x) 
      (let ((the-number (first x)) 
        (the-symbol (cadr x))) 
       (inner-expander (rest xs) (cons (replicate the-symbol the-number) ys)))      
      (inner-expander (rest xs) (cons x ys)))))) 
    (inner-expander xs (list))) 
+0

'(flatten(cons ar))'確實是一種矯枉過正 - 你壓扁了整個序列,包括遞歸結果已經變平了,用'(append ar)'代替可能是bett呃在這方面。 –

+0

是的,我知道,只是一個簡單的例子,說明兩個函數可以分離。這個代碼很快從使用兩個列表尾遞歸方法的版本重構 - 在最後一次調用flatten。 – beoliver

+0

'append'並不理想,因爲它重新跟蹤了'replicate'剛剛構建的第一個列表。所以要麼我們只是用'(append-map replicate_ xs)'(用'replicate'來正確處理這兩種情況)希望(或不關心)['append-map'](https://docs.racket -lang.org/srfi/srfi-std/srfi-1.html#append-map)被有效地實現 - 或者目標是通過'setcdr!'尾部自己來創建結果,只需一次完成隨着我們的成長。 –