2012-03-20 87 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) ...))) 

是很明显现在如何解决它?