ms8
ms8

Reputation: 417

Dynamic 2d array in lisp

I want to have a 2D array in Lisp . But each row can have different number of elements(At max 5). So I thought of maintaining another single list to store the current sizes of each row, and update them whenever required.

So, my code goes like this :

(setq N (read))
(setq myMatrix (make-array (list N 5)))
(setq sizeArray (make-array N:fill-pointer N))
(dotimes (i N)
    (setf (aref sizeArray i) 0)
)

Now after that I am having a loop to fill elements per row like this :

(dotimes (i N)
  //Here I need to take input in each row until user presses -1.It is sure he can't insert more than 5 items in each row.
)

How this can be done ? Please help. I tried something like this :

(setq item (read-line))
(setf (aref myMatrix i (nthcdr i sizeArray)) item)

But it did not worked.

Upvotes: 0

Views: 1691

Answers (1)

Joshua Taylor
Joshua Taylor

Reputation: 85813

Arrays in Common Lisp can have fill pointers, which provides a way to treat an array as something which can grow and extend its length. Your 2-D array could be realized as an array of arrays with fill pointers. E.g.:

(defun make-row-resizeable-array (rows max-columns)
  "Returns an array of length ROWS containing arrays
of length MAX-COLUMNS, but with a fill pointer initially
set to 0."
  (make-array rows
              :initial-contents (loop for i from 0 below rows
                                   collect (make-array max-columns
                                                       :fill-pointer 0))))

This would let you do:

CL-USER> (let ((array (make-row-resizeable-array 6 5)))
           (vector-push 'x (aref array 2))
           (vector-push 'y (aref array 2))
           (vector-push 'z (aref array 2))
           (vector-push 'a (aref array 3))
           (vector-push 'b (aref array 3))
           array)
;=> #(#() #() #(X Y Z) #(A B) #() #())

you can get the lengths easily too:

CL-USER> (map 'list 'length *)
;=> (0 0 3 2 0 0)

You can get individual elements from the array with a nested aref call:

(let ((array (make-row-resizeable-array 6 5)))
  (vector-push 'x (aref array 2))
  (vector-push 'y (aref array 2))
  (vector-push 'z (aref array 2))
  (vector-push 'a (aref array 3))
  (vector-push 'b (aref array 3))
  (let ((row 3)
        (col 1))
    (aref (aref array row) col)))
;=> B

Upvotes: 2

Related Questions