Questions about replacing while and if statements with lisp - 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.

Related

Syntax Error in Lisp Loop for defining variables in a loop

I am a beginner student who is learning Lisp. I want to turn the loop to the i value using k using the loop statement, but the following error appears. I think I wrote the parentheses correctly, but I don't know why this error occurs.
LOOP: illegal syntax near (SETQ K (1+ K)) in
(LOOP WHILE (< K I) (SETQ K (1+ K)))
Below is my code.
(DEFUN promising (i)
(setq k 1)
(loop while (< k i) (setq k (1+ k)))
(return-from promising 1)
)
promising(2)
I see several small things:
The loop syntax is not 100% correct, you missed a do keyword
(loop while (< k i) do (setq k (1+ k)))
^^
do keyword is missing!
The syntax for the function call promising(2) is also incorrect
(promising 2)
The return-from thing is unusual
The first reason is that the return value is always 1, in your case, you probably want to return k.
(DEFUN promising (i)
(setq k 1)
(loop while (< k i) (setq k (1+ k)))
(return-from promising 1))
^
Always return 1
The second reason is you don't need a return-from, the last value of a defun form will be given to the function caller.
(DEFUN promising (i)
(setq k 1)
(loop while (< k i) do (setq k (1+ k)))
k)
^
The last value will be returned to the function caller
The k variable should be defined locally and not use a global definition
The final code could be something like this:
(defun promising (i)
(let ((k 1))
(loop while (< k i) do (setq k (1+ k)))
;; return value
k))
(promising 2)
This should return:
2

Nested IF-statements in Lisp with progn

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))))))

LISP - Closest function without setq/setf etc

