 - ;探讨一下算法,目的:把一个列表,分割成和是【接近且小于等于15】的多个表。结果追求【总数n少,组合i少】。
- ;目前最优答案是:"共计生成了16个表,过滤重复后,共有9种组合"
- ;(((9 4 2) 2) ((10 5) 2) ((12 3) 2) ((7 4 4) 1) ((6 4 4 1) 1) ((13 1) 1) ((8 6) 4) ((14) 2) ((15) 1))
- ;抛砖引玉。
- (defun c:ff(/ ass asslst b i k lst n newlst sum);最直接的办法:"共计生成了16个表,过滤重复后,共有10种组合"
- (setq lst '(14 10 9 4 6 8 4 14 10 9 4 6 8 4 5 6 3 2 1 12 4 6 8 4 5 6 3 2 1 12 13 15 8 7))
- (setq newlst(vl-sort(mapcar '(lambda(x)(+ x 0.0))lst)'>))
- (setq sum 0 ass nil asslst nil);---临时总和,元素结果表,元素组合表
- (while newlst
- (if(setq b(vl-some '(lambda(x / a)(if(<=(setq a(+ x sum))15)(list x a)))newlst));---查找表里元素有没有符合要求的
- (progn
- (setq k(car b)sum(cadr b)ass(cons k ass));---有的话就加入到新表
- (setq newlst(vl-remove nil(mapcar '(lambda(x)(if(= x k)(setq x nil k nil)x))newlst)));---删掉第一个指定元素
- )
- (setq asslst(cons(reverse ass)asslst)sum 0 ass nil);---把组合写入到asslst中
- )
- )
- (setq asslst(cons(reverse ass)asslst));---处理最后一个元素
- (setq asslst(reverse asslst));((4 4 4 3) (4 4 4 3) (6 6 2 1) (6 6 2 1) (6 8) (8 5) (8 5) (8 7) (14) (14) (12) (12) (10) (10) (9) (9) (15) (13))
- (setq n(length asslst))
- (setq i(length(dup-Counts asslst)));(((4 4 4 3) 2) ((6 6 2 1) 2) ((6 8) 1) ((8 5) 2) ((8 7) 1) ((14) 2) ((12) 2) ((10) 2) ((9) 2) ((15) 1) ((13) 1))
- (print (strcat "共计生成了" (rtos n) "个表,过滤重复后,共有"(rtos i)"种组合"))
- (princ)
- )
- (defun c:gg(/ ass asslst b i k lst n newlst sum);第二种办法:"共计生成了18个表,过滤重复后,共有11种组合",很显然,这种更不合理了
- (setq lst '(14 10 9 4 6 8 4 14 10 9 4 6 8 4 5 6 3 2 1 12 4 6 8 4 5 6 3 2 1 12 13 15 8 7))
- (setq lst(dup-Counts lst));((14 2) (10 2) (9 2) (4 6) (6 5) (8 4) (5 2) (3 2) (2 2) (1 2) (12 2) (13 1) (15 1) (7 1))
- (setq lst(vl-sort lst '(lambda(x1 x2)
- (if(=(cadr x1)(cadr x2));首选数量排序,次选大小排序
- (>(car x1)(car x2))
- (>(cadr x1)(cadr x2))
- )
- )));((4 6) (6 5) (8 4) (14 2) (12 2) (10 2) (9 2) (5 2) (3 2) (2 2) (1 2) (15 1) (13 1) (7 1))
- (setq newlst nil)
- (foreach x lst
- (repeat(cadr x)
- (setq newlst(cons(car x)newlst));---拍平
- )
- )
- (setq newlst(reverse newlst));(4 4 4 4 4 4 6 6 6 6 6 8 8 8 8 14 14 12 12 10 10 9 9 5 5 3 3 2 2 1 1 15 13 7)
- (setq sum 0 ass nil asslst nil);---临时总和,元素结果表,元素组合表
- (while newlst
- (if(setq b(vl-some '(lambda(x / a)(if(<=(setq a(+ x sum))15)(list x a)))newlst));---查找表里元素有没有符合要求的
- (progn
- (setq k(car b)sum(cadr b)ass(cons k ass));---有的话就加入到新表
- (setq newlst(vl-remove nil(mapcar '(lambda(x)(if(= x k)(setq x nil k nil)x))newlst)));---删掉第一个指定元素
- )
- (setq asslst(cons(reverse ass)asslst)sum 0 ass nil);---把组合写入到asslst中
- )
- )
- (setq asslst(cons(reverse ass)asslst));---处理最后一个元素
- (setq asslst(reverse asslst));((4 4 4 3) (4 4 4 3) (6 6 2 1) (6 6 2 1) (6 8) (8 5) (8 5) (8 7) (14) (14) (12) (12) (10) (10) (9) (9) (15) (13))
- (setq n(length asslst))
- (setq i(length(dup-Counts asslst)));(((4 4 4 3) 2) ((6 6 2 1) 2) ((6 8) 1) ((8 5) 2) ((8 7) 1) ((14) 2) ((12) 2) ((10) 2) ((9) 2) ((15) 1) ((13) 1))
- (print (strcat "共计生成了" (rtos n) "个表,过滤重复后,共有"(rtos i)"种组合"))
- (princ)
- )
- ;---重复元素及其出现次数
- (defun dup-Counts(lst / n newlst x)
- (setq newlst nil)
- (while(setq x(car lst))
- (setq n(length lst))
- (setq lst(vl-remove x lst))
- (setq newlst(cons(list x(- n(length lst)))newlst))
- )
- (reverse newlst)
- )
欢迎大佬们参与。
|