2012-07-12 86 views
3

Common Lisp新手。編寫lisp代碼與編寫C++/java完全不同,就像我之前寫的那樣。寫一個簡單的矩陣類在普通的lisp練習

我想寫一個簡單的矩陣類在普通的lisp練習。有些代碼這樣的:

(defun make-matrix (row col) 
    (make-list row :initial-element (make-list col :initial-element nil))) 

(defun init-matrix (matrix init-value) 
    (labels ((set-element-value (lst) 
           (if (and lst 
             (listp lst)) 
            (mapcar #'set-element-value lst) 
           (setf lst init-value)))) 
    (set-element-value matrix))) 

(defun matrix+ (&rest matrices) 
    (apply #'mapcar (lambda (&rest rows) 
        (apply #'mapcar #'+ rows)) matrices)) 

我的問題是我能寫一個矩陣+接受不同數量的不「適用」的論點,或者更好的辦法?在某種程度上,lisp應該是?

如何矩陣*,可以有人向我展示一些令人敬畏的代碼接受矩陣*中的任意數量的參數?謝謝。

+0

@wvxvw稍後我會看一看。 – Boris 2012-07-12 15:26:44

回答

6

Common Lisp有n維數組。我會用這些矩陣操作。

見:​​,AREF,...

通常我還會再編寫一個二進制(取兩個參數)矩陣運算。然後使用REDUCE對矩陣列表進行操作。

CL-USER > (make-array '(3 5) :initial-element 0) 
#2A((0 0 0 0 0) (0 0 0 0 0) (0 0 0 0 0)) 

上面創建一個尺寸爲3x5的2維數組作爲初始內容。

+0

也許我應該停止這個簡單的練習,然後找到一些東西......我會看到更詳細的文檔。謝謝。 – Boris 2012-07-12 15:25:25

3

矩陣乘法。我不能保證這是最好的例子,但它非常簡單。這是給你使用數組而不是列表。此外,當然,你可以優化方陣,或特殊情況下,如單位矩陣等等。但是這僅僅意味着簡單,效率不高,等等

(defun matrix* (&rest matrices) 
    (assert (cdr matrices) nil 
      "You will achieve nothing by multiplying a single matrix.") 
    (reduce 
    #'(lambda (a b) 
     (assert (= (array-dimension a 0) (array-dimension b 1)) nil 
       "The number of rows in the first matrix should be the number ~ 
       of columns in the second matrix") 
     (let ((result 
       (make-array 
       (list (array-dimension a 1) (array-dimension b 0)) 
       :initial-element 0))) 
     (dotimes (i (array-dimension a 1) result) 
      (dotimes (j (array-dimension b 0)) 
      (dotimes (k (array-dimension a 0)) 
       (incf (aref result i j) (* (aref a k i) (aref b j k)))))))) 
    matrices)) 

(format t "result: ~s~&" (matrix* #2A((1 2) (3 4)) #2A((5 6) (7 8)))) 
;; #2A((23 31) (34 46)) = 
;; (1 * 5 + 3 * 6 = 23) (1 * 7 + 3 * 8 = 31) 
;; (2 * 5 + 4 * 6 = 34) (2 * 7 + 4 * 8 = 46)