だいぶ慣れてきた。「4 ? 4 ? 4 ? 4 = 2」

よくあるクイズ。計算機の力を使わずに解きたくない。

[{'expr': ((4, '*', 4), '/', (4, '+', 4)), 'ans': 2},
 {'expr': ((4, '/', 4), '+', (4, '/', 4)), 'ans': 2},
 {'expr': (4, '-', ((4, '+', 4), '/', 4)), 'ans': 2},
 {'expr': (4, '/', ((4, '+', 4), '/', 4)), 'ans': 2},
 {'expr': ((4, '*', 4), '/', (4, '+', 4)), 'ans': 2},
 {'expr': ((4, '/', 4), '+', (4, '/', 4)), 'ans': 2}]

code

名前が思いつかない。
計算結果の値と式の内容を格納したかったらクラスを作る必要があるなー。

class A(object):
    def __init__(self, kons, ops=('+', '-', '*', '/'),last_item=1, delta=1):
        self.last_item = last_item
        if kons is None:
            self.kons = lambda x, op : x
        else:
            self.kons = kons
        self.ops = ops

    def merge(self, xs, delta=1):
        r = []
        def rec(N, xs):
            if N == self.last_item:
                r.append(xs[0])
            else:
                for i in range(N-delta):
                    for op in self.ops:
                        rec(N-1, self.merge0(xs, N, i, op, delta))
        rec(len(xs), xs)
        return r

    def merge0(self, xs, n, idx, op, delta=1):
        r, tmp = [], []
        flag = False
        for i in range(n):
            if i == idx:
                flag = True

            if flag:
                tmp.append(xs[i])
                if delta == 0:
                    r.append(self.kons(tmp, op))
                    flag = False
                delta -= 1
            else:
                r.append(xs[i])
        return r

class Expr(object):
    def __init__(self, init):
        self.ans = init
        self.expr = init
    
    def copy(self):
        e = Expr(self.ans)
        e.expr = self.expr
        return e

    def kons(self, op, y):
        def ans(e):
            return e.ans if isinstance(e, Expr) else e
        def expr(e):
            return e.expr if isinstance(e, Expr) else e

        e = self.copy()
        e.expr = (self.expr, op, expr(y))
        try:
            e.ans = eval("%s %s %s" % (ans(self), op, ans(y)))
        except ZeroDivisionError, err:
            e.ans = 0
            e.expr = err
        return e

    def __repr__(self):
        return str({'ans' : self.ans, "expr" : self.expr})

def kons(xs, op):
    x, y = xs[0], xs[1]
    if isinstance(x, Expr):
        return x.kons(op, y)
    else:
        return Expr(x).kons(op, y)

#####
xs = [4, 4, 4, 4]
from pprint import  pprint
a = A(kons=kons)
pprint([expr for expr in a.merge(xs) if expr.ans == 2])