2012-03-20 80 views
2

使用抽象函數列表我如何編寫使用抽象列表功能的函數(foldrfoldlmapfilter),且無需遞歸消耗數(list a1 a2 a3 ...)的列表,併產生交替的總和a1 - a2 + a3 ...方案:無遞歸

回答

1

這裏是一個可能的解決方案:

(define (sum-abstract-list-functions lst) 
    (car 
    (foldl 
    (lambda (e acc) 
     (cons (+ (car acc) (* e (cdr acc))) 
      (- (cdr acc)))) 
    '(0 . 1) 
    lst))) 
我只使用 foldlconscarcdr

。訣竅?累加兩個值:實際總和(在累加器的car部分中)和當前符號(累加器的cdr部分中的+/- 1)。累加器的初始值爲0,符號爲+1,最後返回累加器的總和car。使用這樣的:

(sum-abstract-list-functions (list 1 2 3 4 5)) 
> 3 

編輯:

正如已經指出的那樣,這個解決方案是最簡單的的:

(define (sum-abstract-list-functions lst) 
    (foldr - 0 lst)) 
0

這是功課?好了,我們可以分割這個問題分爲兩個子問題:

  • 以列表(a1 a2 a3 a4 ... a2n-1 a2n),或者從它否定元素,產生(a1 (- a2) a3 (- a4) ... a2n-1 (- a2n))
  • 總和結果列表的元素。

第二部分是小事一樁:

(define (sum xs) 
    (foldl + 0 xs)) 

首先是困難的,但它不是太難。您需要轉換列表,同時保持指示您是檢查偶數還是奇數元素的布爾狀態,並且否定或不相應。我可以看到三種方法:

  • 突變方式:將狀態置入關閉狀態,然後傳遞給map。封閉然後修改它的環境從一個呼叫到下一個。
  • 保持摺疊結果中的狀態:摺疊結果是包含「真實」結果和狀態作爲元素的一對。
  • 使用不同種類的抽象列表功能。

這裏的第三種方法的一個實例(如果這是家庭作業,我敢打賭,你的老師可能是不可思議的,你給我了):

(define (contextual-foldr compute-next 
          compute-init 
          advance-context 
          left-context 
          xs) 
    (if (null? xs) 
     (compute-rightmost-result left-context) 
     (compute-next left-context 
        (car xs) 
        (contextual-foldr compute-next 
             compute-init 
             advance-context 
             (advance-context (car xs) left-context) 
             (cdr xs))))) 

(define (contextual-map contextual-fn advance-context left-context xs) 
    (contextual-foldr (lambda (left elem rest) 
         (cons (fn left elem) rest)) 
        '() 
        advance-context 
        left-context 
        xs)) 

(define (alternate-negations xs) 
    (contextual-map (lambda (negate? elem) 
        (if negate? 
         (- elem) 
         elem)) 
        not 
        #f 
        xs)) 
7

這裏有一個提示:

a1 - a2 + a3 - a4 ... aN 

相同

a1 - (a2 - (a3 - (a4 - ... (aN - 0) ...))) 

是很明顯現在如何解決它?