列表操作和结束案例

时间:2014-02-12 21:18:43

标签: scheme

我正在尝试学习计划(扩大思维而不是作业),而且与程序语言相比,我仍在努力解决其差异。

请考虑以下事项:

在过程语言术语中,我有两个基于零的整数数组a和b,长度分别为n> = 1和n + 1,并且想要输出长度为n + 1的数组c,其中:

c [0] = b [0] + a [0]; c [n] = b [n] + a [n-1]; c [i] = b [i] + Max(a [i-1],a [i])(1< = i< = n-1)

所以,例如,如果a = [5,6,1]且b = [1,2,3,4],那么c = [6,8,9,5]

我只能用程序语言来做这件事。例如在Pascal中:

function MaxAdd(a, b : array; n : integer) : array;
var
  i : integer;
begin
  c[0] = b[0] + a[0];
  c[n] = b[n] + a[n-1];
  for i = 1 to n-1 do
    c[i] = b[i] + Max(a[i-1],a[i]);
result := c;
end;

我正在尝试使用我使用两个整数列表而不是数组的方案。以下作品,但对我来说似乎很笨拙。有没有更简洁的方法来处理终结案件?

 (define (max a b)
   (if (> a b) a b)) 

 (define (maxaddhelper l1 l2)
   (cond 
     ((= 1 (length l1)) (list (+ (car l1) (car l2))))
     (else (cons 
       (+ (max (car l1) (car (cdr l1))) (car l2)) 
       (maxaddhelper (cdr l1) (cdr l2))      ))))

 (define (maxadd l1 l2)
   (cond 
     ((= 1 (length l1)) (list (+ (car l1) (car l2)) (+ (car l1) (car (cdr l2)))))
     (else 
       (cons (+ (car l1) (car l2)) 
       (maxaddhelper l1 (cdr l2)) ))))

测试输出......

 Welcome to DrRacket, version 5.93 [3m].
 Language: scheme; memory limit: 128 MB.
 > (maxadd (list 5 6 1) (list 1 2 3 4))

 (6 8 9 5)
 >     

2 个答案:

答案 0 :(得分:2)

此问题会大量使用索引,因此更适合于方案vector - 它提供与数组相同的基于索引的高效操作。例如,Racket中的惯用解决方案是:

(define (max-add a b)
  (let* ([n (vector-length a)]
         [c (make-vector (add1 n))])
    (vector-set! c 0 (+ (vector-ref b 0)
                        (vector-ref a 0)))
    (vector-set! c n (+ (vector-ref b n)
                        (vector-ref a (sub1 n))))
    (for ([i (in-range 1 n)])
      (vector-set! c i (+ (vector-ref b i)
                          (max (vector-ref a (sub1 i))
                               (vector-ref a i)))))
    c))

(max-add '#(5 6 1) '#(1 2 3 4))
=> '#(6 8 9 5)

没有人说Scheme中的所有问题都必须使用链表来解决,这个例子特别表明有时你必须选择更适合这项工作的数据结构。如果列表是必需的,那么list->vectorvector->list将允许您在数据结构之间来回切换。

修改

正如@uselpa所提到的,也可以仅使用列表解决这个问题,更多的是SICP的精神和Scheme的惯用语。为了完整起见,这是我的实现,比其他答案更简单,更容易理解:

(define (max-add a b)
  (let loop ([a a] [b b] [prev (car a)])
    (if (null? a)
        (list (+ (car b) prev))
        (cons (+ (car b) (max prev (car a)))
              (loop (cdr a) (cdr b) (car a))))))

(max-add '(5 6 1) '(1 2 3 4))
=> '(6 8 9 5)

答案 1 :(得分:1)

FWIW,这是一个在纯方案中实现的基于列表的解决方案:

(define (maxadd lst1 lst2)
  (let loop ((last (car lst1)) (lst1 lst1) (lst2 lst2))
    (if (null? lst2)
        '()
        (let ((ca1 (car lst1)) (cd1 (cdr lst1)))
          (cons (+ (max last ca1) (car lst2))
                (loop ca1 (if (null? cd1) lst1 cd1) (cdr lst2)))))))

然后

> (maxadd '(5 6 1) '(1 2 3 4))
'(6 8 9 5)