How to create a list of lists in lisp? - lisp

I am trying to run code in common lisp, but it keeps giving me the following error:
*** - SYSTEM::%EXPAND-FORM: (SETF (NTH X NUMS) 0) should be a lambda
expression
What am I doing wrong? I am pretty new to lisp, and here is my code:
(defun answer-ynq()
(setq nums '(13 15 19 33))
(setq numsstuff '())
(loop for x from 1 to 4
do (progn(
(setf (nth x nums) 0)
(append numstuff nums)
)))
(print numstuff)
)
(answer-ynq)
Also, is this the right way to create a list out of lists? I need numsstuff to be a list of lists in this way, where if I give in a list of objects (13 15 19 33), I get an output that is the following list of lists:
((0 15 19 33) (13 0 19 33) (13 15 0 33) (13 15 19 0))
Thank you so much!

CL-USER > (loop for i below 4
collect (loop for e in '(13 15 19 33)
for j from 0
when (= i j) collect 0 else collect e))
((0 15 19 33) (13 0 19 33) (13 15 0 33) (13 15 19 0))

Related

Change just one position on array Clisp

I'm doing an algorithm that randomizes a TSP (array of citys) based on 1 TSP.
(do ((i 0 (+ i 1)))
((= i n-population))
(setf (aref population i) (shuffle TSP 100))
)
And as far as I know im filling up i positions of the array population with (shuffle TSP 100) that is beeing called each iteration, but the algorithm is setting all array positions and not just i position.
[Note. An earlier version of this answer contained a mistake which would badly alter the statistics of the shuffling: please check below for the corrected version and a note as to what the problem was.]
Given your code, slightly elaborated to turn it into a function:
(defun fill-array-with-something (population n-population TSP)
(do ((i 0 (+ i 1)))
((= i n-population))
(setf (aref population i) (shuffle TSP 100))))
Then each element of population from 0 to (1- n-population) will be set to the result of (shuffle TSP 100). There are then two possibilities:
(shuffle TSP 100) returns a fresh object from each call;
(shuffle TSP 100) returns the same object – probably TSP – from each call.
In the first case, each element of the array will have a distinct value. In the second case, all elements below n-population will have the same value.
Without knowing what your shuffle function does, here is an example of one which will give the latter behaviour:
(defun shuffle (vec n)
;; shuffle pairs of elts of VEC, N times.
(loop with max = (length vec)
repeat n
do (rotatef (aref vec (random max))
(aref vec (random max)))
finally (return vec)))
And we can test this:
> (let ((pop (make-array 10))
(tsp (vector 0 1 2 3 4 5 6 7 8 9 )))
(fill-array-with-something pop (length pop) tsp)
pop)
#(#(2 8 7 1 3 9 5 4 0 6) #(2 8 7 1 3 9 5 4 0 6) #(2 8 7 1 3 9 5 4 0 6)
#(2 8 7 1 3 9 5 4 0 6) #(2 8 7 1 3 9 5 4 0 6) #(2 8 7 1 3 9 5 4 0 6)
#(2 8 7 1 3 9 5 4 0 6) #(2 8 7 1 3 9 5 4 0 6) #(2 8 7 1 3 9 5 4 0 6)
#(2 8 7 1 3 9 5 4 0 6))
As you can see all the elements are mysteriously the same thing, which is because my shuffle simply returned its first argument, having modified it in place.
You can check this by either explicitly checking the result of shuffle, or by, for instance, using *print-circle* to see the sharing. The latter approach is pretty neat:
> (let ((*print-circle* t)
(pop (make-array 10))
(tsp (vector 0 1 2 3 4 5 6 7 8 9 )))
(fill-array-with-something pop (length pop) tsp)
(print pop)
(values))
#(#1=#(4 6 7 0 1 2 5 9 3 8) #1# #1# #1# #1# #1# #1# #1# #1# #1#)
And now it's immediately apparent what the problem is.
The solution is to make sure either that shuffle returns a fresh object, or to copy its result. With my shuffle this can be done like this:
(defun fill-array-with-something (population n-population tsp)
(do ((i 0 (+ i 1)))
((= i n-population))
(setf (aref population i) (shuffle (copy-seq TSP) 100))))
Note that a previous version of this answer had (copy-seq (shuffle TSP 100)): with my version of shuffle this is a serious mistake, as it means that the elements in population are related to each other but get increasingly shuffled as you go along. With (shuffle (copy-seq TSP) 100) each element gets the same amount of shuffling, independently.
And now
> (let ((*print-circle* t)
(pop (make-array 10))
(tsp (vector 0 1 2 3 4 5 6 7 8 9 )))
(fill-array-with-something pop (length pop) tsp)
(print pop)
(values))
#(#(8 3 4 1 6 9 2 5 0 7) #(8 6 5 1 3 0 4 2 9 7) #(5 0 4 7 1 6 9 3 2 8)
#(3 0 7 6 2 9 4 5 1 8) #(8 2 5 1 7 3 9 0 4 6) #(0 5 6 3 8 7 2 1 4 9)
#(4 1 3 7 8 0 5 2 9 6) #(6 9 1 5 0 7 4 2 3 8) #(2 7 5 8 0 9 6 3 4 1)
#(5 4 8 9 6 7 2 0 1 3))
I suspect that the problem is in OP function SHUFFLE which has not yet been shared; my suspicion is that SHUFFLE is shuffling the *TSP* array itself in place instead of creating a shuffled copy of that array. The POPULATION values are then all referencing the same shuffled *TSP* array.
To solve this problem, SHUFFLE should return a shuffled array instead of shuffling the array in place. Here is a function that performs a Fisher-Yates shuffle on a vector:
(defun shuffle-vector (vect)
"Takes a vector argument VECT and returns a shuffled vector."
(let ((result (make-array (length vect) :fill-pointer 0)))
(labels ((shuffle (v)
(if (zerop (length v))
result
(let* ((i (random (length v)))
(x (elt v i)))
(vector-push x result)
(shuffle (concatenate 'vector
(subseq v 0 i)
(subseq v (1+ i))))))))
(shuffle vect))))
Testing in the REPL:
CL-USER> (defvar *TSP* #("Village" "Town" "City" "Metropolis" "Megalopolis"))
*TSP*
CL-USER> (defvar *n-population* 5)
*N-POPULATION*
CL-USER> (defvar *population* (make-array *n-population*))
*POPULATION*
CL-USER> (dotimes (i *n-population*)
(setf (aref *population* i) (shuffle-vector *TSP*)))
NIL
CL-USER> *population*
#(#("Megalopolis" "City" "Metropolis" "Town" "Village")
#("Megalopolis" "Metropolis" "Town" "City" "Village")
#("City" "Megalopolis" "Town" "Village" "Metropolis")
#("City" "Megalopolis" "Village" "Metropolis" "Town")
#("Megalopolis" "Town" "Metropolis" "City" "Village"))

find the position of an atom in list

I have this board with atom T and I wanna get is position in list and sub-list
(defun board ()
"position of T: i=0 e j=9"
'(
;; 0 1 2 3 4 5 6 7 8 9
(96 25 54 89 21 8 36 14 41 T) ;; 0
(78 47 56 23 5 NIL 13 12 26 60) ;; 1
(0 27 17 83 34 93 74 52 45 80) ;; 2
(69 9 77 95 55 39 91 73 57 30) ;; 3
(24 15 22 86 1 11 68 79 76 72) ;; 4
(81 48 32 2 64 16 50 37 29 71) ;; 5
(99 51 6 18 53 28 7 63 10 88) ;; 6
(59 42 46 85 90 75 87 43 20 31) ;; 7
(3 61 58 44 65 82 19 4 35 62) ;; 8
(33 70 84 40 66 38 92 67 98 97);; 9
)
)
Function to get line and cell from board
(defun line (x board)
(nth x board))
(defun cell-board (x y board)
(nth y (line x board)))
(defun column (index board)
(cond ((not (numberp index)) nil)
((< index 0) nil)
(t (mapcar #'(lambda (line &aux (n-column (nth index line))) n-column) board))))
Function that receives the board and returns the position (i j) where the "T" is. If "T" is not on the board, NIL should be returned.
(defun find-T-position (board)
)
you can teste and see the result here https://ideone.com/GQIePI
(print "position : " (find-T-position (board)))
the result correct should be
(0 9)
The board function tries to call a literal list as-if it was a function. The quote is misplaced.
The find-t-position function has no body.
If you add more code and an actual question you will have better feedback.
Hint: either T is in current row (car board), or you need to search the board (cdr board); test often to spot errors.
(defun find-t (rows)
(let* ((col nil)
(row (position-if (lambda (r) (setf col (position t r))) rows)))
(values row col)))
Some tests:
[1]> (find-t nil)
NIL ;
NIL
[2]> (find-t '(()))
NIL ;
NIL
[3]> (find-t '((0)))
NIL ;
NIL
[4]> (find-t '((t)))
0 ;
0
[5]> (find-t '((0 t)))
0 ;
1
[6]> (find-t '((0 t 0)))
0 ;
1
[7]> (find-t '((0 0 t)))
0 ;
2
[8]> (find-t '((0 0 0)))
NIL ;
NIL
[9]> (find-t '((0 0 0)
(t 0 0)))
1 ;
0
[10]> (find-t '((0 0 0)
(t 0 t)))
1 ;
0
[11]> (find-t '((0 0 0)
(0 0 t)))
1 ;
2
[12]> (find-t '((0 0 t)
(0 0 t)))
0 ;
2
I find the answer in this question Lisp position of nested list element with children and it´s work perfectly
(defun my-position (elm tree &optional (start 0))
"find the generalized position of elm inside tree.
Parameters: elm - element to be found
tree - a list of atoms and lists in which to search the element
start - the tentative position"
(cond ((null tree) nil) ; element not present => nil
((atom (first tree)) ; if the first element is an atom, then
(if (eql elm (first tree)) ; if equal to element, found
(list start) ; return position start
;; otherwise, recur on rest of list incrementing the tentative position
(my-position elm (rest tree) (1+ start))))
;; otherwise, the first element is a list,
;; try to find it inside, with a recursive call
(t (let ((pos (my-position elm (first tree) 0)))
(if pos ; if not nil the element has been found
(cons start pos) ; return the current position followed by the position inside the list
; otherwise recur on rest of list incrementing the tentative position
(my-position elm (rest tree) (1+ start)))))))
and my function find-t-position just call the function my-position
with element 'T and the board and return the position of element 'T in
list
(defun find-T-position (board)
(my-position ('T board))
you can see the correct result https://ideone.com/DOIOoB

How do I check what elements in a list are divisible by five in LISP?

I have two functions in my program. The one that is commented out mods every element in a list by five. And the second function counts how many times an element appears in a list. How do I combine both of these to get my desired result of determining how many elements of a list are divisible by five?
Here is my code:
(defun divide-bye-five (lst)
(loop for x in lst collect (mod x 5)))
(defun counter (a lst)
(cond ((null lst) 0)
((equal a (car lst)) (+ 1 (counter a (cdr lst))))
(t (counter a (cdr lst)))))
(counter '0 '(0 0 0 20 0 0 0 0 0 5 31))
If you need just select all elemets in list, which are dividable by five, you can use remove-if-not.
(defun dividable-by-5 (num)
(zerop (mod num 5))
CL-USER> (remove-if-not #'dividable-by-5 '(1 2 3 10 15 30 31 40))
(10 15 30 40)
But I'm not sure, do you want select this elements, or just count them? Of course you can count them by calling length on resulting list, or of you don't need all elements, but just a number, you can use count-if.
CL-USER> (count-if #'dividable-by-5 '(1 2 3 10 15 30 31 40))
4
If you have two functions where the result of one is what you would like as the input for the second you can combine them like this:
(second-fun (first-fun first-fun-arg ...))
So specifically using your provided functions it should work doing:
(counter 0 (divide-bye-five '(1 2 3 4 5 6 7 8 9 10))) ; ==> 2
If you'd like to abstract it you make it a function:
(defun count-dividable-with-five (lst)
(counter 0 (divide-bye-five lst)))

Lisp sort function

I am trying to make a (somehow) delicate sorting function in Lisp. I know there is lambda operator that should make my work a lot easier, but I couldn't find anything helpful so I hope you can help me.
As an input I have a nested list like this one:
((o1 10 15 20) (o2 5 14 20) (o3 7 8 8))
The output should be a nested list like this one:
((o1 1 1 1) (o2 3 2 1) (o3 2 3 3))
To be more specific, the first element from o1 is compared to the first element from o2 and o3 and the return should be it's position (in the example above, 10 is greater than 5 and 7 so it will be on the first position in the resulting list) and so on.
The highest number will get the first position.
(it's like a score function. Some students make an application and their features numbers are compared. The one with highest number of features will get the first place, but when comparing the number of different technologies used, he may get the 2nd or 3rd place).
Thanks and I hope you can help me
A little exploration is in order.
[3]> (setq a '((o1 10 15 20) (o2 5 14 20) (o3 7 8 8)))
((O1 10 15 20) (O2 5 14 20) (O3 7 8 8))
[4]> (setq b (apply #'mapcar #'list a))
((O1 O2 O3) (10 5 7) (15 14 8) (20 20 8))
[5]> (setq c (mapcar #'(lambda(x)(sort x #'>)) (cdr b)))
((10 7 5) (15 14 8) (20 20 8))
[6]> (mapcar #'(lambda(g)(cons (car g) (mapcar #'1+
(mapcar #'position (cdr g) c)))) a)
((O1 1 1 1) (O2 3 2 1) (O3 2 3 3))
Now stir, form, and bake at 190 C until ready.

How to print a list as matrix in Common Lisp

I am working in Common Lisp, trying to make Windows game minesweeper.
I have a list (1 1 1 2 2 2 3 3 3) and want to print that like matrix
(1 1 1
2 2 2
3 3 3)
How to do that?
Edit
I am at the beginning of
(format t "Input width:")
(setf width (read))
(format t "Input height:")
(setf height (read))
(format t "How many mines:")
(setf brMina (read))
(defun matrica (i j)
(cond ((= 0 i) '())
(t (append (vrsta j) (matrica (1- i) j) ))))
(setf minefield (matrica width height))
(defun stampaj ()
(format t "~%~a" minefield ))
Another example, using the pretty-printer for fun:
(defun print-list-as-matrix
(list elements-per-row
&optional (cell-width (1+ (truncate (log (apply #'max list) 10)))))
(let ((*print-right-margin* (* elements-per-row (1+ cell-width)))
(*print-miser-width* nil)
(*print-pretty* t)
(format-string (format nil "~~<~~#{~~~ad~~^ ~~}~~#:>~%" cell-width)))
(format t format-string list)))
Works like this:
CL-USER> (print-list-as-matrix (loop for i from 1 to 9 collect i) 3)
1 2 3
4 5 6
7 8 9
NIL
CL-USER> (print-list-as-matrix (loop for i from 1 to 25 collect i) 5)
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
NIL
CL-USER> (print-list-as-matrix (loop for i from 1 to 16 collect i) 2)
1 2
3 4
5 6
7 8
9 10
11 12
13 14
15 16
Like this:
(defun print-list-as-grid (list rows cols)
(assert (= (length list) (* rows cols))
(loop for row from 0 below rows do
(loop for col from 0 below cols do
(princ (car list))
(princ #\space)
(setf list (cdr list)))
(princ #\newline)))
* (print-list-as-grid '(a b c d e f g h i) 3 3)
A B C
D E F
G H I
NIL