0

I'm a beginner at lisp. I'm grateful that stackoverflow helped me a lot.

First, I want to express the recursive function using the lisp function. There is no compilation error, but I want to check if the code I wrote is grammatically correct.

Below is the C code I wrote.

void queens(int i)
{
    int j;
 
    if (promising(i))    
    {
        if (i == n)   
        {
            //print all col list
            return
        }
        else    
        {
            for (j = 1; j <= n; j++)    
            {
                col[i + 1] = j;
                queens(i + 1);
            }
        }
    } 
}

Below is the lisp code.

(defvar n 4) 
(defvar col (list 0 0 0 0 0 ))

(defun queens(i)
    (let ((j 1))  
    (if (promising i)  
        (if (= i n) (print col)  
        (loop while (<= j n) do (setf (nth (+ 1 i ) col) j) 
        ( queens (+ 1 i ) ) 
        (incf j)))  
    )
))

1 Answer 1

1

First, you (still) need to fix the indentation, alignment, and general style. This is not merely to annoy you, but because it actually makes things clearer, and easier to debug. For example, if you do not indent properly, it becomes hard to see where each expression ends, and this is even worse when using complex macros such as loop. Your code, properly formatted but without any other modification, should be:

(defun queens (i)
  (let ((j 1))
     (if (promising i)  
         (if (= i n)
             (print col)
             (loop while (<= j n)
                   do (setf (nth (+ 1 i) col) j) 
                      (queens (+ 1 i)) 
                      (incf j))))))
  • The closing parenthesis is placed right after the last form of the expression, without line break, without whitespace.
  • The opening parenthesis is also right before the first element of the form, without whitespace, but should be detached from what comes before, unless it is another parenthesis (so (defun queen (i) ...) is correct, while ( defun queens(i)) breaks two of the rules).
  • When using an if construct, either you write it all on a single line (the condition, the "then" form and the "else" form), or you have to insert line breaks after each of them. Otherwise, it is unclear when the "then" form ends and when the "else" starts.
  • When defining special variables with defvar, name them with '*' around their names, as in (defvar *n* 4) and (defvar *col* (list ...)).

Another style considerations, which helps with problems related to nesting: use when and unless instead of if if you are only interested in one of the two branches. This makes intent clear, and can also simplify the syntax in case of complex branches.

Now, for the code: If you want to use loop, use the basic for constructs. Instead of writing

(loop while (< j n) do ... (incf j))

use

(loop for j from <start> to <end> do ...)

You can also use upto, below ... if you want subtly different termination conditions. When you do this, you do not need to introduce a binding for j using let, it will be introduced by the loop.

If you want to modify a list, use a vector instead. Instead of defining col as (list ...), simply use (vector ...) or the make-array function. Afterwards, use elt or aref to access individual elements instead of nth which only works for lists. A version of the code which assumes that all the previous remarks have been taken into account:

(defun queens (i)
  (when (promising i)  
    (if (= i n)
        (print *col*)
        (loop for j from 1 to *n*
              do (setf (aref *col* (1+ i)) j)
                 (queens (1+ i))))))

Without knowing what promising does and what queens is supposed to do, it is hard to give more insight, but the algorithm is weird nonetheless. For example, in a given call to (queens i), the lexically apparent setf will only ever modify the i+1-th cell of col, setting it to a new j at each iteration. As far as I can tell, this simply results in (aref col (1+ i)) being set to n at the end of the loop. It also seems that you do not use the value recursively returned by queens (which is to be expected: your C function returns nothing !), and that you do not really do any check involving col, so a recursive solution seems weird, there is (seemingly) no relation between (queens i) and the (queens (1+ i)) that it calls n times in a loop !

If the above paragraph is irrelevant because promising also heavily modifies col: stop doing C-in-Lisp and stop modifying things all around the place. Don't rely on state, mutation, global variables & the like, when you can avoid it. It is easy to define recursive solution, to pass lists as arguments, to return several values ... and so it is generally unnecessary to use multiple functions, each of them calling the other ones, recursively modifying the shared global state. That's a mess and can't be debugged.

Sign up to request clarification or add additional context in comments.

1 Comment

This is a problem with the nqueen algorithm. Recursions are not currently established in what you point out. :( The promising function is a device that checks whether the queens on the chessboard can be placed. How do you fix i for a recursive to work correctly?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.