Finding paths in a 2d array - arrays

I have a two-dimensional array of integers and want to find the path with the lowest sum from the left column to the right column, when going up, down and left is possible. I started with a loop of all rows and tried to build up the paths as lists.
(defparameter *test-array*
#2A((131 673 234 103 18)
(201 96 342 965 150)
(630 803 746 422 111)
(537 699 497 121 956)
(805 732 524 37 331)))
(defun find-paths (array &aux (height (array-dimension array 0)) (width (array-dimension array 1)))
"Returns the possible paths across a given 2d array from the left column to
the right column."
(loop :for i :from 0 :below height
;; We have three ways per starting point up, left and down.
;; In the first and last row there are two ways, only.
:append (loop :for (j l) :in '((1 0) (0 1) (-1 0))
:when (and (>= (+ j i) 0) (< (+ j i) height))
:collect (list (aref array i 0) (aref array (+ i j) l))) :into paths
:finally (return paths)))
I was wondering if this really leads to a good solution. I am afraid that it will get more and more complex and memory comsuming to turn the whole array in a list of lists representing all possible paths. As far as I understand, it is a graph, basically. But how could I create the graph from the array without wasting memory?

This seems solvable by dynamic programming.
I'd create a new array with the same dimensions, which holds two values at each coordinate: the best path to it, and its cost. Initialize these values at the leftmost column, then propagate them all the way to the right.
Then, propagate each element path up as far as it is an improvement. Then left, then down. Cycle through the directions until none of them gives an improvement.
Finally, the best path at the rightmost column is the solution.

Related

How can lists share structure in ways that are impossible for arrays in Common Lisp?

