Сокращение списка до суммы разностей его элементов - PullRequest
0 голосов
/ 14 декабря 2018

У меня есть простой список с всегда четным числом целых чисел, например

(42 38 15 5)

, и я хочу вычислить общую сумму разности его пар, т.е.

(+ (- 42 38) (+ 15 5)) --> 14

Это может быть 2, 4 или более элементов, но это всегда будет четное число.Я думал, что для этого есть способ с использованием метода Reduce, но я не вижу способа получить правильные пары.

Есть ли простой способ сделать это или проще изменить структуру списка?Например, что-то вроде

((42 38) (15 5))

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018

Вы также можете использовать более короткую петлю:

(loop 
   while list 
   sum (- (pop list)
          (pop list)))
0 голосов
/ 14 декабря 2018

Вы можете использовать loop для этого:

(loop :for (a b) :on list :by #'cddr
      :sum (- a b))

Конструкция for - on выходит за рамки списка, for может разрушить это, by даетпошаговая функция (по умолчанию #'cdr).

Если вы абсолютно хотите использовать функции более высокого порядка, вам нужно сначала разбить раздел (как вы уже догадались) или найти механизм пошагового выполнения.

Разбиениеснова можно сделать через loop или через мошенничество.После этого вы можете уменьшить:

(reduce (lambda (sum pair)
          (+ sum (apply #'- pair)))
        (partition 2 list)
        :initial-value 0)

В качестве альтернативы вы можете думать об этом как о чередующемся сложении и вычитании числа:

(reduce #'+
        (mapcar #'funcall
                (circular-list #'+ #'-)
                list))

(Circular-list от alexandria.)

...