Nested IF-statements in Lisp with progn - lisp

I have a questions about multiple if-statements in lisp. If count is not equal to n I want to continue on with the let and if statements, else I want to do (= (abs (- row i)) and if that is t return nil.
However, I find that whenever count is not n I will return nil because progn always returns the last line of code in the block. Please share with me how I can write the program so that I only when count is not n I will only return nil when any of the or clauses are t.
(loop for i below n
do (if (/= count n)
(progn
(let ((tcol (getqueencol i n)))
(if (or (= col tcol) (= (abs (- row i)) (abs (- col tcol))))
(return-from queen-can-be-placed-here nil))))
(if (= (abs (- row i)))
(return-from queen-can-be-placed-here nil))))
UPDATED:
Thank you for good response. Yes, indeed I am trying to solve the N queen puzzle :P The problem I have right now is that my control to determine if placing a queen at a certain row and column is not working when the row is empty. That is because getqueencol will return nil when the row is empty and in queen-can-be-placed-here there will be a (= nil NUMBER).
To combat that I tried to make a count variable in queen-can-be-placed-here that knows whether a row is empty or not, and that would enable me to not call getqueencol on an empty row. The problem is though that I do not know how the check will be in queen-can-be-placed-here when a queen is to be added to an empty row.
Here is the code so far:
(defvar *board* (make-array '(5 5) :initial-element nil))
(defun getqueencol (row n)
"Traverses through the columns of a certain row
and returns the column index of the queen."
(loop for i below n
do (if (aref *board* row i)
(return-from getqueencol i))))
(defun print-board (n)
"Prints out the solution, e.g. (1 4 2 5 3),
where 1 denotes that there is a queen at the first
column of the first row, and so on."
(let ((solutionlist (make-list n)))
(loop for row below n
do (loop for col below n
do (when (aref *board* row col)
(setf (nth row solutionlist) col))))
(print solutionlist)))
(defun queen-can-be-placed-here (row col n)
"Returns t if (row,col) is a possible place to put queen, otherwise nil."
(let ((count 0))
(loop for i below n ;This is the block I added to keep track of if a row is empty (count = n)
do (if (not (aref *board* row i))
(setf count (+ 1 count))))
(loop for i below n
do (if (/= count n)
(let ((tcol (getqueencol i n)))
(if (or (= col tcol) (= (abs (- row i)) (abs (- col tcol))))
(return-from queen-can-be-placed-here nil)))
(if (= (abs (- row i))) ;Here is where I don't know what to check
(return-from queen-can-be-placed-here nil)))))
(return-from queen-can-be-placed-here t))
(defun backtracking (row n)
"Solves the NxN-queen problem with backtracking"
(if (< row n)
(loop for i below n
do (when (queen-can-be-placed-here row i n)
(setf (aref *board* row i) 't)
(backtracking (+ row 1) n)
(setf (aref *board* row i) 'nil)))
(print-board n)))
(defun NxNqueen-solver (k)
"Main program for the function call to the recursive solving of the problem"
(setf *board* (make-array (list k k) :initial-element nil))
(backtracking 0 k))

I have a questions about multiple if-statements in lisp. If count is
not equal to n I want to continue on with the let and if statements,
else I want to do (= (abs (- row i)) and if that is t return nil.
Once you start having multiple forms on either branch of an if, it's often clearer to use cond instead:
(cond
((/= n count) ; if n is not count, then ...
(let ...
(return-from ...))) ; maybe return something
((= (abs (- row i)) ...) ; else if |row-i] = ...,
(return-from ...))) ; return nil
That said, you don't actually have multiple branches in the then part of your if. There's no need to wrap let in progn. You can just do:
(if (/= count n)
(let ((tcol (getqueencol i n)))
(if (or (= col tcol) (= (abs (- row i)) (abs (- col tcol))))
(return-from queen-can-be-placed-here nil)))
(if (= (abs (- row i)))
(return-from queen-can-be-placed-here nil)))
As to returning nil from the if, there are two things to consider. You're using return-from, which means that you're performing a non-local exit. While the value of an expression of the form (if test then) is nil when test is false, you're never doing anything with that value. Actually, it's a fairly common style in Common Lisp to use when in the case that there's no else part. That is, (when test then) is equivalent to (if test then nil) and to (if test then). It's true that it means (if ...) evaluates to nil, so nil is the value of the let, and thus of the progn, but you don't actually do anything with the value of the progn; it's just a form that you're evaluating within the loop.

Each call to backtrack tries to place a queen at each possible column. That means that when you are calling queen-can-be-placed-here at row row, you can be sure that all rows including row that come after row are empty (you erase the board when backtracking).
So you only need to check if the queen can be placed correctly at current column col and current row by looking at the subset of the board that has a lesser row.
col
v
c0 v c1
r0 Q - - -
r1 - - Q -
row >> - ? - -
- - - -
There can be a queen only if, for all above rows, guetqueencol returns a column that is different from col or in a direct diagonal position (the computations with abs). So you don't really need to count anything, just ensure that a test is never met.
There are minor issues with the code like variable names, so once you are sure everything works as intended you can ask on CodeReview for more feedback, if you want.
What I think is the appropriate answer is inside the following spoiler section.
(defun queen-can-be-placed-here (row col n)
"Returns t if (row,col) is a possible place to put queen, otherwise nil."
(loop
for r below row
for c = (getqueencol r n)
never (or (= col c)
(= (abs (- row r))
(abs (- col c))))))

Related

Questions about replacing while and if statements with lisp

I want to change the code below to Lisp code, but I keep getting errors in grammar. How do I fix the if statement?
int promising(int i)
{
int k = 1;
while (k < i)
{
if (col[i] == col[k] || abs(col[i] - col[k]) == abs(i - k))
return 0;
k++;
}
return 1;
}
Below is the one I changed to the Lisp code.
(setq col (list 0 0 0 0))
(DEFUN promising (i)
(let ((k 1)) ; k =1
(loop while (< k i)
do((if (or ( = (nth i col) (nth k col))
(= ( abs((setq a (- (nth i col) (nth k col)))))
( abs((setq b (- i k ))))))
(return-from promising 0)))
do (setq k (1+ k)))
(return-from promising 1))
)
It is difficult for me to flexibly change the complicated condition of the if statement to the lisp code.
You are doing "C-in-Lisp". Trying to directly translate C (or for that matter, C++/Java/C#/Python ...) programs into Lisp will often lead to poor code, and you should be better off trying to understand how those problems are sovled in Lisp.
That being said:
You should not use (setq col <whatever>) at the toplevel. Global variables are introduced using defvar or defparameter and their name is of the form *variable-name* to distinguish them from other variables. This is because they have different scoping rules, and behave differently (i.e. they are not equivalent to other languages' global variables). In particular, using setq with a variable that has not been declared with defvar or defparameter is undefined behaviour, and most implementations will allow it, but they will then create this global variable. You generally don't want that. To sum up: either use (defvar *col* (list 0 0 ...)) if you need this really is a global variable, or simply use (let ((col (list 0 ...))) <more-code>) where you need it.
loop is a complicated construct. This is, in itself, another mini-language that you have to learn on top of Lisp. In particular, if all you ever want to do is "loop with some variable between some bounds and increment it by some value at each step", use
(loop for k from 1 do ...) ;; this introduces a local variable k, incremented by 1 at each step, with no upper bound
(loop for k from 1 to 10 do ...) ;; same, but only loop until k reaches 10
(loop for k from 1 to 10 by 3 do ...) same, but increments k by 3 at each step
Other constructs are available. Read this section of Practical Common Lisp for a good introduction, and the relevant CLHS section for a technical description and documentation.
Please follow conventions for whitespace this makes it much easier to read. For example, never place a parenthesis alone on its line (e.g. your very last parenthesis), and ( abs((setq b (- i k )))) should really be written (abs ((setq b (- i k)))) (ignoring the fact that this is incorrect, see below ...). As far as style is concerned, you also need to fix the indentation, and don't write DEFUN is uppercase, it is unnecessary and looks weird.
You cannot place extra parenthensis just to group things together, parenthesis have semantic meaning. In particular, in most cases, calling a function or using pretty much any special operator is done by (<operator-name> <first-arg> <second-arg> ... ). You almost never have 2 consecutive opening parenthesis.
Why are you using (setq a ...) and (setq b ...) in your loop ? Neither a nor b is ever declared or used anywhere else.
If you want to access specific elements of a list, don't use a list, use a vector. In particular, several calls to the nth function is often the sign that you really should have been using a vector.
A correct version of your code, using a few loop facilities, and still assuming that col is a list (which is should not be) although there would be other loop constructs making this even clearer ...
(defun promising (i)
(loop for k from 1 below i
for col-k = (nth k col)
do (when (or (= (nth i col) (nth k col))
(= (abs (- (nth i col) (nth k col)))
(abs (- i k))))
(return-from promising 0)))
1)
Note that this code is incredibly inefficient and this is why I suggested not to translate directly from C to Lisp. In particular, although you traverse a list (you access the k-th element at the k-th step), your code calls nth at each step instead of traversing the list ! You also compute (nth i col) at each step, which is already useless in C (it is constant so doesn't need to be recomputed at every step), but is catastrophic here. This should really be:
(defun promising (i)
(let ((col-i (nth i col)))
(loop for k from 1 below i
for col-k in (cdr col) ;; you start from the index 1, not 0
do (when (or (= col-i col-k)
(= (abs (- col-i col-k))
(abs (- i k))))
(return-from promising 0))))
1)
There are several mistakes in the code.
Incorrect function calls
(DEFUN promising (i)
(let ((k 1)) ; k =1
(loop while (< k i)
do((if (or ( = (nth i col) (nth k col))
;; ^^
;; Incorrect
)
And also here:
(setq col (list 0 0 0 0))
(DEFUN promising (i)
(let ((k 1)) ; k =1
(loop while (< k i)
do((if (or ( = (nth i col) (nth k col))
(= ( abs((setq a (- (nth i col) (nth k col)))))
;; ^^
;; Incorrect
( abs((setq b (- i k ))))))
;; ^^
;; Incorrect
(return-from promising 0)))
do (setq k (1+ k)))
(return-from promising 1))
)
The loop macro have 2 do keywords
(setq col (list 0 0 0 0))
(DEFUN promising (i)
(let ((k 1)) ; k =1
(loop while (< k i)
do((if (or ( = (nth i col) (nth k col))
;; ^^
;; First do
(= ( abs((setq a (- (nth i col) (nth k col)))))
( abs((setq b (- i k ))))))
(return-from promising 0)))
do (setq k (1+ k)))
;; ^^
;; Second do
(return-from promising 1))
)
return-from is used several times
return-from is usually not present in Common Lisp code, this is pretty much like C goto, something developers try to avoid.
Incoherent setq defining a and b (probably old code)
(setq col (list 0 0 0 0))
(DEFUN promising (i)
(let ((k 1)) ; k =1
(loop while (< k i)
do((if (or ( = (nth i col) (nth k col))
(= ( abs((setq a (- (nth i col) (nth k col)))))\
;; ^^^^^^
;; ??
( abs((setq b (- i k ))))))
;; ^^^^^^
;; ??
Weird incrementation scheme
(setq k (1+ k))
While being correct, Common Lisp programmers will simply use the increment function:
(incf k)
Final code
The code you might looking for should be close to that one:
(defun promising (i)
(let ((k 1))
(loop while (< k i) do
(if (or (= (nth i col) (nth k col))
(= (abs (- (nth i col) (nth k col)))
(abs (- i k ))))
(return-from promising 0))
(incf k))
;; return value
k))
Please note that the code is not equivalent to the C version, because the data structure is completely different. In the C version, the access to the data will be very fast O(1). The Common Lisp version will be slow if you have a large number of elements O(n). You can be fast with Common Lisp if you replace your list by an array/vector.

N-Queen Lisp (1- n) mean?

(defun queens (n &optional (m n))
(if (zerop n)
(list nil)
(loop for solution in (queens (1- n) m) ;; <=== what does the (1- n) mean?
nconc (loop for new-col from 1 to m
when (loop for row from 1 to n
for col in solution
always (/= new-col col (+ col row) (- col row)))
collect (cons new-col solution)))))
(defun print-solution (solution)
(loop for queen-col in solution
do (loop for col from 1 to (length solution)
do (write-char (if (= col queen-col) #\Q #\.)))
(terpri))
(terpri))
(defun print-queens (n)
(mapc #'print-solution (queens n)))
hi, can anyone explain to me this N-Queen algo why is there a (1- n)? what does the "1-" part and &optional syntax?
thank you,
1- is a function that subtracts one from its parameter.
&optional states that optional parameters will follow. Usually the default value is nil, but if you specify it as a list - i.e. (m n) then the parameter defaults to the second value in the list (in this case m defaults to n if a second parameter is not passed).

Lisp list number of element

I'm preparing myself for my upcoming exam in LISP and I've come across a problem I can't solve, so I was hoping someone more experienced might help me out.Im trying to make a recursive lisp program that returns the position of an element n from a list but i cant use nth.I need to verify if n is in the list between 0 and length of the list -1 if the element is not in the list a error message should appear.
Something like this:(my-list '(1 2 3) 4) =>"error the list has only 3 elements"
Can someone help me with this problem Im still a novice when it comes to LISP
My code so far:
(defun no-nth (n list)
(declare (type (integer 0) n) (type list))
(if (or (zerop n) (null list))
(cons (car list) (no-nth (1- n) (cdr list)))))
Use labels to make a helper. You have the list and an index as argument. When the list is empty you return whatever you do when it's not found, perhaps nil. If not you check the first element with your search term and return index if it's a match. If not you recur with rest of the list and the increment of the index.
Both your problem description and code are confused.
Let's settle for the name no-nth and the parameter order n, then list.
So you have 3 different cases:
n < 0 or list is empty => element could not be found => return nil
n = 0 => result is first element of the list (assuming that the first position is index 0)
n > 0 => recurse by decrementing n and shortening the list by 1.
The code would then be:
(defun no-nth (n list)
(cond
((or (< n 0) (null list)) nil) ; (1) index not in list
((zerop n) (car list)) ; (2) index = 0 => return first element of list
(t (no-nth (1- n) (cdr list))))); (3) index > 0 => recurse down
Do you think of something like this?
(defun no-nth (n list)
(labels ((nth-intern (n list)
(if (zerop n) (car list)
(nth-intern (1- n) (cdr list)))))
(if (< (list-length list) n)
(error "LIST has no Nth element.")
(nth-intern n list))))
(defun help-func (n list)
(cond
((= n 1) (car list))
(T (help-func (1- n) (cdr list)))))
(defun no-nth (n list)
(cond
((or (< n 0) (>= n (length list))) 'invalid-index)
(T (help-func n list))))
(print (no-nth 2 '(1 2 3)))
(print (no-nth 21 '(1 2 3)))
If you want to see the result: http://ideone.com/zW0gvD
First you check if the index is valid, if it's not, you return invalid-index.
If it's valid, you call help-func, a recursive function.
Recursively, you decrease n until you get to n=1 (or n=0, if you want a zero base index element).

Assigning random values to variables one at a time and using that information in LISP

Right now I"m working on a program that should be able to pick 3 people out of a list of 7 ( a b c d e f g) and assign them to be criminals. This "game" then picks 3 random peolpe out of the 7, tells you how many of those people are criminals and asks if you want to guess who the three criminals are, having one guess ( "two of these three are crimnals would you like to guess who the criminals are). However, I currently have a program that pulls 3 random criminals from the list, however the struggle I"m having is initially assigning who's a criminal or not ( randomly picking 3 out of a list and assigning them to values that can be recalled later ) and then being able to print that back out. This is my code so far and I was hoping somebody could point me in the right direction, I'm still very new to functional programming as a whole.
;allows us to use prompt to ask the user for input
(defun prompt-read (prompt)
(format *query-io* "~a: " prompt)
(force-output *query-io*)
(read-line *query-io*))
;allows you to add elements in needed spots
(defun element-at (org-list pos &optional (ini 1))
(if (eql ini pos)
(car org-list)
(element-at (cdr org-list) pos (+ ini 1))))
(defun element-at (lista n)
(if (= n 1)
(first lista)
(element-at (rest lista) (1- n))))
;allows for the removal of unneeded elements
(defun remove-at (org-list pos &optional (ini 1))
(if (eql pos ini)
(cdr org-list)
(cons (car org-list) (remove-at (cdr org-list) pos (+ ini 1)))))
;returns a chosen number of random elements from a list
(defun rnd-select (org-list num &optional (selected 0))
(if (eql num selected)
nil
(let ((rand-pos (+ (random (length org-list)) 1)))
(cons (element-at org-list rand-pos) (rnd-select (remove-at org-list rand-pos) num (+ selected 1))))))
;returns 3 random criminals from a list of 7
(defun rnd-criminals ()
(rnd-select '(a b c d e f g) 3))
(defun game ()
(prompt-for-players))
;allows for the storing of number of players
(defun num-of-players(number)
(list :number number))
;prompts for the amount of players you want to play
(defun prompt-for-players ()
(num-of-players
(or (parse-integer (prompt-read "How many players are there?"
:junk-allowed t) 0))))
This is a sampling without replacement problem (since, I'd assume, you wouldn't want to "pick three criminals" by picking the same person from the list each time). There are lots of ways to do this. One way is to generate indices until you've got enough distinct ones. How about something like this:
(defun pick (sequence n)
"Return n elements chosen at random from the sequence."
(do ((len (length sequence)) ; the length of the sequence
(indices '()) ; the indices that have been used
(elements '())) ; the elements that have been selected
((zerop n) ; when there are no more elements to select,
elements) ; return the elements that were selectd.
(let ((i (random len))) ; choose an index at random
(unless (member i indices) ; unless it's been used already
(push i indices) ; add it to the list of used indices
(push (elt sequence i) elements) ; and grab the element at the index
(decf n))))) ; and decrement n.
If you're not so familiar with do, you could use a recursive approach, e.g., with a local recursive function:
(defun pick2 (sequence n &aux (len (length sequence)))
(labels ((pick2 (indices elements n)
(if (zerop n) ; if no more elements are needed,
elements ; then return elements.
(let ((i (random len))) ; Otherwise, pick an index i.
;; If it's been used before,
(if (member i indices)
;; then continue on with the same indices,
;; elements, and n.
(pick2 indices elements n)
;; else, continue with it in the list of
;; indices, add the new element to the list of
;; elements, and select one fewer elements
;; (i.e., decrease n).
(pick2 (list* i indices)
(list* (elt sequence i) elements)
(1- n)))))))
;; Start the process off with no indices, no elements, and n.
(pick2 '() '() n)))
Another approach would one based on Efficiently selecting a set of random elements from a linked list which suggests Reservoir Sampling.

looping through two lists while updating one of the lists

I have two lists as follows:
(x y z) & (2 1)
and I want to have a result like:
((x y) (z))
The relation of the lists is quite clear. So basically I want to rearrange the members of the first list into a list of lists with two (length of second list) lists.
I have tried running two dotimes iterations to do this:
(let ((result) (list1* list1))
(dotimes (n (length list2) result)
(progn (setq result
(append result
(list (let ((result2))
(dotimes (m (nth n list2) result2)
(setq result2
(append result2
(list (nth m list1*)))))))))
(setq list1*
(subseq list1* 0 (nth n list2))))))
The idea is that I make the first list of the expected result (x y), and then I want to update the (x y z) list so that the x any y are removed and I only have (z). Then the loop runs again to get the (z) list in the expected result. This does not work correctly and results in:
((x y) (x))
which means apparently the second command for progn which is basically updating the list1* is not working. Clearly there must be a correct and better way of doing this and I was wondering whether anyone can help with this. Also explain why it is not possible to have the solution explained?
If I see that right, your problem is in (subseq list1* 0 (nth n list2)), which returns the part of the list that you do not want.
I have the following to offer:
(defun partition-list (list lengths)
(mapcar (lambda (length)
(loop :repeat length
:collect (pop list)))
lengths))
This is a bit simplistic, of course, as it does not handle unexpected input, such as (length list) being smaller than (reduce #'+ lengths), but it can be expanded upon.
Just for the sake of example, an alternative using iterate:
(defun partition-list (list by)
(iter:iter
(iter:for element in list)
(iter:for i from 1)
(iter:generating measure in by)
(iter:collect element into sublist)
(when (= (or measure (iter:next measure)) i)
(iter:collect sublist)
(iter:next measure)
(setf i 0 sublist nil))))