def createLegend(window, node): x1 = .94 xOffset = .02 y1 = .44 yOffset = .02 width = .04 # Initial Speculation window.create_rectangle(window.getWidth() * x1, window.getHeight() * y1, window.getWidth() * (x1 + width), window.getHeight() * (y1 + width), fill=repr(g.Color(.5, .5, .5))) window.create_text(window.getWidth() * (x1 - xOffset), window.getHeight() * (y1 + width / 2), anchor=tk.E, text="Initial Speculation") y1 += width + yOffset # Specific Row Solver window.create_rectangle(window.getWidth() * x1, window.getHeight() * y1, window.getWidth() * (x1 + width), window.getHeight() * (y1 + width), fill=repr(g.Color(.25, 1, .25))) window.create_text(window.getWidth() * (x1 - xOffset), window.getHeight() * (y1 + width / 2), anchor=tk.E, text="Specific Row Solver") y1 += width + yOffset # Sole Box Candidate window.create_rectangle(window.getWidth() * x1, window.getHeight() * y1, window.getWidth() * (x1 + width), window.getHeight() * (y1 + width), fill=repr(g.Color(1, .25, .25))) window.create_text(window.getWidth() * (x1 - xOffset), window.getHeight() * (y1 + width / 2), anchor=tk.E, text="Sole Box Candidate") y1 += width + yOffset # Sole Spot Candidate window.create_rectangle(window.getWidth() * x1, window.getHeight() * y1, window.getWidth() * (x1 + width), window.getHeight() * (y1 + width), fill=repr(g.Color(.25, .25, 1))) window.create_text(window.getWidth() * (x1 - xOffset), window.getHeight() * (y1 + width / 2), anchor=tk.E, text="Sole Spot Candidate")
def soleRowColCandidate(self): changed = 0 color = g.Color(.25, 1, .25) # greenish for row in range(self.size * self.size): for num in range(1, self.size * self.size + 1): if not self.rows[row].contains[num]: # count number of candidate spots count = 0 lastCoordinate = 0 for col in range(self.size * self.size): if self.hints[row][col][num] and self.grid[row][ col] == None: count += 1 lastCoordinate = col if count == 1: self.placeNumber(num, row, lastCoordinate, color=color) changed += 1 for col in range(self.size * self.size): for num in range(1, self.size * self.size + 1): if not self.columns[col].contains[num] and self.grid[row][ col] == None: # start count count = 0 lastCoordinate = 0 for row in range(self.size * self.size): if self.hints[row][col][num]: count += 1 lastCoordinate = row if count == 1: self.placeNumber(num, lastCoordinate, col, color=color) changed += 1 return changed
def soleBoxCandidate(self): changed = 0 color = g.Color(1, .25, .25) # if a number can only go in one spot in a box, place it for box in range(self.size * self.size): for num in range(1, self.size * self.size + 1): # don't bother checking if the box already contains it if not self.boxes[box].contains[num]: # k is coordinate number count = 0 lastCoordinate = 0 for k in range(self.size * self.size): # every 3 boxes is another 3 rows, every 3 k is a single row r = box // self.size * self.size + k // self.size c = box % self.size * self.size + k % self.size if self.grid[r][c] == None: if self.hints[r][c][num]: count += 1 lastCoordinate = k if count == 1: self.placeNumber( num, box // self.size * self.size + lastCoordinate // self.size, box % self.size * self.size + lastCoordinate % self.size, color) changed += 1 return changed
def nakedPairInRow(self): """ This algorithm naively* detects isolated pairs within a single row. *It is naive because it is intuitively easy, but is a different class of isolated-pair from hidden pairs. Therefore it must be attempted. """ # find naked pairs in all rows blockingColor = g.Color(.75, 1, .8, weight=.2) changed = 0 s = self.size for row in range(s * s): if self.rows[row].blankSpots == 2: # no point in doing this... continue for k in range(s * s): hintsK = self.listHints[row][k] if len(hintsK) != 2: continue # not a pair for j in range(s * s): if k == j: continue hintsJ = self.listHints[row][j] if len(hintsJ) != 2: # not a paid continue if self.compareArrays(hintsK, hintsJ): # They match! if self.blockClusterRow(row, [k, j], hintsK, color=blockingColor): changed += 1 self.placeColor(row, k, blockingColor) self.placeColor(row, j, blockingColor) # locked pair analysis # find naked pairs in all columns for col in range(s * s): if self.columns[col].blankSpots == 2: continue for k in range(s * s): hintsK = self.listHints[k][col] if len(hintsK) != 2: continue # not a pair for j in range(s * s): if k == j: continue hintsJ = self.listHints[j][col] if len(hintsJ) != 2: # not a paid continue if self.compareArrays(hintsK, hintsJ): # They match! if self.blockClusterCol(col, [k, j], hintsK, color=blockingColor): changed += 1 self.placeColor(k, col, blockingColor) self.placeColor(j, col, blockingColor) # locked pair analysis return changed
def createColorGrid(self): arr = [] for k in range(self.size * self.size): rowArr = [] for k in range(self.size * self.size): rowArr.append( g.Color(15 / 16.0, 15 / 16.0, 15 / 16.0, weight=.0001)) # rowArr.append(None) arr.append(rowArr) return arr
def soleSpotCandidate(self): changed = 0 color = g.Color(.25, .25, 1) for row in range(self.size * self.size): for col in range(self.size * self.size): if self.grid[row][col] == None: # check to see if theres one candidate if len(self.listHints[row][col]) == 1: self.placeNumber(self.listHints[row][col][0], row, col, color) changed += 1 return changed
def hiddenPairInBox(self): """ This algorithm detects hidden pairs within a single box. More in-depth than naked pairs. steps: (per box) setup local data structure for pair isolations populate structure with box information analyze data block numbers """ changedColor = g.Color(.85, .6, .03, weight=.2) # honey s = self.size changed = 0 for box in range(s * s): if self.boxes[box].blankSpots == 2: continue localHintArray = [None] baseR = box // s * s baseC = box % s * s # set up local structure for k in range(s * s): localHintArray.append([]) # populate local structure for spot in range(s * s): spotHints = self.listHints[baseR + spot // s][baseC + spot % s] for num in spotHints: localHintArray[num].append(spot) # analyze local structure for a in range(1, s * s): if len(localHintArray[a]) != 2: continue for b in range(a + 1, s * s + 1): if len(localHintArray[b]) != 2: continue # arrays are same length, check for pair if self.compareArrays(localHintArray[a], localHintArray[b]): if self.blockClusterBox(box, localHintArray[a], [a, b], changedColor): k = localHintArray[a][0] j = localHintArray[a][1] self.placeColor(baseR + k // s, baseC + k % s, changedColor) self.placeColor(baseR + j // s, baseC + j % s, changedColor) # print("Found a hidden pair in box " + str(box),end=" ") # print([a,b]) changed += 1 return changed
def nakedPairInBox(self): """ This algorithm naively* detects isolated pairs within a single box. *It is naive because it is intuitively easy, but is a different class of isolated-pair from hidden pairs. Therefore it must be attempted. """ changed = 0 blockingColor = g.Color(1, .75, .8, weight=.2) s = self.size for box in range(s * s): if self.boxes[box].blankSpots == 2: # no point in doing this if there are only two left... continue # else there are more, do it baseR = box // s * s baseC = box % s * s for k in range(s * s): hintsK = self.listHints[baseR + k // s][baseC + k % s] if len(hintsK) != 2: # this is no pair continue for j in range(s * s): if k == j: continue hintsJ = self.listHints[baseR + j // s][baseC + j % s] if len(hintsJ) != 2: continue # else they are the same length if self.compareArrays(hintsJ, hintsK): # they match, begin blocking algorithms if self.blockClusterBox(box, [k, j], hintsJ, color=blockingColor): changed += 1 self.placeColor(baseR + k // s, baseC + k % s, blockingColor) self.placeColor(baseR + j // s, baseC + j % s, blockingColor) # print("Found a naked pair in box " + str(box),end=" ") # print(hintsK) if k // s == j // s: # they form a locked pair pass return changed
def solveAndBranch(self): if self.val != None: # print("Starting node of depth " + str(self.depth) + " by placing " + str(self.val) + " at [" + str(self.row) + "][" + str(self.col) + "]",end=" ") # print("With " + str(self.puzzle.blankSpotsLeft) + " spots left") self.puzzle.placeNumber(self.val, self.row, self.col, g.Color(.5, .5, .5)) startTime = time.clock() solveStatus = self.puzzle.solve() endTime = time.clock() self.timeTaken = endTime - startTime if solveStatus: print("SOLVED THIS PUZZLE") print(self.puzzle) self.returnToTree(True) return elif self.puzzle.contradictionExists(): self.valid = False bestR = 0 bestC = 0 minGuesses = self.puzzle.size * self.puzzle.size for r in range(self.puzzle.size * self.puzzle.size): for c in range(self.puzzle.size * self.puzzle.size): if self.puzzle.grid[r][c] == None: if len(self.puzzle.listHints[r][c]) < minGuesses and len( self.puzzle.listHints[r][c]) > 0: bestR = r bestC = c minGuesses = len(self.puzzle.listHints[r][c]) for num in self.puzzle.listHints[bestR][bestC]: if not self.correct and self.valid: # fixed contradictory nodes making children self.children.append( Node(self.puzzle.grid, self.puzzle.size, parent=self, row=bestR, col=bestC, val=num, depth=self.depth + 1)) if not self.correct: self.returnToTree(False) return