我正在尝试列出我拥有的16个数字,并将其列入4个,4个元素的子列表,以表示魔术广场的游戏板。我创建了一个方法,可以获取列表并返回单个子列表,现在我试图递归使用此方法来构建完整的板。
我的问题是,我的initBoard无论如何返回nil,我知道其他所有方法都按预期工作。任何澄清我的错误将不胜感激!
此处还有一个示例输入列表:
(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))
(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))))))
答案 0 :(得分:1)
一些评论:
someList
,lst
,cnt
不是惯用的,请使用some-list
,list
,count
您不需要is-empty
,只需使用endp
或null
,即返回布尔值(不是-1或1)。你可以根据需要制作别名(但为什么?):
(setf (symbol-function 'is-empty) #'endp)
您可以使用small-list
的循环:
(defun small-list (list)
(values (loop repeat 4 collect (pop list)) list))
次要值是列表的其余部分,因此您不需要cddddr
。
但实际上,在单个函数中初始化整个板可能更好:
(defun init-board (list)
(loop repeat 4 collect
(loop repeat 4 collect (pop list))))
第一个LOOP
收集4个元素的列表,这些元素由内部LOOP
收集。收集的元素将从输入列表中弹出。
现在,如果我想要非常小心,我会添加一些检查并报告错误输入的错误:
(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)))))
另外,我会使用多维数组板。
(make-array '(4 4) :initial-contents (init-board list))
答案 1 :(得分:0)
我刚测试了你的三个功能,它给了我正确的输出,所以也许你的问题不在你想象的地方。
(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))
答案 2 :(得分:0)
我会使用以下递归函数:
(defun smalllist (l n)
(when l
(cons (subseq l 0 (min n (length l)))
(smalllist (nthcdr n l) n))))