I am trying to learn Common Lisp with the book Common Lisp: A gentle introduction to Symbolic Computation. In chapter 13 (the penultimate one), the book covers arrays.
Thus, the author makes a contrast between list and arrays. He says:
Because storage in arrays is contiguous, we can access each element of
an array as fast as any other element. With lists, we have to follow a
chain of pointers to get from one cons cell to the next, so depending
on the length of the list, it can take much, much longer to access the
last element than the first. Efficient access is the prime advantage
arrays have over lists. Another advantage is that in most
implementations, an array uses only half as much memory as a list of
equal length. But lists also have some advantages over arrays. Lists
of arbitrary length are easily built up element by element, either
recursively or iteratively. It is not as easy to grow an array one
element at a time. Another advantage of lists is that they can share
structure in ways that are impossible for arrays, but we won’t get
into the details of that in this book.
I understand all comments but the last intentionally cryptic one:
Another advantage of lists is that they can share structure in ways
that are impossible for arrays, but we won’t get into the details of
that in this book.
What exactly would be the share of structure which is possible in the list's data structure but impossible in arrays?
Could someone give me an example to illustrate this?
Thanks.
E.g., create two lists that share the tail:
(defparameter *l1* (list 1 2 3))
(defparameter *l2* (cons 0 (cdr *l1*))) ; (0 2 3)
Now, (eq (cdr *l1*) (cdr *l2*)) is t, and modifying one list can modify the other:
(setf (second *l1*) 10)
; now *l1* is (1 10 3)
; and *l2* is (0 10 3)
Note that arrays can share structure too:
(defparameter *a1* (make-array 10 :initial-contents (loop for i from 1 to 10 collect i)))
; now *A1* is #(1 2 3 4 5 6 7 8 9 10)
(defparameter *a2* (make-array '(2 3) :displaced-to *a1* :displaced-index-offset 3))
; now *A2* refers to a part of *A1*: #2A((4 5 6) (7 8 9))
Now, modifying *a1* also modifies *a2*:
(setf (aref *a1* 6) 123)
; now *a1* is #(1 2 3 4 5 6 123 8 9 10)
; and *a2* is #2A((4 5 6) (123 8 9))
The difference here between lists and arrays is in the way structure is shared: lists can share tails while arrays can share contiguous memory segments.

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.

Clojure multiply first n elements in sequence by 'x' non recursive

I am a newbie in clojure and came across a problem which says, multiply first n elements in a sequence by some number 'x' (non recursively). So for example
(multiply-n-by-x [1 2 3 4 5] 2 10) => [10 20 30 4 5]
So here i understood that i need to loop over the sequence n times and then stop, but i am unable to do that. If someone could guide me on how to do about it, it would be great.
Same as Shawn's answer but with destructuring and split-at (a bit less redundant):
(defn multiply-n-by-x [s n x]
(let [[s1 s2] (split-at (inc n) s)]
(concat (map #(* x %) s1) s2)))
I think the easy way is :
(defn multiply-n-by-x [seq n m]
(concat (map #(* m %) (take (inc n) seq)) (drop (inc n) seq) )
)
This does what you want:
(defn multiply-n-by-x [sq n x]
(for [i (range (count sq)) ;for i in range 0 to number of elements in sq
:let [element (nth sq i)]] ;bind element to the nth item in sq
(if (<= i n) ;if index below n, return the multiplied element, otherwise return the element as is
(* x element)
element)))
whatever you return inside the for macro gets put into a sequence so the end result is collection.
Lazy sequences capture delayed recursion. take, drop, split and for are lazy constructions. We can avoid them by computing the altered head of the sequence eagerly, as follows:
(defn multiply-n-by-x [coll n x]
(loop [head [], coll coll, n n]
(if (and (seq coll) (>= n 0))
(recur (conj head (* (first coll) x)) (rest coll) (dec n))
(concat head coll))))
For example,
(multiply-n-by-x [1 2 3 4 5] 2 10)
;(10 20 30 4 5)
By the way, the convention in Clojure is to give the count of a slice, not the index of the final element, which is one less.
(range 3)
;(0 1 2)

How to rearrange an array in such a way that each element is greater/smaller than its neighbours

For example, if the numbers are:
30, 12, 49, 6, 10, 50, 13
The array will be:
[10, 6, 30, 12, 49, 13, 50]
As you can see:
6 is smaller than both 10 and 30 and
49 is greater than 12 and 13 and so on.
The numbers are all different and real. I need the most efficient algorithm.
This can be done in O(n):
Find median in O(n) (description is available in Wikipedia
Put every element larger than the median on odd places and every smaller element - on even places
Of course, this assumes that all elements are distinct, otherwise sometimes it will fail.
Assuming the numbers are all distinct, the easiest way is probably to sort the numbers then interleave the first and second halves of the sorted list. This will guarantee the high/low/high/low/high/low/.... pattern that you need.
This algorithm is O(n log n) which should be efficient enough for most purposes, and may benefit from optimised sorting routines in your standard library.
If the numbers are not distinct, then it is possible that there is no solution (e.g. if the numbers are all equal)
Someone posted this question as a dupe to this but the solution over there is better than the accepted solution here so I figured I'd post it here.
Basically the key is for every three numbers where it has to hold that a < b > c you look at the sequence and swap the biggest number into the center. Then you increment by 2 to get to the next sequence like a < b > c and do the same thing.
Technically the solution still runs in O(n) like the accepted solution, but it is a better O(n) and it is much simpler because the median of medians algo is tricky to implement. Hopefully anyone who favorited this problem will at least see this solution, I can post the code if anyone is interested.
I'm not too knowledgeable about complexity, but here's my idea.
For even length lists:
(For our odd length example,
put 30 aside to make the list even)
1. Split the list into chunks of 2 => [[12,49],[6,10],[50,13]]
2. Sort each chunk => [[12,49],[6,10],[13,50]]
3. Reverse-sort the chunks by
comparing the last element of
one to the first element of
the second => [[12,49],[13,50],[6,10]]
For odd length lists:
4. Place the removed first element in
the first appropriate position => [30,12,49,13,50,6,10]
Haskell code:
import Data.List (sortBy)
import Data.List.Split (chunksOf)
rearrange :: [Int] -> [Int]
rearrange xs
| even (length xs) = rearrangeEven xs
| null (drop 1 xs) = xs
| otherwise = place (head xs) (rearrangeEven (tail xs))
where place x (y1:y2:ys)
| (x < y1 && y1 > y2) || (x > y1 && y1 < y2) = (x:y1:y2:ys)
| otherwise = place' x (y1:y2:ys)
place' x (y1:y2:ys)
| (x < y1 && x < y2) || (x > y1 && x > y2) = (y1:x:y2:ys)
| otherwise = y1 : (place' x (y2:ys))
rearrangeEven = concat
. sortBy (\a b -> compare (head b) (last a))
. map sort
. chunksOf 2
Output:
*Main> rearrange [30,12,49,6,10,50,13]
[30,12,49,13,50,6,10]
*Main> rearrange [1,2,3,4]
[3,4,1,2]

Ordering of a 2D array

I am trying to solve a problem on 2D arrays and need little help. The problem goes like this:
Suppose we have a 2D array A of size nxn comprising of unique elements. The need to rearrange the elements of A as follows. Let A11, A12, A21, A22 be four mutually disjoint subarrays of A, each of size n/2 x n/2. Then A11 < A12 < A21 < A22. If each of these subarrays is recursively split into four equal-sized sub-arrays, then also the property holds.
User input: n, N (≥ n2). n is a power of 2
I have tried many things but nothing seems to work.
You need to create a function which will convert an index between 0 and n*n-1 to coordinates in your array according to the ordering in question. Then you just run some usual 1D sorting algorithm, on an array of size n*n, jth element of which is substituted using that function. It solves the problem.
Update: the mapping function maps numbers in this matrix to their coordinates:
0 1 4 5
2 3 6 7
8 9 12 13
10 11 14 15
Piggybacking somewhat on the answer of unkulunkulu I think you could approach it as follows:
Take all the values in your matrix (2D) and put them in a simple array (1D). Then take this array and sort the values from lowest to highest.
Now what you need to do is fill the matrix again but in such a way that it conforms to the rules you have specified. If you have a look at a Z-order space filling curve in 2D, you will find that if you fill you matrix in this order (with the sorted elements), that the resulting matrix has your desired properties.
Now actually coding this would be up to you.
The book numerical recipes chapter 21.8 http://www.nrbook.com/nr3/ gives an analytic expression to calculate an index into the 2D array given the coordinates of a quadtree.
Here is another straight forward approach that I tried, but I don't like it as much:
(defun quad-pos (pos)
"POS is a list of letters that indicate the position in a 2x2 matrix [a,b; c,d]."
(let ((x 0)
(y 0)
(s 1))
(dolist (e pos)
(setf s (/ s 2))
(ecase e
('a )
('b (incf x s))
('c (incf y s))
('d (incf x s) (incf y s))))
(values x y)))
#+nil
(quad-pos '(a)) ;=> 0, 0
#+nil
(quad-pos '(a b c)) ;=> 1/4, 1/8
#+nil
(quad-pos '(d d d d)) ;=> 15/16, 15/16

Resources