def test_coordsFromIndexAgainstValue(self): self.sudokuBoard.clearBoard() self.sudokuBoard.loadBoard('preloads/sudoku1.txt') for index in range(81): valByIndex = self.sudokuBoard.getDigit(index) coords = SudokuBoard.coordsFromIndex(index) index2 = SudokuBoard.indexFromCoords(coords) valByIndex2 = self.sudokuBoard.getDigit(index2) self.assertTrue(valByIndex == valByIndex2)
def resolve(sudokuStr): sudokuStr = sudokuStr.replace("x", "0") board = SudokuBoard(sudokuStr) if board.isValid() == False: print "The board is not valid, give me a break!" # think(board, 0, 0); return board.toString()
def test_squareFromCoords(self): self.assertTrue(SudokuBoard.squareFromCoords((0,0)) == 0) self.assertTrue(SudokuBoard.squareFromCoords((4,1)) == 1) self.assertTrue(SudokuBoard.squareFromCoords((8,2)) == 2) self.assertTrue(SudokuBoard.squareFromCoords((0,3)) == 3) self.assertTrue(SudokuBoard.squareFromCoords((4,4)) == 4) self.assertTrue(SudokuBoard.squareFromCoords((8,5)) == 5) self.assertTrue(SudokuBoard.squareFromCoords((0,6)) == 6) self.assertTrue(SudokuBoard.squareFromCoords((4,7)) == 7) self.assertTrue(SudokuBoard.squareFromCoords((8,8)) == 8)
def solveUsingIntersect(sb): alg2 = AlgIntersectValue2(sb) goodRun = False solutions = [] contSolving = True iteration = 0 while contSolving: # Check each place anyFound = False; for index in range(81): place = sb.getDigit(index) if place is None: # Place is empty, check if we can solve it solution = alg2.runAlg(SudokuBoard.coordsFromIndex(index)) if solution is not None: solutions.append((index, solution)) anyFound = True goodRun = True print("Iteration {0}: Found {1} solutions!".format(iteration, len(solutions))) for i in solutions: print("Index: {0} Solution: {1}".format(i[0], i[1])) sb.setDigit(i[1], i[0]) solutions.clear() contSolving = anyFound iteration += 1 # was this good run? return goodRun
class Test_testAlgIntersectValue(unittest.TestCase): def setUp(self): self.board = SudokuBoard() self.board.loadBoard('preloads/sudoku3.txt') self.alg = AlgIntersectValue(self.board) def test_AlgIntersectNonBlankValue(self): coords = (0,1) self.assertTrue(self.alg.runAlg(coords) == None) def test_AlgIntersectNotSolvable(self): coords = (8,8) self.assertTrue(self.alg.runAlg(coords) == None) def test_AlgIntersectSolve(self): coords = (1,1) self.assertTrue(self.alg.runAlg(coords) == 9)
def runAlg(self, coords): # Get digit at coords n = self.board.getDigit(SudokuBoard.indexFromCoords(coords)) # Should we solve it? if n is not None: return None # Get candidates at the square cands = self.getCand(coords) if len(cands) != 1: return None else: return cands.pop()
from SudokuBoard import SudokuBoard from AlgIntersectValue2 import AlgIntersectValue2 from AlgNumbersInLayers import AlgNumbersInLayers # Create and load board sb = SudokuBoard() sb.loadBoard('preloads/sudoku1.txt') sb.printBoard() def solveUsingIntersect(sb): alg2 = AlgIntersectValue2(sb) goodRun = False solutions = [] contSolving = True iteration = 0 while contSolving: # Check each place anyFound = False; for index in range(81): place = sb.getDigit(index) if place is None: # Place is empty, check if we can solve it solution = alg2.runAlg(SudokuBoard.coordsFromIndex(index)) if solution is not None: solutions.append((index, solution)) anyFound = True goodRun = True print("Iteration {0}: Found {1} solutions!".format(iteration, len(solutions))) for i in solutions:
from SudokuBoard import SudokuBoard 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] if __name__ == "__main__": easy = SudokuBoard("..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..") print "This is an easy puzzle ..." print easy.pretty_initial_state() easy.solve() print easy.pretty() print "done" hard = SudokuBoard("4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......") print "This is a very HARD puzzle ..." print hard.pretty_initial_state() hard.solve() print hard.pretty_values() print "done"
def setUp(self): self.sudokuBoard = SudokuBoard()
class TestSudokuBoard(unittest.TestCase): def setUp(self): self.sudokuBoard = SudokuBoard() # Init the object def test_initAllToNone(self): self.setUp() vals = [] for k in range(81): vals.append(self.sudokuBoard.baseData[k]) #self.assertIsInstance(self.sudokuBoard.baseData[0], NoneType) self.assertTrue(all(vals[0] == item for item in vals)) def test_startAtVer0(self): self.setUp() self.assertEqual(self.sudokuBoard.version, 0) # Get the value def test_getDigitIndexIsInt(self): with self.assertRaises(TypeError): self.sudokuBoard.getDigit("string") def test_getDigitIndexMin(self): with self.assertRaises(ValueError): self.sudokuBoard.getDigit(-1) def test_getDigitIndexMax(self): with self.assertRaises(ValueError): self.sudokuBoard.getDigit(81) def test_getDigitIndexWork(self): index = 5 value = 5 self.sudokuBoard.baseData[index] = value self.assertEqual(self.sudokuBoard.getDigit(index), value) def test_getDigitIndexRetNone(self): self.setUp() self.assertIsNone(self.sudokuBoard.getDigit(1)) def test_getDigitIndexRetInt(self): index = 1 value = 1 self.sudokuBoard.baseData[index] = value self.assertIsInstance(self.sudokuBoard.getDigit(index), int) # Set the value def test_setDigitIndexIsInt(self): with self.assertRaises(TypeError): self.sudokuBoard.setDigit(1, "string") def test_setDigitValueIsInt(self): with self.assertRaises(TypeError): self.sudokuBoard.setDigit("string", 1) def test_setDigitIndexMin(self): with self.assertRaises(ValueError): self.sudokuBoard.setDigit(1, -1) def test_setDigitIndexMax(self): with self.assertRaises(ValueError): self.sudokuBoard.setDigit(1, 81) def test_setDigitValueMin(self): with self.assertRaises(ValueError): self.sudokuBoard.setDigit(0, 1) def test_setDigitValueMax(self): with self.assertRaises(ValueError): self.sudokuBoard.setDigit(10, 1) def test_setDigitValueSet(self): index = 1 value = 2 self.sudokuBoard.setDigit(value, index) self.assertEqual(self.sudokuBoard.baseData[index], value) def test_setDigitVerIncr(self): verOld = self.sudokuBoard.version self.sudokuBoard.setDigit(1, 1) self.assertTrue(self.sudokuBoard.version > verOld) # Get row def test_getRowNumIsInt(self): with self.assertRaises(TypeError): for i in self.sudokuBoard.getRow("string"): a = i def test_getRowNumMin(self): with self.assertRaises(ValueError): for i in self.sudokuBoard.getRow(-1): a = i def test_getRowNumMax(self): with self.assertRaises(ValueError): for i in self.sudokuBoard.getRow(9): a = i def test_getRowReturnIter(self): i = self.sudokuBoard.getRow(1) iter(i) # Get col def test_getColNumIsInt(self): with self.assertRaises(TypeError): for i in self.sudokuBoard.getCol("string"): a = i def test_getColNumMin(self): with self.assertRaises(ValueError): for i in self.sudokuBoard.getCol(-1): a = i def test_getColNumMax(self): with self.assertRaises(ValueError): for i in self.sudokuBoard.getCol(9): a = i def test_getColReturnIter(self): i = self.sudokuBoard.getCol(1) iter(i) # Get square def test_getSqrNumIsInt(self): with self.assertRaises(TypeError): for i in self.sudokuBoard.getSqr("string"): a = i def test_getSqrNumMin(self): with self.assertRaises(ValueError): for i in self.sudokuBoard.getSqr(-1): a = i def test_getSqrNumMax(self): with self.assertRaises(ValueError): for i in self.sudokuBoard.getSqr(9): a = i def test_getSqrReturnIter(self): i = self.sudokuBoard.getSqr(1) iter(i) def test_getSqrReturnVal(self): self.sudokuBoard.clearBoard() self.sudokuBoard.loadBoard('preloads/sudoku1.txt') actual = list(i for i in self.sudokuBoard.getSqr(0)) expected = [None, None,None, 8, None, None, None, 4, 9] self.assertTrue(actual == expected) # Multitest for coords - index translation def test_coordsFromIndexAgainstValue(self): self.sudokuBoard.clearBoard() self.sudokuBoard.loadBoard('preloads/sudoku1.txt') for index in range(81): valByIndex = self.sudokuBoard.getDigit(index) coords = SudokuBoard.coordsFromIndex(index) index2 = SudokuBoard.indexFromCoords(coords) valByIndex2 = self.sudokuBoard.getDigit(index2) self.assertTrue(valByIndex == valByIndex2) # Validity test def test_testGroup(self): # Empty iterator self.assertFalse(self.sudokuBoard.testGroup([])) # Too short iterator self.assertFalse(self.sudokuBoard.testGroup(range(5))) # Too long iterator self.assertFalse(self.sudokuBoard.testGroup(range(11))) # Good length wrong numbers self.assertFalse(self.sudokuBoard.testGroup(range(9))) # Good length, some Nones self.assertFalse(self.sudokuBoard.testGroup([1,2,3,4,5,6,7,8,None])) # Valid group self.assertTrue(self.sudokuBoard.testGroup(range(1,10))) def test_indexFromCoords(self): self.assertTrue(SudokuBoard.indexFromCoords((0,0)) == 0) self.assertTrue(SudokuBoard.indexFromCoords((1,1)) == 10) self.assertTrue(SudokuBoard.indexFromCoords((8,8)) == 80) def test_squareFromCoords(self): self.assertTrue(SudokuBoard.squareFromCoords((0,0)) == 0) self.assertTrue(SudokuBoard.squareFromCoords((4,1)) == 1) self.assertTrue(SudokuBoard.squareFromCoords((8,2)) == 2) self.assertTrue(SudokuBoard.squareFromCoords((0,3)) == 3) self.assertTrue(SudokuBoard.squareFromCoords((4,4)) == 4) self.assertTrue(SudokuBoard.squareFromCoords((8,5)) == 5) self.assertTrue(SudokuBoard.squareFromCoords((0,6)) == 6) self.assertTrue(SudokuBoard.squareFromCoords((4,7)) == 7) self.assertTrue(SudokuBoard.squareFromCoords((8,8)) == 8)
def test_indexFromCoords(self): self.assertTrue(SudokuBoard.indexFromCoords((0,0)) == 0) self.assertTrue(SudokuBoard.indexFromCoords((1,1)) == 10) self.assertTrue(SudokuBoard.indexFromCoords((8,8)) == 80)
# import numpy as np from SudokuBoard import SudokuBoard from SudokuDisplay import SudokuDisplay # input sudoku as 9x9 with 0s as empty spaces input_board = [ '006309005', '003000472', '805010030', '000407690', '002901008', '401080000', '080000204', '060570100', '030060700' ] if __name__ == "__main__": # init brett brett = SudokuBoard(input_board) # display window window = SudokuDisplay(brett)
# test_isinstance.py """ Not seeing SudokuData """ from SudokuBoard import SudokuBoard from SudokuData import SudokuData from SudokuPly import SudokuPly sb = SudokuBoard() sd = SudokuData() sp = SudokuPly() if isinstance(sd, SudokuData): print(f"Found sd{sd} to be SudokuData instance") else: print(f"Did not find sd{sd} to be SudokuData instance")
def get_sudoku_object(self): return SudokuBoard([ self.board[x][y] if type(self.board[x][y]) is int else 0 for x, y in product(SudokuBoard.INDEX_RANGE, SudokuBoard.INDEX_RANGE) ])
def make_puzzle(nfilled=None): """ Create puzzle with number of cells filled in Set reset_data to this :nfilled: Number of cells filled in, None = random """ ###global o_data, o_board display_close() if (g.o_data is None): g.o_data = SudokuData( cols=g.nCol, rows=g.nRow, gcols=g.nSubCol, grows=g.nSubRow, ) g.o_data.clear() # Clear data if g.o_board is None: g.o_board = SudokuBoard(mw=g.mw, frame=new_main_bd_frame(), data=g.o_data, bdWidth=g.bSize, bdHeight=g.bSize) ncell = g.nRow * g.nCol if (nfilled is None): nfilled = int(ncell / 3) if nfilled & 1 != 0 and ncell & 1 != 0: nfilled -= 1 # No possible symitry # with odd # and even row/col o_list = SudokuData(base=g.o_data) a_start_list = o_list.startCells(nFilled=nfilled, symRules=g.makePuzzleSym) if (a_start_list is None): SlTrace.lg(f"no such pattern for nRow=:{g.nRow}, nCol=:{g.nCol}" + f" nFilled={nfilled} symRules={g.makePuzzleSym}") sys.exit("quitting") # Display start list sl = SudokuData(rows=g.nRow, grows=g.nSubRow, cols=g.nCol, gcols=g.nSubCol) # for diagnostic display SlTrace.lg(f"start list: ") n = 0 for sc in a_start_list: val = n if (n <= ord('Z') - ord('A')): val = chr(ord('A') + n) elif (n < 2 * (ord('Z') - ord('A'))): val_ord = ord('a') + n - ((ord('Z') - ord('A') - 1)) val = chr(val_ord) sl.setCellVal(sc.row, sc.col, val) SlTrace.lg(f" (r:{sc.row}, c:{sc.col})") n += 1 sl.display() if (len(a_start_list) != nfilled): SlTrace.lg(f"Actual list = {len(a_start_list)}" + f" Requested list = {nfilled}") # Set starting arrangement o_sol = SudokuPly(base=g.o_data) sols = o_sol.makePuzzle(startList=a_start_list) if sols is not None and len(sols) == 1 and defined(sols[0]): sol = sols[0] g.o_data = sol.getData(subset=a_start_list) g.o_board.showData(g.o_data) g.Initial_data = SudokuData(base=g.o_data) return sols
def runAlg(self, layer): # Get numbers in each layer self.row = [] self.row.append(list(self.board.getRow(3 * layer + 0))) self.row.append(list(self.board.getRow(3 * layer + 1))) self.row.append(list(self.board.getRow(3 * layer + 2))) # loop all numbers for target in range(1,10): #print("Analyzing target {0}".format(target)) # Analyze the situation self.analyzePositions(target) # For now implement only when a single row is missing a target # Get a row that is missing a target missingRow = self.rowMissingTarget() #print("Missing row {0}".format(missingRow)) if missingRow is None: continue # Get the third that should contain the missing number allThirds = set(range(0,3)) if missingRow == 0: allThirds.remove(self.row1TargetThird) allThirds.remove(self.row2TargetThird) elif missingRow == 1: allThirds.remove(self.row0TargetThird) allThirds.remove(self.row2TargetThird) else: allThirds.remove(self.row0TargetThird) allThirds.remove(self.row1TargetThird) targetThird = allThirds.pop() #print("Target third {0}".format(targetThird)) # Get the numbers in the target third in targer row slice = [] if targetThird == 0: slice = self.row[missingRow][0:3] elif targetThird == 1: slice = self.row[missingRow][3:6] else: slice = self.row[missingRow][6:9] #print("Target slice: {0}".format(slice)) # Get the number of Nones in the slice numNone = slice.count(None) #print("Count none {0}".format(numNone)) # If only one - we can return now if numNone == 1: noneIndex = slice.index(None) #print("None index {0}".format(noneIndex)) index = SudokuBoard.indexFromCoords(((targetThird * 3 + noneIndex), layer * 3 + missingRow)) return (index, target) # Nothing found return None
def setUp(self): self.board = SudokuBoard() self.board.loadBoard('preloads/sudoku3.txt') self.alg = AlgIntersectValue(self.board)