I am working on the N-queens problem using backtracking in Lisp. So far, my code prints all possible solutions for n>=4. However, I wish to print only the first solution for any value of n.
(defun backtracksearch (row n)
// (if () *I probably need a line here to stop once the first solution is found*
(if (< row n)
(loop for j below n
do (when (is-safe row j n)
(setf (aref *chessboard* row j) 'board)
(backtracksearch (+ 1 row) n)
(setf (aref *chessboard* row j) 'nil)))
(print-solution n)))
I have tried to use the same implementation/logic as that in the C++ solution of backtracking n-queens.
Any advice on the possible way forward would be helpful.
Some feedback on your code:
It is badly formatted, indent as follows:
(defun backtracksearch (row n)
(if (< row n)
(loop for j below n
do (when (is-safe row j n)
(setf (aref *chessboard* row j) 'board)
(backtracksearch (+ 1 row) n)
(setf (aref *chessboard* row j) 'nil)))
(print-solution n)))
// are comments in c++, use ; instead
(dotimes (j n) (when ...)) would be sufficient.
Some questions to help you find a solution:
What happens when there is no j satisfying is-safe?
In particular, what is the return value of backstracksearch?
What is the return value when you find a solution?
How could you determine if a recursive call to backtracksearch found a solution?
Could you use this information to avoid computing other solutions?
Related
I'm pretty new to Common Lisp. And I try to build my own operator functions.
In the first function I tried to add one to the given number.
The second function we do a recursive use of the first in the frequency of m.
When I enter totaladd ( 5 3 ) I expect an 8.
What can I do about the undefined funciton k?
(defun add1(n)
(+ n 1)
)
(write (add1 5))
(defun totaladd (k m)
(if (eq m 0)
0
(totaladd(add1(k) (- m 1)))
)
)
(write (totaladd 5 3))
There are three errors in the next line:
(totaladd(add1(k) (- m 1)))
Let's look at it:
(totaladd ; totaladd is a function with two parameters
; you pass only one argument -> first ERROR
(add1 ; add1 is a function with one parameter
; you pass two arguments -> second ERROR
(k) ; K is a variable, but you call it as a function,
; but the function K is undefined -> third ERROR
(- m 1)))
(defun add1 (n) (+ n 1))
(defun totaladd (k m)
(if (= m 0)
k
(add1 (totaladd k (- m 1)))))
There is a extra function for (= ... 0) called zerop which asks whether a number os zero or not. Very frequently used when recursing over numbers as the break condition out of the recursion.
There is also an extra function for (- ... 1) or (+ ... 1) because these are common steps when recursing with numbers: (1- ...) and (1+ ...), respectively.
(Their destructive forms are (incf ...) and (decf ...), but these are not needed for recursion.)
So, using this, your form becomes:
(defun totaladd (k m)
(if (zerop m)
k
(add1 (totaladd k (1- m)))))
UPDATED: The code should compile now without errors or warnings. Sorry about the previous one. The problem I have now is that when a run (or with any other integer)
(NxNqueen-solver 10)
The function getqueencol will return nil because there are no queens on the board in the first place, hence there will be a (= number nil) in the queen-can-be-placed-here because tcol will be nil. I think this will happen everytime there is no queen in the row passed as argument to the queen-can-be-placed-here function.
Please share some advice on how to fix this problem. Thank you in advance.
Here is the code
(defvar *board* (make-array '(10 10) :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."
(loop for i below n
do (let ((tcol (getqueencol i n)))
(if (or (= col tcol) (= (abs (- row i)) (abs (- col tcol))))
(return-from queen-can-be-placed-here nil)))))
(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)
(return-from backtracking (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 '(k k) :initial-element nil))
(backtracking 0 k))
You say that you compiled your code. That can't be the case, since then you would have see the compiler complaining about errors. You want to make sure that you really compile the code and correct the code, such that it compiles without errors and warnings.
You might want to get rid of the errors/problems in the code (see Renzo's comment) and then look at the algorithmic problem. I makes very little sense to look into an algorithmic problem, when the code contains errors.
SETQ does not introduce a variable, the variable has to be defined somewhere
DEFVAR makes no sense inside a function.
Something like (let (x (sin a)) ...) definitely looks wrong. The syntax of LET requires a pair of parentheses around the bindings list.
RETURN-FROM takes as first argument the name of an existing block to return from. The optional second argument is a return value. Get the syntax right and return from the correct block.
in a call to MAKE-ARRAY specify the default value: (make-array ... :initial-element nil), otherwise it's not clear what it is.
The variable *board* is undefined
Style
in LOOP: for i to (1- n) is simpler for i below n
you don't need to quote NIL and T.
(if (eq foo t) ...) might be simpler written as (if foo ...). Especially if the value of foo is either NIL or T.
(if foo (progn ...)) is simply (when foo ...)
I'm not sure what you are doing to claim that your code compiles. It does not compile.
Every function has compiler warnings. You should check the compiler warnings and fix the problems.
(defun getqueencol (row)
"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))))
The compiler complains:
;;;*** Warning in GETQUEENCOL: N assumed special
;;;*** Warning in GETQUEENCOL: BOARD assumed special
Where is n defined? Where is board coming from?
(defun print-board (board)
"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)
(setq 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))
The LET makes no sense. (let (foo) (setq foo bar) ...) is (let ((foo bar)) ...).
Why is solutionlist not defined? Look at the LET... it does not make sense.
Where is n coming from?
(defun queen-can-be-placed-here (row col)
"Returns t if (row,col) is a possible place to put queen, otherwise nil."
(loop for i below n
do (let (tcol)
(setq tcol (getqueencol i)))
(if (or (= col tcol) (= (abs (- row i)) (abs (- col tcol))))
(return-from queen-can-be-placed-here nil))))
where is n coming from? The LET makes no sense.
(defun backtracking (row)
"Solves the NxN-queen problem with backtracking"
(if (< row n)
(loop for i below n
do (when (queen-can-be-placed-here row i)
(setf (aref board row i) 't)
(return-from backtracking (backtracking (+ row 1)))
(setf (aref board row i) 'nil))
(print-board board))))
Where is n coming from? Where is board defined?
(defun NxNqueen-solver (k)
"Main program for the function call to the recursive solving of the problem"
(let (n board)
(setq n k)
(setq board (make-array '(k k) :initial-element nil)))
(backtracking 0))
Why use setq when you have a let? The local variables n and board are unused.
MAKE-ARRAY expects a list of numbers, not a list of symbols.
I propose you use a basic Lisp introduction (Common Lisp: A Gentle Introduction to Symbolic Computation - free download) and a Lisp reference (CL Hyperspec).
I decided to write a function that given a number will return a list containing the digits in that number, my attempt is:
(define (rev-digits n)
(if (= n 0)
'()
(cons (modulo n 10) (digits (quotient n 10)))))
(define (digits n)
(reverse (rev-digits n)))
The fact is, I need the digits to be in proper order, but the function returns, for example:
> (digits 1234567890)
'(9 7 5 3 1 2 4 6 8 0)
In seemingly random order... can you help me getting a more ordinated output?
rev-digits needs to call itself, not digits.
(define (rev-digits n)
(if (= n 0)
'()
(cons (modulo n 10) (rev-digits (quotient n 10)))))
(define (digits n)
(reverse (rev-digits n)))
should work.
It's worth noting that your "random" output was not in fact random; rather the digits were "bouncing" back and forth from the start to the end of the list. Which makes sense, because you were effectively switching back and forth between a "normal" and reversed version of your digits function.
The answer given by #JayKominek is spot-on and fixes the error in your code. To complement it, here's an alternative implementation:
(define (rev-digits n)
(let loop ((n n) (acc '()))
(if (< n 10)
(cons n acc)
(loop (quotient n 10) (cons (modulo n 10) acc)))))
The advantages of the above code are:
It's tail recursive and hence more efficient
It correctly handles the edge case when n is zero (your code returns an empty list)
It doesn't require a helper procedure, thanks to the use of a named let
It builds the list in the correct order, there's no need to reverse it at the end
A simple solution:
#lang racket
(define (digits n)
(for/list ([c (number->string n)])
(- (char->integer c) (char->integer #\0))))
The function is supposed to be tail-recursive and count from 1 to the specified number. I think I'm fairly close. Here's what I have:
(define (countup l)
(if (= 1 l)
(list l)
(list
(countup (- l 1))
l
)
)
)
However, this obviously returns a list with nested lists. I've attempted to use the append function instead of the second list to no avail. Any guidance?
Here's an incorrect solution:
(define (countup n)
(define (help i)
(if (<= i n)
(cons i (help (+ i 1)))
'()))
(help 1))
This solution:
uses a helper function
recurses over the numbers from 1 to n, cons-ing them onto an ever-growing list
Why is this wrong? It's not really tail-recursive, because it creates a big long line of cons calls which can't be evaluated immediately. This would cause a stack overflow for large enough values of n.
Here's a better way to approach this problem:
(define (countup n)
(define (help i nums)
(if (> i 0)
(help (- i 1)
(cons i nums))
nums)))
(help n '()))
Things to note:
this solution is better because the calls to cons can be evaluated immediately, so this function is a candidate for tail-recursion optimization (TCO), in which case stack space won't be a problem.
help recurses over the numbers backwards, thus avoiding the need to use append, which can be quite expensive
You should use an auxiliar function for implementing a tail-recursive solution for this problem (a "loop" function), and use an extra parameter for accumulating the answer. Something like this:
(define (countup n)
(loop n '()))
(define (loop i acc)
(if (zero? i)
acc
(loop (sub1 i) (cons i acc))))
Alternatively, you could use a named let. Either way, the solution is tail-recursive and a parameter is used for accumulating values, notice that the recursion advances backwards, starting at n and counting back to 0, consing each value in turn at the beginning of the list:
(define (countup n)
(let loop ((i n)
(acc '()))
(if (zero? i)
acc
(loop (sub1 i) (cons i acc)))))
Here a working version of your code that returns a list in the proper order (I replaced l by n):
(define (countup n)
(if (= 1 n)
(list n)
(append (countup (- n 1)) (list n))))
Sadly, there is a problem with this piece of code: it is not tail-recursive. The reason is that the recursive call to countup is not in a tail position. It is not in tail position because I'm doing an append of the result of (countup (- l 1)), so the tail call is append (or list when n = 1) and not countup. This means this piece of code is a normal recusrive function but to a tail-recursive function.
Check this link from Wikipedia for a better example on why it is not tail-recusrive.
To make it tail-recursive, you would need to have an accumulator responsible of accumulating the counted values. This way, you would be able to put the recursive function call in a tail position. See the difference in the link I gave you.
Don't hesitate to reply if you need further details.
Assuming this is for a learning exercise and you want this kind of behaviour:
(countup 5) => (list 1 2 3 4 5)
Here's a hint - in a tail-recursive function, the call in tail position should be to itself (unless it is the edge case).
Since countup doesn't take a list of numbers, you will need an accumulator function that takes a number and a list, and returns a list.
Here is a template:
;; countup : number -> (listof number)
(define (countup l)
;; countup-acc : number, (listof number) -> (listof number)
(define (countup-acc c ls)
(if ...
...
(countup-acc ... ...)))
(countup-acc l null))
In the inner call to countup-acc, you will need to alter the argument that is checked for in the edge case to get it closer to that edge case, and you will need to alter the other argument to get it closer to what you want to return in the end.
what is a more efficient way to accomplish this in clojure:
(defn ones
([n] (ones n 1 1))
([n i res]
(if (< i n)
(recur n (inc i) (bit-set res i))
res)))
preferably it should still "do the right thing" when it comes to numerical type.
Why not take 2^(X-1) (by setting only the Xth bit) and then subtract 1?