示例#1
0
文件: sudoku.py 项目: dbueno/puzzler
def solveBoard(board):
    global numUnique, printResult, checkUnique, checkUnique

    def assumeBoard(printBoard):
        for v in checkAssumps:
            cnf.assume(-v)
        row = 0
        col = 0
        for b in board:
            if printBoard:
                sys.stdout.write(b)
            if b == ".":
                pass
            else:
                i = -1
                if N < 10:
                    i = int(b) - 1
                else:
                    i = ord(b) - ord("A")
                # print '(%d,%d) = i = %d' % (row,col,i)
                cnf.assume(p[i][row][col])
            col += 1
            if col == N:
                col = 0
                row += 1
                if row == N:
                    break
        if printBoard:
            sys.stdout.write("\n")

    assumeBoard(printResult)
    result = cnf.solve()
    assert result == cnf.RESULT_SAT
    if printResult:
        showBoard(board)

    if checkUnique:
        v = cnf.newVar("uniq")
        c = [-v]
        for j in range(0, N):
            for k in range(0, N):
                for i in range(0, N):
                    if cnf.assignment(p[i][j][k]):
                        c.append(-p[i][j][k])
        cnf.addClause("uniq", c)
        assumeBoard(False)
        cnf.assume(v)
        checkAssumps.append(v)
        result = cnf.solve()
        if result == cnf.RESULT_SAT:
            print "non-unique board"
            showBoard(board)
            return False
        elif result == cnf.RESULT_UNSAT:
            numUnique += 1
    return True
示例#2
0
文件: grid.py 项目: dbueno/puzzler
  def __init__(self, name, rows, cols):
    self.tbl = {}
    self.rows = rows
    self.cols = cols
    for r in rows:
      self.tbl[r] = {}
      clause = []
      for c in cols:
        self.tbl[r][c] = cnf.newVar(name)
        clause.append( self.tbl[r][c] )
      cnf.addClause('>=1', clause)
    for r in rows:
      for c1 in cols:
        for c2 in cols:
          if c1 != c2:
            cnf.addClause('<=1', [-self.tbl[r][c1], -self.tbl[r][c2]])

    def entry(row, col):
      assert row in self.rows
      assert col in self.cols
      return self.tbl[row][col]
示例#3
0
文件: sudoku.py 项目: dbueno/puzzler
def setup():
    """
  Sets up universal sudoku constraints. Nothing set up here is specific to the
  actual board being solved.
  """
    cnf.init()
    cnf.pico.picosat_set_seed(0)
    # cnf.pico.picosat_set_global_default_phase(0) # 1361274
    cnf.pico.picosat_set_global_default_phase(1)  # 1353908

    # create vars
    for i in range(0, N):
        p[i] = {}
        for j in range(0, N):
            p[i][j] = {}
            for k in range(0, N):
                p[i][j][k] = cnf.newVar("[%d][%d] = %d" % (j, k, i))

    # must choose at least one possibility per square
    for j in range(0, N):
        for k in range(0, N):
            clause = []
            for i in range(0, N):
                clause.append(p[i][j][k])
            cnf.addClause(">=1", clause)

    # must choose at most one possibility per square
    for j in range(0, N):
        for k in range(0, N):
            for i in range(0, N):
                for l in range(0, N):
                    if i != l:
                        cnf.addClause("<=1", [-p[i][j][k], -p[l][j][k]])

    # columns have 1-9 at most once
    for i in range(0, N):
        for r in range(0, N):
            for c in range(0, N):
                for r2 in range(0, N):
                    if r2 != r:
                        cnf.addClause("col_val", [-p[i][r][c], -p[i][r2][c]])

    # rows have 1-9 at most once
    for i in range(0, N):
        for r in range(0, N):
            for c in range(0, N):
                for c2 in range(0, N):
                    if c2 != c:
                        cnf.addClause("row_val", [-p[i][r][c], -p[i][r][c2]])

    # 3x3 grids have 1-9 at most once
    for s in range(0, N / Sq):
        for t in range(0, N / Sq):
            for r in range(s * (N / Sq), (s + 1) * (N / Sq)):
                for c in range(t * (N / Sq), (t + 1) * (N / Sq)):
                    for r2 in range(s * (N / Sq), (s + 1) * (N / Sq)):
                        for c2 in range(t * (N / Sq), (t + 1) * (N / Sq)):
                            # comment this out to see if your python doesn't suck.
                            # it doesn't error iff it sucks
                            for i in range(0, N):
                                if r != r2 and c != c2:
                                    # print "%d %d %d -- %d %d %d" % (i,r,c, i,r2,c2)
                                    cnf.addClause("3x3", [-p[i][r][c], -p[i][r2][c2]])