美文网首页
数独终结者

数独终结者

作者: faithefeng | 来源:发表于2017-03-31 20:43 被阅读0次

    这篇文章简单介绍下“数独求解器”怎么用程序实现??
    文章背景图片是一个比较难的数独问题,感兴趣的可以试着手动求解啊。
    这里暂时不多解释,直接贴代码,等有时间了详细解释下具体怎么实现的。代码使用python写的,总共大概一页纸。

    import collections
    def cross(A,B):
        "Cross product of elements in A and elements in B"
        return [a+b for a in A for b in B]
    
    def parse_Grid(values):
        '''Convert grid to a dicf of values {square:digits}, 
        and a dict of possible values {square:digits}, 
        or return False if a contradiction is detected. That is, no possible value
        '''
        # Input is a string of with length of 81
        digits = '123456789'
        if not values:
            return False,False
        if isinstance(values, str):
            chars = [c for c in values if c in digits or c in '0.']
            values = dict(zip(squares, chars))
        elif isinstance(values, dict):
            values  = values
        values_Possible = dict((s,'') for s in squares)
        for s,d in values.items():
            if d in '0.':
                #Also, this line will implement the contradiction check!!!
                values_Possible[s] = ''.join(set(digits)-set(values[s2] for s2 in peers[s] if values[s2] in digits))
                if len(values_Possible[s]) == 0:
                    return False,False
    
        return values, values_Possible
    
    def display(values):
        "Display these values as a 2-D grid"
        digits = '123456789'
        if isinstance(values, str):
            chars = [c for c in values if c in digits or c in '0.']
            values = dict(zip(squares, chars))
        for s,d in values.items():
            if d in '0.':
                values[s] = ''
        width = 1+max(len(values[s]) for s in squares)
        line = '+'.join(['-'*(width*3)]*3)
        for r in rows:
            print(''.join(values[r+c].center(width) + ('|' if c in '36' else '') for c in cols))
            if r in 'CF':print(line)
        #return values
    
    def solver(values):
        # This is the solver!!!
        values, values_Possible = parse_Grid(values)
        if not values_Possible:
            return False
        display(values)
        print('-'*30)
        if not all(len(d) == 0 for s,d in values_Possible.items()):
            n,s = min((len(d),s) for s,d in values_Possible.items() if len(d)!=0)
            print(n,s,values_Possible[s])
            return some(solver(assign(values.copy(),s, d)) for d in values_Possible[s]) # This is a generator!!!
        return values
    def some (seq):
        if isinstance(seq, collections.Iterable):
            for e in seq:
                print(e)
                if e: 
                    return e
        else:
            if seq:
                return seq
        return False
    def assign(values, s, d):
        values[s] = d
        return values
    
    # some constants
    digits = '123456789'
    cols = '123456789'
    rows = 'ABCDEFGHI'
    squares = cross(rows,cols)
    unitlist = ([cross(a,cols) for a in rows] +
               [cross(rows,b) for b in cols] + 
               [cross(rb,cb) for rb in ('ABC','DEF','GHI') for cb in ('123','456','789')])
    units = dict((s,[u for u in unitlist if s in u]) for s in squares)
    
    peers = dict((s,set(sum(units[s],[]))-set([s])) for s in squares)
    

    然后输入要求解的问题,

    puzzle = '''005300000
                800000020
                070010500
                400005300
                010070006
                003200080
                060500009
                004000030
                000009700'''
    

    求解

    a = solver(values)
    

    然后输出

    display(a)
    

    结果如下,搞定

    相关文章

      网友评论

          本文标题:数独终结者

          本文链接:https://www.haomeiwen.com/subject/omavottx.html