How to iterate through a vector of vectors? - loops

I have a data structure like this:
(defparameter *test*
#(#(3)
#(7 4)
#(2 4 6)
#(8 5 9 3)))
which represents a triangle of integers and a function
(defun get-node (i j triangle)
"Returns the value of the node I J of TRIANGLE."
(assert (<= j i) (i j) "~&J has to be smaller than I! I: ~D J: ~D~%" i j)
(svref (svref triangle i) j))
which allows me to access each node of the triangle easily (at least I think it does).
I thought using these two it would be easy to build up the sum along different paths through the triangle from top (3) to bottom, e.g. 8 --> 3 + 7 + 2 + 8 = 20. The next path would be 3 + 7 + 2 + 5 = 17.
Unfortunately, I totally fail to generate the indices of my vector of vectors in a reasonable way to find all the eight path in this simple example. This is not about brute-force vs. dynamic programming, etc. I am just looking for a way to iterate through the columns and rows of *test* which assures that each path was found.
How could one iterate the two indices, e.g. i and j in such a way that the correct combinations are found?

I think i now better understand what you want to enumerate so here is
another answer to your question for the alternative definition of
a “path”: a path can be described as a sequence of directions,
either down (0) or down right (1). That is trivially mapped
to an unsigned integer 0 ≤ path < 2path-directions
where each bit represents the successive directions. Each path is
conveniently represented by the pair (path-directions, number)
where path-directions is the number of directions, and number
encodes the successive directions in bits 0 through path-directions-1.
(defun gen-paths (path-directions)
(loop for i below (expt 2 path-directions)
collect i))
(gen-paths 3) => (0 1 2 3 4 5 6 7)
(defun path-to-directions (path-directions path)
(loop for i downfrom (- path-directions 1) to 0
collect (elt #(:down :down-right)
(ldb (byte 1 i) path))))
(loop for path in (gen-paths 3) collect (path-to-directions 3 path)) =>
((:DOWN :DOWN :DOWN) (:DOWN :DOWN :DOWN-RIGHT)
(:DOWN :DOWN-RIGHT :DOWN) (:DOWN :DOWN-RIGHT :DOWN-RIGHT)
(:DOWN-RIGHT :DOWN :DOWN) (:DOWN-RIGHT :DOWN :DOWN-RIGHT)
(:DOWN-RIGHT :DOWN-RIGHT :DOWN) (:DOWN-RIGHT :DOWN-RIGHT :DOWN-RIGHT))
Note that path-directions is one less than the size of the
triangle. When you represent the path as the list of nodes you
have an extra element, the starting node (0, 0).
(defun path-to-ref (path-directions path)
"Map a path to the list of (I J) pairs as understood by `get-node`."
(loop for i upto path-directions
for j = 0 then (+ j (ldb (byte 1 (- path-directions i)) path))
collect (list i j)))
 
(loop with path-directions = (- (length *test*) 1)
for path in (gen-paths path-directions)
collect (path-to-ref path-directions path))
=>
(((0 0) (1 0) (2 0) (3 0)) ((0 0) (1 0) (2 0) (3 1))
((0 0) (1 0) (2 1) (3 1)) ((0 0) (1 0) (2 1) (3 2))
((0 0) (1 1) (2 1) (3 1)) ((0 0) (1 1) (2 1) (3 2))
((0 0) (1 1) (2 2) (3 2)) ((0 0) (1 1) (2 2) (3 3)))
 
(defun get-path-nodes (path triangle)
"Returns the values of the nodes along PATH in TRIANGLE"
(loop with path-directions = (- (length triangle) 1)
for (i j) in (path-to-ref path-directions path)
collect (get-node i j triangle)))
You can then easily get the values:
(loop with path-directions = (- (length *test*) 1)
for path in (gen-paths path-directions)
collect (get-path-nodes path *test*))
=>
((3 7 2 8) (3 7 2 5) (3 7 4 5) (3 7 4 9)
(3 4 4 5) (3 4 4 9) (3 4 6 9) (3 4 6 3))
or sum them
(loop with path-directions = (- (length *test*) 1)
for path in (gen-paths path-directions)
collect (loop for v in (get-path-nodes path *test*)
sum v))
=>
(20 17 19 23 16 20 22 16)

Lisp unsurprisingly has friendlier support for lists, so I went with:
(defparameter *pyre*
'((3)
(7 4)
(2 4 6)
(8 5 9 3)))
My first stab just collects a tree and is repetitive but perhaps easier to follow:
(defun summit (n levels)
(destructuring-bind (this . more) levels
(let ((me (nth n this)))
(if more
(list
(list* me (summit n more))
(list* me (summit (1+ n) more)))
(list me)))))
Test by evaluating:
(summit 0 *pyre*)
Now tighten it up and compute the sums:
(defun summit (n levels)
(destructuring-bind (this . more) levels
(let ((me (nth n this)))
(if more
(loop for fork below 2
nconc (summit (+ n fork) more) into fork-sums
finally (return (loop for fs in fork-sums
collecting (+ me fs))))
(list me)))))
If recomputing paths concerns you, we could have some fun and rplaca the cons at one level with the sum of the existing car and each value computed at the next level. Left as an exercise.
Addendum: OK, no need for rplaca to avoid repeated calculations, to my great disappointment (but the moral is that recursion makes explicit path management unnecessary by funneling data along the paths implicit in the data):
(defun summit-ex (levels)
(destructuring-bind (level . lower-levels) levels
(if lower-levels
(loop with next-result = (let ((nr (summit-ex lower-levels)))
(print nr)
nr)
for pos upfrom 0
for value in level
for next-values = (loop for fork below 2
append (nth (+ pos fork) next-result))
collect (loop for next-value in next-values
collecting (+ value next-value)))
(mapcar 'list level))))
The debug printing was left in place because I like how they make clear what is going on:
((8) (5) (9) (3))
((10 7) (9 13) (15 9))
((17 14 16 20) (13 17 19 13))
((20 17 19 23 16 20 22 16))
Meanwhile, yes, some languages are more vector-friendly, such as Clojure:
(def pyre [[3]
[7 4]
[2 4 6]
[8 5 9 3]])
(defn summit-ex [[level & lower-levels]]
(if lower-levels
(let [next-result (summit-ex lower-levels)]
(for [pos (range (count level))]
(let [value (nth level pos)
next-values (mapcat #(nth next-result (+ pos %))
[0 1])]
(map #(+ value %) next-values))))
(map list level)))
Me, I prefer Lisp.

To generate the “paths”, that is the sequence of (i j)s you can do:
(defun gen-paths (depth)
(if (plusp depth)
(loop for p in (gen-paths (- depth 1))
nconc (loop for j to depth
collect (append p (list (list depth j)))))
'(((0 0)))))
For example (gen-paths 3) =>
(((0 0) (1 0) (2 0) (3 0)) ((0 0) (1 0) (2 0) (3 1)) ((0 0) (1 0) (2 0) (3 2)) ((0 0) (1 0) (2 0) (3 3))
((0 0) (1 0) (2 1) (3 0)) ((0 0) (1 0) (2 1) (3 1)) ((0 0) (1 0) (2 1) (3 2)) ((0 0) (1 0) (2 1) (3 3))
((0 0) (1 0) (2 2) (3 0)) ((0 0) (1 0) (2 2) (3 1)) ((0 0) (1 0) (2 2) (3 2)) ((0 0) (1 0) (2 2) (3 3))
((0 0) (1 1) (2 0) (3 0)) ((0 0) (1 1) (2 0) (3 1)) ((0 0) (1 1) (2 0) (3 2)) ((0 0) (1 1) (2 0) (3 3))
((0 0) (1 1) (2 1) (3 0)) ((0 0) (1 1) (2 1) (3 1)) ((0 0) (1 1) (2 1) (3 2)) ((0 0) (1 1) (2 1) (3 3))
((0 0) (1 1) (2 2) (3 0)) ((0 0) (1 1) (2 2) (3 1)) ((0 0) (1 1) (2 2) (3 2)) ((0 0) (1 1) (2 2) (3 3)))
You can then map get-node into this to transform these indexes into the corresponding values:
(loop for path in (gen-paths 3)
collect (loop for (i j) in path
collect (get-node i j *test*)))
=>
((3 7 2 8) (3 7 2 5) (3 7 2 9) (3 7 2 3)
(3 7 4 8) (3 7 4 5) (3 7 4 9) (3 7 4 3)
(3 7 6 8) (3 7 6 5) (3 7 6 9) (3 7 6 3)
(3 4 2 8) (3 4 2 5) (3 4 2 9) (3 4 2 3)
(3 4 4 8) (3 4 4 5) (3 4 4 9) (3 4 4 3)
(3 4 6 8) (3 4 6 5) (3 4 6 9) (3 4 6 3))
or sum the values of each “path”
(loop for path in (gen-paths 3)
collect (loop for (i j) in path
summing (get-node i j *test*)))
=>
(20 17 21 15 22 19 23 17 24 21 25 19 17 14 18 12 19 16 20 14 21 18 22 16)

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.

Common Lisp - apply function to every other element in list

I want to apply the function (* x 2) to every other element in a list and return the entire list using the loop macro. The solution I've come up with so far is this:
(defun double-every-other (xs)
(loop for x in xs by #'cddr collect (* x 2)))
However, this will double every other element and only return the elements that were doubled, so if I executed:
(double-every-other '(1 2 3 4))
The result would be:
'(4 8)
But I want the result to be:
'(1 4 3 8)
Is there a way I can do this using (loop)?
Another version with less math:
(defun double-every-other (list)
(loop
for (a b) on list by #'cddr
collect a
when b collect (* b 2)))
(double-every-other '(1 2 3 4))
=> (1 4 3 8)
(double-every-other '(1 2 3 4 5))
=> (1 4 3 8 5)
Obviously, you won't be able to abstract the N as easily as the other answer (if you are thinking "macro", stop now). Here we iterate using the on keyword, which means each sublist is visited in turn. Since we use by #'cddr, every other sublist is skipped. The destructuring syntax (a b) binds the first and second elements of the visited list.
You can for instance test an integer increasing while the list is scanned:
(defun double-every-other (xs)
(loop for x in xs
for i from 1
if (oddp i)
collect x
else collect (* x 2)))
(defun double-every-other (xs)
(loop for x in xs
for doublep = nil then (not doublep)
collect (if doublep (* x 2) x)))
another version, without loop at all:
(defun make-cycled (&rest items)
(setf (cdr (last items)) items))
(mapcar #'funcall
(make-cycled #'identity (lambda (x) (* 2 x)))
'(10 9 8 7 6 5 4 3))
;;=> (10 18 8 14 6 10 4 6)
You could use the loop "on" list iteration primitive. This takes a list of loop variables that will be "smeared" across the list, with the last being the tail of the entire remaining list. The conditional loop for is necessary to avoid multiplying nil if we have an odd number of arguments.
(defun double-every-other (list)
(loop for (single double tail) on list by #'cddr
if (null double)
collect single
else
append (list single (* 2 double))))
And if we try to run it:
* (double-every-other '(1 2 3 4 5))
(1 4 3 8 5)

fibonacci sequence using iterative process in SICP, cannot completely understand

Here is an iterative example of a procedure computing the fibonacci sequence in SICP. The idea is:
a = fib(n+1) = a+b
b = fib(n) = a
(define (fib n)
(fib-iter 1 0 n))
(define (fib-iter a b count)
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1))))
Looking at it deeper, I don't understand why continuing the computation towards fib(n+1) is necessary. I found we could have written.
;; a and b are first and second integers respectively
;; in the recursive call, b would be replaced by a+b because it is the next number in the sequence
;; so now a will be replaced by the previous value of b because it is the previous value.
(define (fib2 n)
(fib-iter 1 0 n))
(define (fib-iter a b count)
(if (= count 0)
b
(fib-iter b (+ a b) (- count 1))))
Now, I really think the first example, the one continuing up to n+1 is really redundant. I don't understand why is that necessary. What's wrong with my proposed iterative example?
Bot procedures produce correct result. However, the first one retains the relationship between a and b: a is Fib(i+1) and b is Fib(i) where i=n-count. The second method uses the first iteration to swap a and b around, thus introducing one redundant iteration. This can be seen by taking the trace of procedures:
> (define (fib n)
(fib-iter 1 0 n))
(define (fib-iter a b count)
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1))))
> (trace fib-iter)
> (fib 3)
>(fib-iter 1 0 3)
>(fib-iter 1 1 2)
>(fib-iter 2 1 1)
>(fib-iter 3 2 0)
<2
2
> (define (fib-iter a b count)
(if (= count 0)
b
(fib-iter b (+ a b) (- count 1))))
> (trace fib-iter)
> (fib 3)
>(fib-iter 1 0 3)
>(fib-iter 0 1 2)
>(fib-iter 1 1 1)
>(fib-iter 1 2 0)
<2
2
What you actually want is something like this:
> (define (fib n)
(if (zero? n)
0
(fib-iter 0 1 (- n 1))))
(define (fib-iter a b count)
(if (zero? count)
b
(fib-iter b (+ a b) (- count 1))))
> (trace fib-iter)
> (fib 3)
>(fib-iter 0 1 2)
>(fib-iter 1 1 1)
>(fib-iter 1 2 0)
<2
2
Notice, there is one less iteration. However, I'm doing extra work in procedure fib.
There is nothing wrong. The two approaches give the same result.
#lang racket
(define (fib n)
(fib-iter 1 0 n))
(define (fib-iter a b count)
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1))))
(define (fib2 n)
(fib-iter2 1 0 n))
(define (fib-iter2 a b count)
(if (= count 0)
b
(fib-iter2 b (+ a b) (- count 1))))
(define xs '(0 1 2 3 4 5 6 7 8 9 10))
(map fib xs)
(map fib2 xs)
The output is:
'(0 1 1 2 3 5 8 13 21 34 55)
'(0 1 1 2 3 5 8 13 21 34 55)
This shows that you are indeed computing the same sequence.

Algorithm that mix array respecting certain constraints

I've this problem:
i must develop an algorithm that get an int array and reshuffles the elements respecting these constraints:
For each element, must be lower than its neighbors or greater than its neighbors:
for each x in array a,
( a[x-1]<=a[x] AND a[x+1]<=a[x] )
OR
( a[x-1]>=a[x] AND a[x+1]>=a[x] )
This all in theta(n log n) in the worst case
I've no idea how to do this, my only intuition is that i must do something similar to merge-sort...
Sorry for mi poor English
Sort the array
Cut it in halfs
Put elements from first half in between elements of the second half
If number of elemnts is not even move last element to the front
Example:
2 3 1 5 7 8 6 4 9
1 2 3 4 5 6 7 8 9
1 5 2 6 3 7 4 8 9
9 1 5 2 6 3 7 4 8
As a naive approach, you could perform some sorting first and group the array to groups of equal size. Afterwards, adjacent groups would have to be pairwise switched; if the number of groups is odd, the first group needs to be switched to the back.
An example:
Input: 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 (already sorted)
Groups: (9 9) (8 8) (7 7) (6 6) (5 5) (4 4) (3 3) (2 2) (1 1)
Groups pairwise switched: (8 8) (9 9) (6 6) (7 7) (4 4) (5 5) (2 2) (3 3) (1 1)
First group moved to the back: (9 9) (6 6) (7 7) (4 4) (5 5) (2 2) (3 3) (1 1) (8 8)
Perhaps the idea can be refined to obtain a better algorithm.

Resources