Lisp array element swap - arrays

I'm new to lisp and I'm trying to trade two elements in an array. I would like to know if there is a function to get a specified position so I can use rotatef to swap them.
I've tried the function position but it doesn't work on arrays since it isn't a sequence.
What is the best computational solution in case there isn't a built in function for array?
I've searched around and can't seem to find a simple solution. Is row-major-aref the solution?
Basically, i want to find the position of an element in the 2 dimensional array and return the position to be used in rotatef

You can make a one-dimensional displaced array and use that as a vector for position.
Example:
CL-USER 9 > (let ((a0 (make-array '(2 3)
:initial-contents '((foo1 bar foo2)
(foo3 baz foo4)))))
(let ((a1 (make-array (reduce #'+ (array-dimensions a0))
:displaced-to a0)))
(let ((pos1 (position 'baz a1))
(pos2 (position 'bar a1)))
(when (and pos1 pos2)
(rotatef (aref a1 pos1)
(aref a1 pos2)))))
a0)
#2A((FOO1 BAZ FOO2) (FOO3 BAR FOO4))

I think it should work - arrays are indeed sequences.
(let* ((an-array (make-array 6 :initial-contents '(#\f #\o #\o #\b #\a #\r)))
(f-pos (position #\f an-array))
(r-pos (position #\r an-array)))
(rotatef (elt an-array f-pos)
(elt an-array r-pos))
an-array)
;=> #(#\r #\o #\o #\b #\a #\f)
Of course, you don't need to bind the positions to names. This will work too:
(let ((an-array (make-array 6 :initial-contents '(#\f #\o #\o #\b #\a #\r))))
(rotatef (elt an-array (position #\f an-array))
(elt an-array (position #\r an-array)))
an-array)
;=> #(#\r #\o #\o #\b #\a #\f)
If the problem is with position not finding the element you need, its :test argument may be helpful. There are also position-if and position-if-not functions which let you supply your own predicate for identifying the element. All three are described here in the HyperSpec.
Here's an example that probably won't work without the :test argument, since the default (which is eql for all sequence functions with :test arguments - see table 11-2 here for a nice summary of the standard sequence function keyword arguments) doesn't work on lists.
(let ((an-array (make-array 3 :initial-contents '((1 2 3)
(4 5 6)
(7 8 9)))))
(rotatef (elt an-array (position '(1 2 3) an-array :test #'equal))
(elt an-array (position '(7 8 9) an-array :test #'equal)))
an-array)
;=> ((7 8 9) (4 5 6) (1 2 3))
(Tested on SBCL 1.0.55.0.debian).
Added:
Here's a brute force way to do it with a two-dimensional array. find-position assumes the array is of size (3 3) but it would be easy to make it somewhat more general.
I don't advocate this as the best solution, but I didn't want to leave you empty handed after misunderstanding your question :)
(defvar an-array #2A((1 2 3) (4 5 6) (7 8 9)))
(defun find-position (array item &key (test #'eql))
(loop for i below 3 do
(loop for j below 3 do
(when (funcall test (aref array i j) item)
(return-from find-position (list i j))))))
(defun swap-4-and-7 (array)
;; Example use
(destructuring-bind (i1 j1) (find-position array 4)
(destructuring-bind (i2 j2) (find-position array 7)
(rotatef (aref array i1 j1)
(aref array i2 j2))))
array)
(swap-4-and-7 an-array)
;=> #2A((1 2 3) (7 5 6) (4 8 9))

Related

How to convert a list to a one dimensional array (vector) in Common Lisp having the same output either using make-array or coerce?

I want to convert from a simple list:
'(1 2 3)
To a one dimensional array (vector):
#(1 2 3)
I found this question which is similar but does not cover this problem.
I also managed to find a way to achieve it. Not sure if it is the best:
CL-USER> (coerce '(1 2 3) 'vector)
#(1 2 3)
CL-USER> (type-of *)
(SIMPLE-VECTOR 3)
I wonder if it is possible to use make-array to achieve the same result. I tried:
CL-USER> (make-array '() :initial-contents '(1 2 3))
#0A(1 2 3)
CL-USER> (type-of *)
(SIMPLE-ARRAY T NIL)
This is close, but I do not understand #0A in #0A(1 2 3).
For some reason that I do not understand, this output does not work on further compositions, such as aref:
CL-USER> (aref #0A(1 2 3) 0)
; Evaluation aborted on #<SIMPLE-ERROR "Wrong number of subscripts, ~W, for array of rank ~W." {1003C07793}>.
Is it possible to use make-array to achieve the same result as coerce?
What are the differences between these two approaches?
Is one of them faster or more elegant than the other?
COERCE is fine, you can even specify the element-type if you want:
USER> (coerce '(1 2 3) '(vector fixnum))
#(1 2 3)
USER> (describe *)
#(1 2 3)
[simple specialized vector]
Element-type: FIXNUM
Length: 3
You can do the same with make-array, but you need to give the right dimension. The dimension parameter indicates how many rows, columns, etc. the possibly multi-dimensional array has. It should be a list, but when you only have one dimension, it can just be a number. Both forms here are equivalent:
USER> (make-array 3 :initial-contents '(1 2 3))
#(1 2 3)
USER> (make-array '(3) :initial-contents '(1 2 3))
#(1 2 3)
Usually you would call (length list). The added value compared to coerce is that you can specify the :fill-pointer or :adjustable arguments, something that the type argument of coerce cannot convey.
The printed representation of an array is #nA(), where n is the number of dimensions of the array, where the number and A is omitted if its a vector (n = 1). For example:
USER> (make-array '(10 2) :initial-element 0)
#2A((0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0))
For a given array of dimension n, you access the elements with aref and as many arguments as there are dimensions, in row-major order (the same order you specified the dimensions in make-array).
USER> (aref * 5 1)
0 (0 bits, #x0, #o0, #b0)
In your example, you defined an array of dimension 0, because you wrote '() (a.k.a. just () or nil) as the dimension. This can be used if you need a box to store a single element:
USER> (defparameter *box* (make-array nil :element-type '(mod 8)))
*BOX*
USER> (describe *box*)
#0A0
[simple specialized array]
Element-type: (UNSIGNED-BYTE 4)
Dimensions: NIL
Storage vector: #<(SIMPLE-ARRAY (UNSIGNED-BYTE 4) (1)) {101EA0C59F}>
; No values
USER> (setf (aref *box*) 7)
7 (3 bits, #x7, #o7, #b111)
USER> (incf (aref *box*))
8 (4 bits, #x8, #o10, #b1000)
USER> (aref *box*)
8 (4 bits, #x8, #o10, #b1000)
(as you can see, the values that can be stored in the array are the ones corresponding to the upgraded-element-type, here (unsigned-byte 4); for example, (setf (aref *box*) (expt 2 16)) signals an error)
It looks like :initial-contents had the same result as :initial-element, because with your example the content of the zero-dimensional array was the list (1 2 3)
Is one of them faster or more elegant than the other?
I try to use coerce when possible because it's shorter to write and it looks more descriptive of what I am doing. I don't think it is faster, unless you know in advance the length of the list.

Looking for a way to map a function over a 2D Lisp array

All of the map functions like mapcar, mapcan, mapc, etc require lists as their inputs. I am working with 2D arrays, and would prefer to not mess with the rank of my arrays given the often large sizes (50,000 x 1,000 sometimes).
I need a way to apply a function like (log n) to each element in the 2D array and yield a resulting 2D array.
Any help or direction is much appreciated.
Working in AllegroCL (Common Lisp)
What you need is a combination of
dotimes
array-dimensions
make-array
array-total-size
row-major-aref
Something like this:
(defun array-map (function array
&optional (retval (make-array (array-dimensions array))))
"Apply FUNCTION to each element of ARRAY.
Return a new array, or write into the optional 3rd argument."
(dotimes (i (array-total-size array) retval)
(setf (row-major-aref retval i)
(funcall function (row-major-aref array i)))))
Example:
(defparameter a (make-array '(2 3) :initial-contents '((1 2 3) (4 5 6))))
a
==> #2A((1 2 3) (4 5 6))
(array-map #'sqrt a)
==> #2A((1 1.4142135 1.7320508) (2 2.236068 2.4494898))
a ; does not change!
==> #2A((1 2 3) (4 5 6))
You can also use array-map similar to map-into:
(array-map #'1+ a a)
==> #2A((2 3 4) (5 6 7))
a ; modified, no new storage is allocated
==> #2A((2 3 4) (5 6 7))
Note that array-map will work on any array dimension, from vectors to matrices to 10d &c.
Exercise: implement array-multi-map accepting a function of any number of argument and any number of arrays, so that
(array-multi-map #'+ #A((1 2 3) (4 5 6)) #A((11 22 33) (44 55 66)))
==> #A((12 24 36) (48 60 72))
PS. The whole CLHS Chapter 15 Arrays or CLtL2 Chapter 17 Arrays is worth studying.

add value to first list (of lists) matching predicate

I have a list of lists and a value. My goal is a new list of lists, where the value is conjed (new first item) to the first list matching a predicate (eg > to the first item of the list). If no list matches the predicate, I want my value to "begin" a new list at the end of lists.
if my list is: ['(2 3 4) '(4 5 6 7) '(5 6 7)]
and my value: 3
and my predicate: (comp (partial < my-value) first)
then my result should be: ['(2 3 4) '(3 4 5 6 7) '(5 6 7)]
if my value was: 10
my result should be: ['(2 3 4) '(4 5 6 7) '(5 6 7) '(10)]
This problem confuses me, because my imperative mind keeps telling me how easy it should be, but I cannot find an easy (ok, be honest: any) solution. this is my attempt so far:
(defn add-to-first-list-that-matches [func value]
(loop [result []
remaining-lists list-of-lists
value-to-add value]
(if (empty? remaining-lists)
result
(let [current-list (first remaining-lists)
value-matches? (func value-to-add current-list)
new-list (if value-matches? (conj value-to-add current-list) current-list)]
(recur (conj new-list result)
(rest remaining-lists)
(if-not value-matches? value-to-add nil))))))
(it crashes)
please enlighten me with some clojure expression magic :)
btw. I want to solve this as part of the longest-increasing-subsequence problem.
This uses loop-recur.
(defn add-to-ll
[ll pred value]
(loop [[current & unprocessed] ll
processed []]
(cond
(pred current) (concat processed
[(cons value current)]
unprocessed)
(empty? unprocessed) (concat processed
[current]
[[value]])
:else (recur unprocessed
(conj processed current)))))
(def l-l1 [[2 3 4] [4 5 6 7] [5 6 7]])
(add-to-ll l-l1 (comp (partial < 10) first) 10)
=> ([2 3 4] [4 5 6 7] [5 6 7] [10])
(add-to-ll l-l1 (comp (partial < 3) first) 3)
=> ([2 3 4] (3 4 5 6 7) [5 6 7])
You could also use split-with
(defn add-to-ll
[ll pred value]
(let [[first-lists [to-change & rest-lists]] (split-with (complement pred) ll)]
(if to-change
(concat first-lists [(cons value to-change)] rest-lists)
(concat ll [[value]]))))
Performance wise the first solution should run a bit faster.
Ye olde lazy-seq:
(defn add-to-first-match
[pred x coll]
(lazy-seq
(if-let [s (seq coll)]
(let [fst (first s)]
(if (pred fst)
(cons (conj fst x) (rest s))
(cons fst (add-to-first-match pred x (rest s)))))
(cons (list x) nil))))
Note: one could further extract list into an argument and allow for example also vector as element constructor.
(defn find-index
"find index of the first item in s matching predicate `pred`"
[pred s]
(first (keep-indexed (fn [index item]
(if (pred item)
index
nil))
s)))
(defn update-first-match
"update first item in s that matches `pred` using (f item args*)"
[s pred f & args]
(apply update-in s [(or (find-index pred s)
(count s))]
f args))
(def my-lists
['(2 3 4) '(4 5 6 7) '(5 6 7)])
(defn add-to-first-list-less-than
[l n]
(update-first-match l #(< n (first %)) conj n))
;; usage:
(update-first-match my-lists #(< 5 (first %)) conj 5)
;; or
(add-to-first-list-less-than my-lists 5)
Here is my attempt to answer more succinctly using reduce:
(defn add-to-first-list-that-matches
[value lists]
(let [pred (comp (partial < value) first)
[found result] (reduce (fn [[found result] el]
(if (and (not found) (pred el))
[true (conj result (cons value el))]
[found (conj result el)]))
[false []]
lists)]
(if found
result
(conj result (list value)))))
I am using the idiom of a vector in reduce to carry multiple values (a boolean to indicate whether a match has been found, plus the modified data structure we are building up). I was also able to combine the various conditions into a single if per element, plus a final post-condition rather than nested conditions or a multi branch cond.
Here is how it works with your examples:
user> (add-to-first-list-that-matches 3 ['(2 3 4) '(4 5 6 7) '(5 6 7)])
[(2 3 4) (3 4 5 6 7) (5 6 7)]
user> (add-to-first-list-that-matches 10 ['(2 3 4) '(4 5 6 7) '(5 6 7)])
[(2 3 4) (4 5 6 7) (5 6 7) (10)]

Common Lisp: convert between lists and arrays

How do we convert elegantly between arbitrarily nested lists and arrays?
e.g.
((1 2 3) (4 5 6))
becomes
#2A((1 2 3) (4 5 6))
and vice versa
List to 2d array:
(defun list-to-2d-array (list)
(make-array (list (length list)
(length (first list)))
:initial-contents list))
2d array to list:
(defun 2d-array-to-list (array)
(loop for i below (array-dimension array 0)
collect (loop for j below (array-dimension array 1)
collect (aref array i j))))
The multi-dimensional form for list to 2d is easy.
(defun list-dimensions (list depth)
(loop repeat depth
collect (length list)
do (setf list (car list))))
(defun list-to-array (list depth)
(make-array (list-dimensions list depth)
:initial-contents list))
The array to list is more complicated.
Maybe something like this:
(defun array-to-list (array)
(let* ((dimensions (array-dimensions array))
(depth (1- (length dimensions)))
(indices (make-list (1+ depth) :initial-element 0)))
(labels ((recurse (n)
(loop for j below (nth n dimensions)
do (setf (nth n indices) j)
collect (if (= n depth)
(apply #'aref array indices)
(recurse (1+ n))))))
(recurse 0))))
Another 2d array to list solution:
(defun 2d-array-to-list (array)
(map 'list #'identity array))
And list to 2d array (But maybe not as efficient as the solution of the last reply):
(defun list-to-2d-array (list)
(map 'array #'identity list))
Use coerce: Coerce the Object to an object of type Output-Type-Spec.
(coerce '(1 2 3) 'vector) => #(1 2 3)
(coerce #(1 2 3) 'list) => '(1 2 3)

Printing contents of array LISP

Why does this code not print out the content of the array -
(defun loopfn (state)
(loop for x from 0 to 2 do
(loop for y from 0 to 2 do
(aref state x y))))
Here I am passing a 3x3 matrix which is built like this -
`(setq i (make-array '(3,3) :initial-contents '((0 1 3) (4 2 5) (7 8 6))))`
I am calling - (loopfn i)
Edit--------
#Greg
Thanks for pointing that out...
I had the following question..
Why does this print the output ...
(defun loopfn ()
(loop for x from 0 to 3 do
(if (eq x 2)(return (list x)))))
Where as this prints a nil...
(defun loopfn ()
(loop for x from 0 to 2 do
(loop for y from 0 to 2 do
(if (eq x 2)(return (list x y))))))
I am calling
(loopfn)
Your code does not print anything. That's also what you want - usually.
But you want functions to return something useful.
So you need to understand the difference between printing and having a REPL printing a return value.
CL-USER > 3
3
Above returns 3. The Read-Eval-Print-Loop prints the return value.
CL-USER > (print 3)
3
3
Above prints a newline and then two times the 3. Why?
The first is the side-effect of the PRINT call which prints the newline and then its argument.
The second is the REPL printing the return value.
Note also the EQ is not for numeric comparisons. Use EQL instead.
See: http://www.lispworks.com/documentation/lw50/CLHS/Body/f_eql.htm
As for your second question, (return ...) is equivalent to (return-from NIL ...) so you just return from your inner LOOP into the outer one. Use this instead:
[11]> (defun loopfn ()
(loop for x from 0 to 2 do
(loop for y from 0 to 2 do
(if (= x 2) (return-from loopfn (list x y))))))
[12]> (loopfn)
(2 0)
Another possibility is to collect more values than just one, as in
[36]> (defun loopfn ()
(loop for x from 0 to 2 nconc
(loop for y from 0 to 2
if (= y 2)
collect (list x y))) )
LOOPFN
[37]> (loopfn)
((0 2) (1 2) (2 2))
Your call to aref is getting the specified element, but you're not doing anything with it. You could stick it on to a list which is then returned:
(defun loopfn (state)
(let ((result '()))
(loop for x from 0 to 2 do
(loop for y from 0 to 2 do
(setf result (cons (aref state x y) result))))
result))
or you could just print it out:
(defun loopfn (state)
(loop for x from 0 to 2 do
(loop for y from 0 to 2 do
(format t "~a~%" (aref state x y)))))
The former is far more useful ; you want to return things which can then be further processed, and anything that gets passed to the top level will be printed out for you.
As long as you are using LOOP you can easily gather up your values with COLLECT, APPEND, etc., which is the idiomatic way to do it.
This was neatly covered in this forum topic.
The outer loop has no clause which would cause a return value.
Some code examples from that thread:
(defun print-2d-array-as-table (array)
(loop for i from 0 below (array-dimension array 0)
do (loop for j from 0 below (array-dimension array 1)
do (princ (aref array i j))
(if (= j (1- (array-dimension array 1)))
(terpri)
(princ #\Space)))))
and one loop:
(defun print-2d-array-as-table (array)
(loop for i below (array-total-size array) do
(if (zerop (mod i (array-dimension array 0)))
(terpri)
(princ #\Space))
(princ (row-major-aref array i))))
For your second question, in the loop that doesn't print, (eq x 2) is never true. You have modified the loop bounds from 0 to 3 to 0 to 2, so x never reaches 2. Since there is no explicit (return ...) executed, the function returns nil.

Resources