I'm trying to write the "closest" function,in Lisp, without using setq/setf etc...
The function finds the nearest vector of a given vector (finding it on a list of lists).
I tried but without sets is too hard,thanks a lot.
Usually the updating of variable is done by recursion:
(defun main-function (arg)
(main-function-helper arg 0 1))
(defun main-function-helper (arg var1 var2)
(if (= arg var1)
var2
(main-function-helper arg (1+ var1) (1+ var2))))
When you're done you can put the helper into the main function:
(defun main-function (arg)
(labels ((helper (var1 var2) ; arg left out since it's not changed
(if (= arg var1)
var2
(helper (1+ var1) (1+ var2)))))
(helper 0 1)))
This is of course a silly implementation of 1+ for positive arguments.
Without set, returns a list of lists in case there are ties:
(NOTE: loop macro uses set at some point :P)
(defun euclid (v1 v2)
(sqrt (loop for x in v1 for y in v2 sum
(expt (- x y) 2))))
(defun closest (target listoflists distancefn)
(loop for l in listoflists for d = (apply distancefn (list target l))
minimizing d into min
collecting (list l d) into col
finally (return
(loop for (vec dis) in col when
(eql dis min) collect vec))))
(closest '(1 2 3) '((1 2 2) ( 1 2 2) ( 2 2 2)) #'euclid)
> ((1 2 2) (1 2 2))

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.

Feedback on lisp program for project euler 4 [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I just started learning common lisp and so I've been working on project euler problems. Here's my solution (with some help from https://github.com/qlkzy/project-euler-cl ). Do you guys have any suggestions for stylistic changes and the sort to make it more lisp-y?
; A palindromic number reads the same both ways. The largest palindrome made
; from the product of two 2-digit numbers is 9009 = 91 99.
; Find the largest palindrome made from the product of two 3-digit numbers.
(defun num-to-list (num)
(let ((result nil))
(do ((x num (truncate x 10)))
((= x 0 ) result)
(setq result (cons (mod x 10) result)))))
(defun palindrome? (num)
(let ((x (num-to-list num)))
(equal x (reverse x))))
(defun all-n-digit-nums (n)
(loop for i from (expt 10 (1- n)) to (1- (expt 10 n)) collect i))
(defun all-products-of-n-digit-nums (n)
(let ((nums (all-n-digit-nums n)))
(loop for x in nums
appending (loop for y in nums collecting (* x y)))))
(defun all-palindromes (n)
(let ((nums (all-products-of-n-digit-nums n)))
(loop for x in nums
when (palindrome? x) collecting x)))
(defun largest-palindrome (n)
(apply 'max (all-palindromes 3)))
(print (largest-palindrome 3))
Barnar's solution is great however there's just a small typo, to return a result it should be:
(defun largest-palindrome (n)
(loop with start = (expt 10 (1- n))
and end = (1- (expt 10 n))
for i from start to end
maximize (loop for j from i to end
for num = (* i j)
when (palindrome? num)
maximize num)))
(setq list (cons thing list))
can be simplified to:
(push thing list)
My other comments on your code are not so much about Lisp style as about the algorithm. Creating all those intermediate lists of numbers seems like a poor way to do it, just write nested loops that calculate and test the numbers.
(defun all-palindromes (n)
(loop for i from (expt 10 (1- n)) to (1- (expt 10 n))
do (loop for j from (expt 10 (1- n)) to (1- (expt 10 n))
for num = (* i j)
when (palindrome? num)
collect num)))
But LOOP has a feature you can use: MAXIMIZE. So instead of collecting all the palindroms in a list with COLLECT, you can:
(defun largest-palindrome (n)
(loop with start = (expt 10 (1- n))
and end = (1- (expt 10 n))
for i from start to end
do (loop for j from start to end
for num = (* i j)
when (palindrome? num)
maximize num)))
Here's another optimization:
(defun largest-palindrome (n)
(loop with start = (expt 10 (1- n))
and end = (1- (expt 10 n))
for i from start to end
do (loop for j from i to end
for num = (* i j)
when (palindrome? num)
maximize num)))
Making the inner loop start from i instead of start avoids the redundancy of checking both M*N and N*M.
The example below is a bit contrived, but it finds the palindrome in a lot less iterations than your original approach:
(defun number-to-list (n)
(loop with i = n
with result = nil
while (> i 0) do
(multiple-value-bind (a b)
(floor i 10)
(setf i a result (cons b result)))
finally (return result)))
(defun palindrome-p (n)
(loop with source = (coerce n 'vector)
for i from 0 below (floor (length source) 2) do
(when (/= (aref source i) (aref source (- (length source) i 1)))
(return))
finally (return t)))
(defun suficiently-large-palindrome-of-3 ()
;; This is a fast way to find some sufficiently large palindrome
;; that fits our requirement, but may not be the largest
(loop with left = 999
with right = 999
for maybe-palindrome = (number-to-list (* left right)) do
(cond
((palindrome-p maybe-palindrome)
(return (values left right)))
((> left 99)
(decf left))
((> right 99)
(setf left 999 right (1- right)))
(t ; unrealistic situation
; we didn't find any palindromes
; which are multiples of two 3-digit
; numbers
(return)))))
(defun largest-palindrome-of-3 ()
(multiple-value-bind (left right)
(suficiently-large-palindrome-of-3)
(loop with largest = (* left right)
for i from right downto left do
(loop for j from 100 to 999
for maybe-larger = (* i j) do
(when (and (> maybe-larger largest)
(palindrome-p (number-to-list maybe-larger)))
(setf largest maybe-larger)))
finally (return largest)))) ; 906609
It also tries to optimize a bit the way you check that number is a palindrome, for an additional memory cost though. It also splits the number into a list using somewhat longer code, but making less divisions (which are somewhat computationally expensive).
The whole idea is based on the concept that the largest palindrome will be somewhere more towards the... largest multipliers, so, by starting off with 99 * 99 you will have a lot of bad matches. Instead, it tries to go from 999 * 999 and first find some palindrome, which looks good, doing so in a "sloppy" way. And then it tries hard to improve upon the initial find.