1

I am trying to take a list of 16 numbers I have and make it into a list of 4, 4 element sublists to represent the game board of a magic square. I made a method that can take a list and return a single sublist, and now I am trying to recursively use this method to build the full board.

My problem however, is my initBoard returns nil no matter what and I know every other method is working as desired. Any clarification of my error would be greatly appreciated!

Also here is an example input list:

(4 5 15 10 14 11 1 8 9 16 6 3 7 2 12 13)

And what I want as the output would be:

((4 5 15 10) (14 11 1 8) (9 16 6 3) (7 2 12 13))

(defun smallList (lst cnt)
   (cond ((>= cnt 4) nil)
   (t (cons (car lst) (smallList (cdr lst) (+ 1 cnt))))))

(defun isEmpty (lst)
   (if lst 1 -1))

(defun initBoard (lst)
   (cond ((= (isEmpty lst) -1) nil) 
   (t (cons (smallList lst 0) (initBoard  (cddddr lst))))))

3 Answers 3

1

Some remarks:

  • someList, lst, cnt is not idiomatic, use some-list, list, count
  • You don't need is-empty, just use endp or null, which returns a boolean (not -1 or 1). You could make an alias if you want (but why?):

    (setf (symbol-function 'is-empty) #'endp)
    

You could use a loop for small-list:

(defun small-list (list)
  (values (loop repeat 4 collect (pop list)) list))

The secondary value is the rest of the list, so that you don't need to cddddr.

But in fact, it might be better to initialize the whole board inside a single function:

(defun init-board (list)
  (loop repeat 4 collect
       (loop repeat 4 collect (pop list))))

The first LOOP collect lists of 4 elements, which are collected by the inner LOOP. The collected elements are popped from the input list. Now, if I wanted to be extremely careful, I would add some checks and report errors on bad inputs:

(defun init-board (list)
  (flet ((failure ()
           (error "Input list should contain exactly 16 integers: ~S"
                  list)))
    (loop
       with current = list
       repeat 4 collect
         (loop
            repeat 4
            collect (if current
                        (let ((element (pop current)))
                          (check-type element integer)
                          element)
                        (failure)))
       into board
       finally (if list (failure) (return board)))))

Also, I would use a multi-dimensional array for boards.

(make-array '(4 4) :initial-contents (init-board list)) 
Sign up to request clarification or add additional context in comments.

2 Comments

I avoid using list since there is the function that is defined as list. Thanks for pointing out the way to avoid isEmpty. I would much rather use a 2d array and loops, but the assignment is asking for lists and recursion unfortunately.
@DShuler I understand, but just in case you come from a Scheme background, (lambda (list) (list list)) works fine in CL and is not ambiguous at all.
0

I just tested your three functions and it gave me the correct output, so perhaps your issue isn't where you think it is.

(initBoard '(4 5 15 10 14 11 1 8 9 16 6 3 7 2 12 13))

=> ((4 5 15 10) (14 11 1 8) (9 16 6 3) (7 2 12 13))

5 Comments

Well the once difference in what I have versus your example, I'm passing a list I defined with setq, is that perhaps causing some sort of issue? EDIT: that line you posted still returned nil, are you using clozure?
No, I'm using SBCL, but they're both standards compliant and this is standard code. I started up a blank REPL, pasted in the functions you gave me, and then ran that line.
I figured but I just wanted to check. That's super strange, seeing as the code posted is copy pasted directly from the code I wrote. Copy pasted the code back and it started working, thanks for proving it worked!
What other code have you loaded and what development environment are you using?
I have a few other functions for file IO and user input. I'm writting in lispbox, so emacs running clozure
0

I would use the following recursive function:

(defun smalllist (l n) 
   (when l 
      (cons (subseq l 0 (min n (length l))) 
            (smalllist (nthcdr n l) n))))

Comments

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.