#!python2
from itertools import *
from operator import *
calc24 = lambda a,b,c,d:list(set(sum((
(o(p(i,q(j,k)),l)==24 and ["(%s%s(%s%s%s))%s%s"%s] or [])+
(o(i,p(q(j,k),l))==24 and ["%s%s((%s%s%s)%s%s)"%s] or [])+
(o(i,p(j,q(k,l)))==24 and ["%s%s(%s%s(%s%s%s))"%s] or [])+
(o(p(i,j),q(k,l))==24 and ["(%s%s%s)%s(%s%s%s)"%s] or [])+
(o(p(q(i,j),k),l)==24 and ["(((%s%s%s)%s%s)%s%s)"%s] or [])
for nums,opp in [((a,b,c,d),(add,sub,mul,lambda x,y:truediv(x,y) if y else float('nan')))]
for j,i,k,l in permutations(nums) for o,p,q in product(opp,repeat=3)
for r in [dict(zip(opp,("+","-","*","/")))] for s in [(i,r[o],j,r[p],k,r[q],l)]),[])))
>>> calc24(6,6,6,6)
['6+((6+6)+6)', '(((6+6)+6)+6)', '(6+(6+6))+6', '(6+6)+(6+6)', '(((6-6)-6)*6)', '(6-6)*(6+6)', '6+(6+(6+6))']
>>> calc24(2,3,8,9)
['(8/(9*3))-2', '8/(2/(9-3))', '8*(9-(2*3))', '8*((9/3)-2)', '(((9*3)/2)-8)', '(8*2)/(9-3)', '(((9/3)*8)-2)', '(9/3)-(2/8)', '(9*3)-(8/2)', '8*(9-(3*2))', '(9*(3-2))*8', '(9*(2-3))*8']
下面这个考虑了交换律的重复。故意写个很累赘的样子,
而且为了吻合IEEE还把mapcan和format等等都替换了一下。
(define (calc24 a b c d)
(define (flat-map p x)
(apply append (map p x)))
(define (filter p x)
(cond ((null? x) '())
((p (car x)) (cons (car x) (filter p (cdr x))))
(else (filter p (cdr x)))))
(define (drop-one x lst)
(cond ((null? lst) '())
((equal? x (car lst)) (cdr lst))
(else (cons (car lst) (drop-one x (cdr lst))))))
(define (perm lst)
(if (null? lst)
'(())
(flat-map
(lambda (x)
(map (lambda (y) (cons x y))
(perm (drop-one x lst))))
lst)))
(define (pow lst n)
(if (zero? n) '(())
(flat-map
(lambda (x)
(map (lambda (y) (cons x y))
(pow lst (- n 1))))
lst)))
(define (buld-exp num ops)
(apply
(lambda (i j k l)
(apply
(lambda (o p q)
(list
`(,o (,p ,i ,j) (,q ,k ,l))
`(,o (,p ,i (,q ,j ,k)) ,l)))
ops))
num))
(define (eval-exp exp)
(if (list? exp)
(let ((arg (map eval-exp (cdr exp)))
(/ (lambda (x y)
(if (zero? y) +nan.0 (/ x y)))))
(case (car exp)
((+) (apply + arg))
((-) (apply - arg))
((*) (apply * arg))
((/) (apply / arg))
((--) (apply - (reverse arg)))
((//) (apply / (reverse arg)))
(else (error "op?"))))
exp))
(define (show-exp exp)
(define (bin-op-str op arg)
(apply (lambda (x y)
(string-append "(" x op y ")"))
(map (lambda (x)
(if (number? x) (number->string x) x)) arg)))
(if (list? exp)
(let ((arg (map show-exp (cdr exp)))
(/ (lambda (x y) (if (zero? y) +nan.0 (/ x y)))))
(case (car exp)
((+) (bin-op-str "+" arg))
((-) (bin-op-str "-" arg))
((*) (bin-op-str "*" arg))
((/) (bin-op-str "/" arg))
((--) (bin-op-str "-" (reverse arg)))
((//) (bin-op-str "/" (reverse arg)))
(else (error "op?"))))
exp))
(define (unique lst)
(if (null? lst) '()
(cons (car lst)
(unique
(filter (lambda (x)
(not (equal? x (car lst)))) lst)))))
(unique
(flat-map
(lambda (x)
(flat-map
(lambda (y)
(flat-map
(lambda (z)
(if (= 24 (eval-exp z))
(list (show-exp z))
'()))
(buld-exp x y)))
(pow '(+ - * / -- //) 3)))
(perm (list a b c d)))))
(calc24 2 3 8 9)
("(((9-3)/2)*8)" "(8/(2/(9-3)))" "((8/2)*(9-3))" "((9-3)/(2/8))" "((9-3)*(8/2))" "((8*(9-3))/2)" "((9-(2*3))*8)" "((9-(3*2))*8)")
(calc24 6 6 6 6)
("((6+6)+(6+6))" "((6+(6+6))+6)" "((6*6)-(6+6))" "(((6*6)-6)-6)")
更多的不同语言写的可以看这个:
http://rosettacode.org/wiki/24_game/Solve
乱如备份下平时在npp里面用来插入行首空格的东西。
能用,不过貌似可能会干出多余的事情来,比如不仅仅是行首的情况。
另外使用前务必先用一下npp自带的转义& < > "的菜单命令。
editor.pyreplace(r"^ ", r" ")
def s():editor.pysearch(r" " ,lambda x,y:rp())
def rp():editor.pyreplace(r" ", r" ") and False or s()
s()
如果要变成算24的游戏的话,还要一个随机数生成,和表达式计算的东西。
没有评论:
发表评论