One of the oldest most visited problems in any computer science course the Fibonacci series a very good explanation including sample algorithms can be found in the almighty Wikipedia

This program presents a slight extension in that you can calculate series formed by the sum of the k prior elements. All you have to do is change the size of the array that stores the k prior numbers.

There is just a little trick to work out in which element of the array will the nth element be stored.

;working array of only two el elements

;If the array is initialised to k the program will calculate series or order k

;That is f(i)=f(i-1)+...+f(i-k) when k=2 its the Fibonacci series

(setq arr (make-array 2))

;initialising the array

; builds the first array for k as (0 ... k)

(dotimes (i (array-dimension arr 0))

(setf (aref arr i ) i )

)

;function summing all the elements in the array

(defun sum (vect)

(setq temp 0)

(dotimes (i (array-dimension arr 0))

(setq temp (+ temp (aref vect i )))

)

(setq sum temp)

)

;function calculating the fibbonaci-k series without recursion

(defun fib(pos)

(setq buffSize (array-dimension arr 0 ))

(dotimes (i pos)

(setq j (mod i buffSize))

(setf (aref arr j) (sum arr))

)

(setq extract (mod (- pos 1) (array-dimension arr 0)))

(setq fib (aref arr extract))

)

(print '(I will calculate for you the nth fibonacci number n= ) )

(setq num (read))

(print '(using k=))

(print (array-dimension arr 0))

(setq res (fib num))

(print res)

;(print arr)

This is one of the typical algorithms that gains alot from being de-recursified. Like this the memory footprint is low, the computation time also, as we only add a modulus operation, and everyone is happy.

## 4/09/2006

## 4/06/2006

### Renversant?

I decided to name this code snippet after the french term for reversing because this algorithm does just that. It iterates through the perimeter of the array, extracts the anti-diagonal "(-1,1) direction" and reverses that list. Then it simply asigns it back to the same array.

Little idea extracted from an exercise of "Programming pearls"

The program reads:

Program output is also very pretty:

This is the sort of algorithm that may be handy if you have little memory and need to do everything in place, there is no need for a second array making things easy on the memory side of things.

Little idea extracted from an exercise of "Programming pearls"

The program reads:

;example of array transposition based on rotations

;The method consists of the following: we reverse each of the anti-diagonal arrays

;first we have to extract and re assign each of the elements

(setq arr (make-array '(11 11)))

;initialise the array

(dotimes (i (array-dimension arr 0))

(dotimes (j (array-dimension arr 1))

(setf (aref arr i j ) (+ (* i (array-dimension arr 0 )) j) )

)

)

;utility method for computing the sum of the elements in a list

(defun sum(in)

(setq temp 0)

(loop for item in in do

(setq temp (+ temp item))

)

(setq sum temp)

)

;utility for working out the first co-ordinate of the diagonal

(defun next-diag(pos dim)

(setq x (car pos))

(setq y (cadr pos))

(cond

((eq dim x)

(setq y (+ y 1 ))

)

((eq dim x)

(setq x (- x 1))

)

)

(cond

((eq y 0)(setq x (+ x 1)))

((eq y 0)(setq y (+ y 1)))

)

(setq pos (list x y))

(setq next-diag pos)

)

;method extracting the contents of an anti-diagonal of the array

;starting at the specified co-ordinates

(defun extract-diagonal(pos data)

(setq x (car pos))

(setq y (cadr pos))

(setq temp(list (aref data x y)))

(loop while(and (> x 0) (< y (- (array-dimension data 1) 1))) do

(setq x (- x 1))

(setq y (+ 1 y))

(setq temp (append temp (list (aref data x y )) ) )

)

(setq extract-diagonal temp)

)

(defun insert-diagonal(pos data diagonal)

(setq x (car pos))

(setq y (cadr pos))

(dolist (k diagonal)

(setf (aref data x y) k )

(setq x (- x 1))

(setq y (+ 1 y))

)

)

(defun transpose(data)

(setq xdim (- (array-dimension data 0) 1))

(cond

((evenp xdim)(setq modif 2))

((oddp xdim)(setq modif 3))

)

(setq numdiag (- (sum (array-dimensions data)) modif ))

(setq diagpos '(0 0))

(dotimes (i numdiag)

(setq diagpos (next-diag diagpos xdim))

;step one extract the diagonal to a list

(setq diagonal (extract-diagonal diagpos data))

;step two reverse

(setq diagonal(reverse diagonal))

(print diagonal)

;step three profit ;-)

(insert-diagonal diagpos data diagonal)

)

)

(print 'Before )

(print arr)

(print 'transpose)

(transpose arr)

(print 'After )

(print arr)

;example of array transposition based on rotations

;The method consists of the following: we reverse each of the anti-diagonal arrays

;first we have to extract and re assign each of the elements

(setq arr (make-array '(11 11)))

;initialise the array

(dotimes (i (array-dimension arr 0))

(dotimes (j (array-dimension arr 1))

(setf (aref arr i j ) (+ (* i (array-dimension arr 0 )) j) )

)

)

;utility method for computing the sum of the elements in a list

(defun sum(in)

(setq temp 0)

(loop for item in in do

(setq temp (+ temp item))

)

(setq sum temp)

)

;utility for working out the first co-ordinate of the diagonal

(defun next-diag(pos dim)

(setq x (car pos))

(setq y (cadr pos))

(cond

((eq dim x)

(setq y (+ y 1 ))

)

((eq dim x)

(setq x (- x 1))

)

)

(cond

((eq y 0)(setq x (+ x 1)))

((eq y 0)(setq y (+ y 1)))

)

(setq pos (list x y))

(setq next-diag pos)

)

;method extracting the contents of an anti-diagonal of the array

;starting at the specified co-ordinates

(defun extract-diagonal(pos data)

(setq x (car pos))

(setq y (cadr pos))

(setq temp(list (aref data x y)))

(loop while(and (> x 0) (< y (- (array-dimension data 1) 1))) do

(setq x (- x 1))

(setq y (+ 1 y))

(setq temp (append temp (list (aref data x y )) ) )

)

(setq extract-diagonal temp)

)

(defun insert-diagonal(pos data diagonal)

(setq x (car pos))

(setq y (cadr pos))

(dolist (k diagonal)

(setf (aref data x y) k )

(setq x (- x 1))

(setq y (+ 1 y))

)

)

(defun transpose(data)

(setq xdim (- (array-dimension data 0) 1))

(cond

((evenp xdim)(setq modif 2))

((oddp xdim)(setq modif 3))

)

(setq numdiag (- (sum (array-dimensions data)) modif ))

(setq diagpos '(0 0))

(dotimes (i numdiag)

(setq diagpos (next-diag diagpos xdim))

;step one extract the diagonal to a list

(setq diagonal (extract-diagonal diagpos data))

;step two reverse

(setq diagonal(reverse diagonal))

(print diagonal)

;step three profit ;-)

(insert-diagonal diagpos data diagonal)

)

)

(print 'Before )

(print arr)

(print 'transpose)

(transpose arr)

(print 'After )

(print arr)

Program output is also very pretty:

prozak@Mistral:~/Exploration/lisp/pearls%clisp transpose.lisp

BEFORE

#2A((0 1 2 3 4 5 6 7 8 9 10)

(11 12 13 14 15 16 17 18 19 20 21)

(22 23 24 25 26 27 28 29 30 31 32)

(33 34 35 36 37 38 39 40 41 42 43)

(44 45 46 47 48 49 50 51 52 53 54)

(55 56 57 58 59 60 61 62 63 64 65)

(66 67 68 69 70 71 72 73 74 75 76)

(77 78 79 80 81 82 83 84 85 86 87)

(88 89 90 91 92 93 94 95 96 97 98)

(99 100 101 102 103 104 105 106 107 108 109)

(110 111 112 113 114 115 116 117 118 119 120))

TRANSPOSE

(1 11)

(2 12 22)

(3 13 23 33)

(4 14 24 34 44)

(5 15 25 35 45 55)

(6 16 26 36 46 56 66)

(7 17 27 37 47 57 67 77)

(8 18 28 38 48 58 68 78 88)

(9 19 29 39 49 59 69 79 89 99)

(10 20 30 40 50 60 70 80 90 100 110)

(21 31 41 51 61 71 81 91 101 111)

(32 42 52 62 72 82 92 102 112)

(43 53 63 73 83 93 103 113)

(54 64 74 84 94 104 114)

(65 75 85 95 105 115)

(76 86 96 106 116)

(87 97 107 117)

(98 108 118)

(109 119)

(120)

AFTER

#2A((0 11 22 33 44 55 66 77 88 99 110)

(1 12 23 34 45 56 67 78 89 100 111)

(2 13 24 35 46 57 68 79 90 101 112)

(3 14 25 36 47 58 69 80 91 102 113)

(4 15 26 37 48 59 70 81 92 103 114)

(5 16 27 38 49 60 71 82 93 104 115)

(6 17 28 39 50 61 72 83 94 105 116)

(7 18 29 40 51 62 73 84 95 106 117)

(8 19 30 41 52 63 74 85 96 107 118)

(9 20 31 42 53 64 75 86 97 108 119)

(10 21 32 43 54 65 76 87 98 109 120))

prozak@Mistral:~/Exploration/lisp/pearls%clisp transpose.lisp

BEFORE

#2A((0 1 2 3 4 5 6 7 8 9 10)

(11 12 13 14 15 16 17 18 19 20 21)

(22 23 24 25 26 27 28 29 30 31 32)

(33 34 35 36 37 38 39 40 41 42 43)

(44 45 46 47 48 49 50 51 52 53 54)

(55 56 57 58 59 60 61 62 63 64 65)

(66 67 68 69 70 71 72 73 74 75 76)

(77 78 79 80 81 82 83 84 85 86 87)

(88 89 90 91 92 93 94 95 96 97 98)

(99 100 101 102 103 104 105 106 107 108 109)

(110 111 112 113 114 115 116 117 118 119 120))

TRANSPOSE

(1 11)

(2 12 22)

(3 13 23 33)

(4 14 24 34 44)

(5 15 25 35 45 55)

(6 16 26 36 46 56 66)

(7 17 27 37 47 57 67 77)

(8 18 28 38 48 58 68 78 88)

(9 19 29 39 49 59 69 79 89 99)

(10 20 30 40 50 60 70 80 90 100 110)

(21 31 41 51 61 71 81 91 101 111)

(32 42 52 62 72 82 92 102 112)

(43 53 63 73 83 93 103 113)

(54 64 74 84 94 104 114)

(65 75 85 95 105 115)

(76 86 96 106 116)

(87 97 107 117)

(98 108 118)

(109 119)

(120)

AFTER

#2A((0 11 22 33 44 55 66 77 88 99 110)

(1 12 23 34 45 56 67 78 89 100 111)

(2 13 24 35 46 57 68 79 90 101 112)

(3 14 25 36 47 58 69 80 91 102 113)

(4 15 26 37 48 59 70 81 92 103 114)

(5 16 27 38 49 60 71 82 93 104 115)

(6 17 28 39 50 61 72 83 94 105 116)

(7 18 29 40 51 62 73 84 95 106 117)

(8 19 30 41 52 63 74 85 96 107 118)

(9 20 31 42 53 64 75 86 97 108 119)

(10 21 32 43 54 65 76 87 98 109 120))

This is the sort of algorithm that may be handy if you have little memory and need to do everything in place, there is no need for a second array making things easy on the memory side of things.

## 4/02/2006

*Programming Pearls*by Jon Bentley, in it I saw a method for rotating the elements of a vector that I just had to implement. Since I now mainly write java for work I decided to implement it in Lisp.

The method for rotating the vector is very simple and elegant it just holds in the following code.

To rotate an array of size N by k positions

- We start by reversing the first k elements,
- Then we reverse the N-k last elements
- Finally we reverse the whole array

Its simple and completely fool proof its one of those methods that just work out of the box, the code is so simple that it can not go wrong. If it appears unclear play around with some examples until it cliks in.

Here are the same three lines translated to lisp.

**;rotate by num elements the collection**

(defun rot (collection num)

(myreverse collection 0 num)

(myreverse collection (+ num 1) (- (length collection) 1))

(myreverse collection 0 (- (length collection) 1 ))

)

(defun rot (collection num)

(myreverse collection 0 num)

(myreverse collection (+ num 1) (- (length collection) 1))

(myreverse collection 0 (- (length collection) 1 ))

)

I decided not to use any libraries to make the example easier to understand so here is the full code of a demo:

**;Example of an in place N rot i in O(N)**

;this implementation is as presented in programming pealrs by Jon Bentley

(setq arr (make-array 23))

;psedudo algo is as follows for all data i between start and end swap

(defun myreverse(data start end)

(dotimes (i (/ (- end start) 2))

(setq k (- end i))

(setq l (+ start i))

(swap data k l)

)

)

;standard swapping of two elements in a vector

(defun swap(vect i j)

(setq temp (aref vect i))

(setf (aref vect i) (aref vect j))

(setf (aref vect j) temp)

)

;rotate by num elements the collection

(defun rot (collection num)

(myreverse collection 0 num)

(myreverse collection (+ num 1) (- (length collection) 1))

(myreverse collection 0 (- (length collection) 1 ))

)

;initialising the collection with simple integers

(dotimes (i (length arr))

(setf (aref arr i) i)

)

;invoking the rotation of five elements

(print "Before: " )

(print arr)

(print "(rot arr 5)" )

(rot arr 5)

(print "After: " )

(print arr)

;this implementation is as presented in programming pealrs by Jon Bentley

(setq arr (make-array 23))

;psedudo algo is as follows for all data i between start and end swap

(defun myreverse(data start end)

(dotimes (i (/ (- end start) 2))

(setq k (- end i))

(setq l (+ start i))

(swap data k l)

)

)

;standard swapping of two elements in a vector

(defun swap(vect i j)

(setq temp (aref vect i))

(setf (aref vect i) (aref vect j))

(setf (aref vect j) temp)

)

;rotate by num elements the collection

(defun rot (collection num)

(myreverse collection 0 num)

(myreverse collection (+ num 1) (- (length collection) 1))

(myreverse collection 0 (- (length collection) 1 ))

)

;initialising the collection with simple integers

(dotimes (i (length arr))

(setf (aref arr i) i)

)

;invoking the rotation of five elements

(print "Before: " )

(print arr)

(print "(rot arr 5)" )

(rot arr 5)

(print "After: " )

(print arr)

Running it in your favoutite Lisp interpreter will give you:

*prozak@Mistral:~/Exploration/lisp/pearls%clisp rot.lisp*

"Before: "

#(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22)

"(rot arr 5)"

"After: "

#(6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 0 1 2 3 4 5)

"Before: "

#(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22)

"(rot arr 5)"

"After: "

#(6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 0 1 2 3 4 5)

There is some inherent beauty in the simple basic elements of programming, today I had the chance to re-discover the basics. Wonder what it will be like if I finally get round to read Knuth's books. ;-)

Subscribe to:
Posts (Atom)