一道小学推理题

 偶然看到了一道小学推理题,打算用代码的形式解出来。

from collections import defaultdict
from copy import deepcopy
import itertools

class MathGame:

    def __init__(self, calcinfo, n1, n2, answer, cards="abcdefghijklmn"):
        self.n1 = n1
        self.n2 = n2
        self.answer = answer
        self.cards = cards
        self.calcinfo = MathGame.initcalcinfo(calcinfo, n1, n2, answer)

    @staticmethod
    def initcalcinfo(calcinfo, n1, n2, answer):
        '''
            初始化系数
            输入:
                n1 = "abc"
                n2 = "cba"
                answer = "bbcb"
            由:
                abc: a * 100 + b * 10 + c
                cba: c * 100 + b * 10 + a
                bbcb: b * 1000 + b * 100 + c * 10 + b
            得:
                101*c -1081*b + 91*a = 0
            返回:
                {'c': 101, 'b': -1081, 'a': 91}
        '''
        for i in range(1, len(n1)+1):
            calcinfo[n1[-i]] += (10**(i-1))
        for i in range(1, len(n2)+1):
            calcinfo[n2[-i]] += (10**(i-1))
        for i in range(1, len(answer)+1):
            calcinfo[answer[-i]] -= (10**(i-1))
        return calcinfo

    def calc(self):
        return MathGame._calc(self.calcinfo)
    
    @staticmethod
    def _calc(calcinfo, preinfo={}):
        '''
            解方程,递归遍历所有可能性组合
            输入:
                {'c': 101, 'b': -1081, 'a': 91}
            由:
                101*c -1081*b + 91*a = 0
            得:
                {'a': a, 'b': b, 'c': c}
            返回:
                {'a': 3, 'b': 1, 'c': 8}
        '''
        _calcinfo = deepcopy(calcinfo)
        calctuple = _calcinfo.popitem()
        result = {}
        for i in range(1, 10):
            preinfo[calctuple[0]] = (calctuple[1], i)
            if _calcinfo:
                result.update(MathGame._calc(_calcinfo, preinfo))
            if sum(map(lambda t:t[0]*t[1], preinfo.values())) == 0:
                result.update(list(map(lambda t:(t[0],t[1][1]),preinfo.items())))
        return result

    @staticmethod
    def getassociationinfo(n1, n2, answer):
        '''
            游戏的解
            输入:
                n1 = "abc"
                n2 = "cba"
                answer = "bbcb"
            返回:
                {'a': 3, 'b': 1, 'c': 8}
        '''
        calcinfo = defaultdict(lambda : 0)
        calcinfo = MathGame.initcalcinfo(calcinfo, n1, n2, answer)
        return MathGame._calc(calcinfo)

    @staticmethod
    def permutations(n_class=3, n_length=3, cards="abcdefghijklmn"):
        '''
            获取所有排列
            输入:
                n_class:卡片种类
                n_length:排列长度
                cards:自定义卡片标签
            返回:
                生成器
        '''
        b = cards[:n_class]
        restcombinations = itertools.product(b,repeat=n_length-n_class)
        for i in restcombinations:
            permutation = b + "".join(i)
            for j in itertools.permutations(permutation, n_length):
                yield "".join(j)

    @staticmethod
    def product(cards, n_length):
        '''
            笛卡尔积
            输入:
                s:自定义卡片
                n_length:长度
            返回:
                生成器
        '''
        for n in itertools.product(cards, repeat=n_length):
            yield "".join(n)

    @staticmethod
    def findallassociation(n1_class=3, n1_length=3, n2_length=3, n2_class=3, answer_length=4):
        '''
            找到所有组合
            输入:
                n1_class:第一行数字的排列种类
                n1_length:第一行数字的排列长度
                n2_class:第二行数字的排列种类
                n2_length:第二行数字的排列长度
                answer_length:答案的排列长度
            返回:
                [
                    {'n1': 'abc', 'n2': 'acb', 'answer': 'bcaa', 'associationinfo': {'a': 9, 'b': 1, 'c': 8}},
                    {'n1': 'abc', 'n2': 'acb', 'answer': 'cbaa', 'associationinfo': {'a': 9, 'b': 8, 'c': 1}},
                    ...
                ]
        '''
        result = []
        for n1 in MathGame.permutations(n1_class, n1_length):
            for n2 in MathGame.permutations(n2_class, n2_length):
                s = "".join((set(list(n1+n2))))
                for answer in MathGame.product(s, answer_length):
                    question = {
                        "n1":n1,
                        "n2":n2,
                        "answer":answer
                    }
                    if not issamestruct(question, *result):
                        associationinfo = MathGame.getassociationinfo(n1, n2, answer)
                        if associationinfo:
                            question["associationinfo"] = associationinfo
                            result.append(question)
        return result

def issamestruct(question, *questionlist):
    '''
        判断是否同构
        输入:
            {'n1': 'abc', 'n2': 'acb', 'answer': 'cba'}
            {'n1': 'bca', 'n2': 'bac', 'answer': 'acb'}
        返回:
            True
    '''
    question1 = question
    n1 = question1["n1"]
    n2 = question1["n2"]
    answer = question1["answer"]
    for question2 in questionlist:
        _n1 = question2["n1"]
        _n2 = question2["n2"]
        _answer = question2["answer"]
        if _issamestruct(n1, n2, answer, _n1, _n2, _answer) or  _issamestruct(n1, n2, answer, _n2, _n1, _answer):
            return True
    return False
        
 
def _issamestruct(n1, n2, answer, _n1, _n2, _answer):
    d = {}
    tempanswer = ""
    for i, v in enumerate(n1):
        d[v] = _n1[i]
    for i, v in enumerate(n2):
        d[v] = _n2[i]
    for i, v in enumerate(answer):
        tempanswer += d.get(v, "NAN")
    return tempanswer == _answer


if __name__ == '__main__':
    n1 = "abc"  
    n2 = "cba"  
    answer  = "bbab"
    MathGame.getassociationinfo(n1, n2, answer)
    # print(MathGame.findallassociation(3, 3, 3, 3, 4))

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值