十分に活用できていませんnreconc
。do
とに基づくソリューションを次に示しreconc
ます。アイデアは、置換する必要がある要素の位置に到達するまで、リストから要素を逆の順序で蓄積しながらリストをたどることです。次に、ビットをくっつけます。つまり、蓄積してきたリストを逆にして、新しい要素とその後の末尾から構築されたリストに追加します。
(defun add (number index list)
(do ((head '() (list* (first tail) head))
(tail list (rest tail))
(index index (1- index)))
((zerop index)
(nreconc head (list* (+ number (first tail))
(rest tail))))))
CL-USER> (add 5 2 '(3 1 4 6 7))
(3 1 9 6 7)
これらの値が時間の経過とともにどのように変化するかを確認する価値があります。より多くの数値を含む例を考えてみましょう。各反復におけるhead
、tail
、およびの値を見てみましょう。index
CL-USER> (add 90 5 '(0 1 2 3 4 5 6 7 8 9))
(0 1 2 3 4 95 6 7 8 9)
head: ()
tail: (0 1 2 3 4 5 6 7 8 9)
index: 5
head: (0)
tail: (1 2 3 4 5 6 7 8 9)
index: 4
head: (1 0)
tail: (2 3 4 5 6 7 8 9)
index: 3
head: (2 1 0)
tail: (3 4 5 6 7 8 9)
index: 2
head: (3 2 1 0)
tail: (4 5 6 7 8 9)
index: 1
head: (4 3 2 1 0)
tail: (5 6 7 8 9)
index: 0
にたどり着いたら、 に足してと一緒にすることで、残りの最終結果0
を得ることができます。つまり、number
(car tail)
(cdr tail)
(list* (+ (car tail) number) (cdr tail)
生産する
(95 6 7 8 9)
そして、nreconc
take および get に使用し(4 3 2 1 0)
ます(95 6 7 8 9)
。(0 1 2 3 4 95 6 7 8 9)
つまり、
(nreconc (list 4 3 2 1 0) '(95 6 7 8 9))
;=> (0 1 2 3 4 95 6 7 8 9)
何らかの理由で を使用できない場合do
、たとえばこれが宿題である場合でも、そのトレースはアキュムレータを使用してこれの直接再帰バージョンを作成するのに十分な情報を提供するはずです。ただし、何があっても、リストを作成(または) したり、いくつかのリストを一緒に (または、組み合わせたり、または) しreverse
たりできる必要があります。nreverse
append
nconc
revappend
nreconc