5

この問題では、3 つの (同じ構造の) リストがあります。2 つはすべて数字で、もう 1 つは で埋められていnilます。空のリストの対応する値を、2 つのリストの対応する値を追加して置き換えようとしています。これまでのところ、ループを利用setfして値を置き換えるために使用しています。

(defun add-two-lists (list1 list2 list3)
   (loop for a in list1
        for b in list2
        for c in list3 do
        (setf c (+ a b))))

問題は、この関数が破壊的でないことです。この関数を破壊的にするにはどうすればよいですか?


わかりました、これを行うために an を使用できることは承知しapplyていますが、将来または接線の目的で、ループを使用して同じことを行う方法はありますか?


最後から 2 番目の解決策に頼ることにしました。リストの長さを使用して、リストを横断します。

(defun add-two-lists (list1 list2 list3)
       (loop for x from 0 to (- (list-length list1) 1) do
            (setf (nth x list3) (+ (nth x list1) (nth x list2))))
       (values list3))
4

3 に答える 3

4

1 つの方法を次に示します。

(defun add-two-lists (list1 list2 list3)
   (loop for a in list1
        for b in list2
        for c on list3 do
        (rplaca c (+ a b)))

補遺

ループの代わりにマップを使用する別の方法を次に示します。

(defun add-two-lists (list1 list2 list3)
  (mapl #'(lambda (cl al bl) (rplaca cl (+ (car al) (car bl))))
    list3 list1 list2))
于 2012-06-12T16:54:38.590 に答える
3

Common Lisp はそのための関数を提供します: MAP-INTO

于 2012-06-12T20:30:04.103 に答える
3

ループを使用せずに同じことを行うさらに別の方法 (概念的には似ていますが)

(defun add-two-lists (a b c &optional (d c))
  (if a
    (add-two-lists
     (cdr a) (cdr b)
     (cdr (rplaca c (+ (car a) (car b)))) d) d))

(add-two-lists '(1 2 3 4 5) '(1 2 3 4 5) '(nil nil nil nil nil))

編集

(defun add-two-lists (a b c &optional (d c))
  (if a
    (add-two-lists
     (cdr a) (cdr b)
     (cdr (rplaca c (+ (car a) (car b)))) d) d))

(time
 (dotimes (i 1e6)
   (add-two-lists '(1 2 3 4 5)
          '(1 2 3 4 5)
          '(nil nil nil nil nil))))

;; Evaluation took:
;;   0.077 seconds of real time
;;   0.076004 seconds of total run time (0.076004 user, 0.000000 system)
;;   98.70% CPU
;;   214,723,476 processor cycles
;;   0 bytes consed

(defun add-two-lists-1 (list1 list2 list3)
  (loop for a in list1
     for b in list2
     for c on list3 do
       (rplaca c (+ a b))))

(time
 (dotimes (i 1e6)
   (add-two-lists-1 '(1 2 3 4 5)
          '(1 2 3 4 5)
          '(nil nil nil nil nil))))

;; Evaluation took:
;;   0.060 seconds of real time
;;   0.060004 seconds of total run time (0.060004 user, 0.000000 system)
;;   100.00% CPU
;;   169,395,444 processor cycles
;;   0 bytes consed

編集2

ただし、最適化されたバージョンの動作に注目してください。おそらく、これも YMMV ですが、これは SBCL を使用した 64 ビット Debian で得られるものです。

(defun add-two-lists (a b c &optional (d c))
  (declare (optimize (speed 3) (safety 0)))
  (declare (type list a b c d))
  (if a
    (add-two-lists
     (cdr a) (cdr b)
     (cdr (rplaca
       c 
       (the fixnum
         (+ (the fixnum (car a))
        (the fixnum (car b)))))) d) d))

(time
 (dotimes (i 1e6)
   (add-two-lists '(1 2 3 4 5)
          '(1 2 3 4 5)
          '(nil nil nil nil nil))))

;; Evaluation took:
;;   0.041 seconds of real time
;;   0.040002 seconds of total run time (0.040002 user, 0.000000 system)
;;   97.56% CPU
;;   114,176,175 processor cycles
;;   0 bytes consed

(defun add-two-lists-1 (list1 list2 list3)
  (declare (optimize (speed 3) (safety 0)))
  (loop for a fixnum in list1
     for b fixnum in list2
     for c cons on list3 do
       (rplaca c (the fixnum (+ a b)))))

(time
 (dotimes (i 1e6)
   (add-two-lists-1 '(1 2 3 4 5)
          '(1 2 3 4 5)
          '(nil nil nil nil nil))))

;; Evaluation took:
;;   0.040 seconds of real time
;;   0.040003 seconds of total run time (0.040003 user, 0.000000 system)
;;   100.00% CPU
;;   112,032,123 processor cycles
;;   0 bytes consed
于 2012-06-12T17:21:19.890 に答える