移植一个接受整数的函数并吐出该数字的整数分区,即
((4) (3 1) (2 2) (2 1 1) (1 1 1 1))
应该产生
row
也就是说,分区列表首先由最大部分排序,然后是第二大部分,等等。并且总和是我们正在分区的整数。
在John Stembridge的枫包SF中,这是由以下子程序产生的,该子程序在由col
和SF/Par/sub(n,n,n)
定义的框内生成带有图表的分区,以便`SF/Par/sub`:=proc(n,row,col) local i;
if n=0 then [[]]
elif col=0 then []
else
[seq(op(map((x,y)->[y,op(x)],`SF/Par/sub`(n+i,-i,col-1),-i)),
i=-min(row,n)..-iquo(n+col-1,col))]
fi
end:
就是我想:
(floor (/ x y))
其中iquo是(2 (2 ()) (1 (1 ())))
问题是如何从
获得((2 2) (2 1 1))
结果
(defun partitions (n row col)
""
(block nil
(if (= n 0) (return '(())))
(if (= col 0) (return '()))
(loop for i from (- (min row n)) to (floor (/ (- (+ n col) 1) col))
collect (cons (- i) (partitions (+ n i) (- i) (- col 1))))))
修改
以下是我的尝试
(partitions 3 3 3)
它运行并终止,但我能说的就是它。
((3 NIL) (2 (1 NIL) (0 (0) (-1)) (-1 (-1) (-2))) (1 (1 (1 NIL) (0) (-1)) (0 (0) (-1) (-2)) (-1 (-1) (-2) (-3))) (0 (0 (0) (-1) (-2) (-3)) (-1 (-1) (-2) (-3) (-4)) (-2 (-2) (-3) (-4) (-5))) (-1 (-1 (-1) (-2) (-3) (-4) (-5)) (-2 (-2) (-3) (-4) (-5) (-6))))
收益
((3) (2 1) (1 1 1))
我希望它返回{{1}}
答案 0 :(得分:4)
由于你已经得到了一个有效的答案,这里有一些关于你的编码风格的评论:
(defun partitions (n row col)
""
(block nil
(if (= n 0) (return '(())))
(if (= col 0) (return '()))
(loop for i from (- (min row n)) to (floor (/ (- (+ n col) 1) col))
collect (cons (- i) (partitions (+ n i) (- i) (- col 1))))))
""
可以省略,因为它没用,也不包含文档。
DEFUN
已经设置了一个块,但它被命名为partitions
。所以
(defun partitions (...)
(block nil ... (return ...) ...)
将是
(defun partitions (...)
...
(return-from partitions ...)
...)
(if (foo) (bar))
通常写为(when (foo) (bar))
。
因为(if (foo) (progn (bar) (baz)))
是(when (foo) (bar) (baz))
。
在Lisp中使用(block ... (if ... (return ...)) (if ... (return...)...)
是不常见的。 IF
通常会返回一个值,因此不需要使用RETURN
或RETURN-FROM
的其他控制流。而不是
(block nil
(if (= n 0) (return '(())))
(if (= col 0) (return '()))
(loop for i from (- (min row n)) to (floor (/ (- (+ n col) 1) col))
collect (cons (- i) (partitions (+ n i) (- i) (- col 1))))))
一个人会写:
(if (= n 0)
'(())
(if (= col 0)
'()
(loop for i from (- (min row n)) to (floor (/ (- (+ n col) 1) col))
collect (cons (- i) (partitions (+ n i) (- i) (- col 1))))))
由于这些嵌套的If
在Lisp代码中非常常见,因此cond
结构使编写起来更容易一些。代码也不会通过每个子句向右移动:
(cond ((= n 0)
'(()))
((= col 0)
'())
(t
(loop for i from (- (min row n)) to (floor (/ (- (+ n col) 1) col))
collect (cons (- i) (partitions (+ n i) (- i) (- col 1))))))
答案 1 :(得分:3)
您应该使用BLOCK
代替RETURN
/ (defun partitions (n row col)
(cond ((= n 0) ...)
((= col 0) ...)
(t (loop ...))))
ZEROP
然后,您可以使用(= X 0)
代替1-
,(- X 1)
代替I
。我也没有看到任何理由让DOWNTO
为否定(你可以使用循环关键字FLOOR
倒计时)。 (FLOOR X Y)
将除数作为可选参数,因此您可以编写(FLOOR (/ X Y))
而不是(defun partitions (n row col)
""
(cond ((zerop n) '(()))
((zerop col) '())
(t (loop for i from (min row n) downto (floor (1- (+ n col)) col)
collect (cons i (partitions (- n i) i (1- col)))))))
(partitions 3 3 3)
;=> ((3 NIL) (2 (1 NIL)) (1 (1 (1 NIL))))
。
通过以下更改:
NIL
这些COND
是由NIL
的第一个子句中的嵌套列表引起的。请记住,空列表与'()
相同。如果您将其更改为((3) (2 (1)) (1 (1 (1))))
,则结果为N
。
要删除那些额外的内部列表,您可以使用构建结果的内部函数,并在(defun partitions (n row col)
""
(let ((result (list)))
(labels ((%partitions (n row col acc)
(cond ((zerop n) (push (reverse acc) result))
((zerop col))
(t (loop for i from (min row n) downto (floor (1- (+ n col)) col)
do (%partitions (- n i) i (1- col) (cons i acc)))))))
(%partitions n row col '())
(nreverse result))))
(partitions 3 3 3)
;=> ((3) (2 1) (1 1 1))
(partitions 4 4 4)
;=> ((4) (3 1) (2 2) (2 1 1) (1 1 1 1))
为零时将其推送到列表中。
(defun partitions (n)
(let ((result (list)))
(labels ((%partitions (n largest-number acc)
(cond ((< n 1) (push (reverse acc) result))
(t (loop for l from largest-number downto 1
do (loop for i from (floor n l) downto 1
do (%partitions
(- n (* l i))
(1- l)
(append (make-list i :initial-element l)
acc))))))))
(%partitions n n '())
(nreverse result))))
(partitions 3)
;=> ((3) (2 1) (1 1 1))
(partitions 4)
;=> ((4) (3 1) (2 2) (2 1 1) (1 1 1 1))
(partitions 5)
;=> ((5) (4 1) (3 2) (3 1 1) (2 2 1) (2 1 1 1) (1 1 1 1 1))
稍长一点,但至少是IMO,更简单的方法来解决问题:
#include <stdio.h>
int main(){
typedef struct Ds {
int i1;
int i2;
char c1;
int i3;
} Ds;
Ds ds;
sscanf("12,6,@,3","%d,%d,%c,%d",&ds.i1, &ds.i2, &ds.c1, &ds.i3);
printf("%d,%d,%c,%d\n",ds.i1,ds.i2,ds.c1,ds.i3);
return 0;
}