Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Решатель судоку аналитическими методами ⇐ ПредыдущаяСтр 5 из 5
TRIPLETS = [[0,1,2],[3,4,5],[6,7,8]]
#Row/ Col /3x3 iteration list, each is nine lists of nine (row, col) pairs ROW_ITER = [[(row,col) for col in range(0,9)] for row in range(0,9)] COL_ITER = [[(row,col) for row in range(0,9)] for col in range(0,9)] TxT_ITER = [[(row,col) for row in rows for col in cols] for rows in TRIPLETS for cols in TRIPLETS]
class sudoku: def __init__ (self, start_grid=None): #Setup list of lists (the rows), each row is a list of 9 cells, which are each a list of integers 1-9 inclusive. self. squares =[ [range(1,10) for col in range(0,9)] for row in range(0,9)]
if start_grid is not None: if len(start_grid)==81: for row in range(0,9): self. set_row(row, start_grid[(row*9):((row+1)*9)]) else: assert len(start_grid)==9, "Bad input!" for row in range(0,9): self. set_row(row, start_grid[row])
#self.check() self. _changed=False
def solved (self): for row in range(0,9): for col in range(0,9): if len(self. squares[row][col]) > 1: return False return True
def copy (self): sudoku_copy = sudoku(None) for row in range(0,9): for col in range(0,9): sudoku_copy.squares[row][col] = self. squares[row][col][:] #copy! sudoku_copy._changed=False return sudoku_copy
def set_row (self,row, x_list): assert len(x_list)==9 for col in range(0,9): try: x = int(x_list[col]) except: x = 0 #self.set_cell(row, col,x) self. set_cell(row,col,x)
def set_cell (self,row,col,x): if self. squares[row][col] == [x]: #Already done! pass elif x not in range(1,9+1): #Set to unknown pass else: assert x in self. squares[row][col], \ "Told to set square (%i,%i) to an impossible entry, %i" % (row,col,x)
self. squares[row][col] = [x] self. update_neighbours(row,col,x) self. _changed=True
def cell_exclude (self, row,col,x): assert x in range(1,9+1) if x in self. squares[row][col]: #Remove it... self. squares[row][col].remove(x) #Should be one or more entries left... assert len(self. squares[row][col]) > 0, \ "Removed last possible entry for square (%i,%i) which was %i" \ % (row, col, x) #Now, has this confirmed the value for this square? if len(self. squares[row][col]) == 1: #This cell is now definate.. #Need to update its friends... #print "After exluding %i, square (%i,%i) must be %i" \ #% (x, self.row, self.col, self[0]) self. _changed=True self. update_neighbours(row,col, self. squares[row][col][0]) else: #Don't need to remove this, already done! pass return
def row_exclude (self, row, x): assert x in range(1,9+1) for col in range(0,9): self. cell_exclude(row,col,x)
def col_exclude (self, col, x): assert x in range(1,9+1) for row in range(0,9): self. cell_exclude(row,col,x)
def update_neighbours (self,set_row,set_col,x): """Call this when the square is set to x, either directly, or as a side effect of an exclude leaving only one entry""" #print "Updating (%i,%i) to be %i..." % (self.row, self.col, x) #Update the possibilies in this row... for row in range(0,9): if row <> set_row: self. cell_exclude(row,set_col,x) #Update the possibilies in this col... for col in range(0,9): if col <> set_col: self. cell_exclude(set_row,col,x) #Update the possibilies in this 3x3 square... for triplet in TRIPLETS: if set_row in triplet: rows = triplet[:] if set_col in triplet: cols = triplet[:] #Only need to do four of the eight possibles (well, 9 if you count the cell itself) #as did two on the row, and two on the col rows.remove(set_row) cols.remove(set_col) for row in rows: for col in cols: assert row <> set_row or col <> set_col #print "Updating (%i,%i) to be %i, excluding %i from (%i, %i)" \ #% (self.row, self.col, x, x, row, col)
self. cell_exclude(row,col,x)
def get_cell_int (self,row,col): if len(self. squares[row][col])==1: return int(self. squares[row][col][0]) else: return 0
def get_cell_str (self,row,col): if len(self. squares[row][col])==1: return "(%i,%i) = %i" % (row, col, self. squares[row][col][0]) else: return ("(%i,%i) = " % (row, col)) + ",". join([str(x) for x in self. squares[row][col]])
def get_cell_digit_str (self,row,col): if len(self. squares[row][col])==1: return str(self. squares[row][col][0]) else: return "0"
def as_test_81 (self): """Return a string of 81 digits""" return "". join(self. as_test_list())
def simple_text (self): return "\n". join(self. as_test_list())
def as_test_list (self): return [ ("". join([ self. get_cell_digit_str(row,col) for col in range(0,9)])) for row in range(0,9) ] """ answer=[] for row in range(0,9): line="" for col in range(0,9): line = line + self.get_cell_digit_str(row, col) answer.append(line) return answer """
def __repr__ (self): answer= "[" + ",". join([ \ ("[" + ",". join([ self. get_cell_digit_str(row,col) for col in range(0,9)]) + "]") \ for row in range(0,9) ]) return answer
def __str__ (self): answer = " 123 456 789\n" for row in range(0,9): answer = answer + str(row+1) \ + " [" + "". join([ self. get_cell_digit_str(row,col).replace("0", "?") for col in range(0,3)]) \ + "] [" + "". join([ self. get_cell_digit_str(row,col).replace("0", "?") for col in range(3,6)]) \ + "] [" + "". join([ self. get_cell_digit_str(row,col).replace("0", "?") for col in range(6,9)]) \ + "]\n" if row+1 in [3,6]: answer = answer + " --- --- ---\n" return answer
def retArr (self): data = [] for row in range(0,9): data.append([]) for col in range(0, 9): data[row].append(self. get_cell_digit_str(row,col)) return data
def check (self, level=0): self. _changed=True while self. _changed: #print "checking..." self. _changed=False self. check_for_single_occurances() self. check_for_last_in_row_col_3x3() if level >= 1: self. overlapping_3x3_and_row_or_col() #(aka slicing and dicing) if level >= 2: self. one_level_supposition() if level >= 3: self. two_level_supposition()
#If nothing happened, then self.changed==False (still) #and we break the loop return
def check_for_single_occurances (self): #Want to see if x only occurs once in this row/ col /3x3... for check_type in [ROW_ITER, COL_ITER, TxT_ITER]: for check_list in check_type: for x in range(1,9+1): #1 to 9 inclusive x_in_list = [] for (row,col) in check_list: if x in self. squares[row][col]: x_in_list.append((row,col)) if len(x_in_list)==1: (row,col) = x_in_list[0] #This position MUST be be x if len(self. squares[row][col]) > 1: self. set_cell(row,col,x)
def check_for_last_in_row_col_3x3 (self): #Now, for each row/ col /3x3 want to see if there is a single #unknown entry... for (type_name, check_type) in [("Row",ROW_ITER),(" Col ",COL_ITER),("3x3",TxT_ITER)]: for check_list in check_type: unknown_entries = [] unassigned_values = range(1,9+1) #1-9 inclusive known_values = [] for (row,col) in check_list: if len(self. squares[row][col]) == 1: assert self. squares[row][col][0] not in known_values, \ "Already have %i (%i,%i) in known list [%s] for %s" % (self. squares[row][col][0],row,col, ",". join(map(str,known_values)), type_name)
known_values.append(self. squares[row][col][0])
assert self. squares[row][col][0] in unassigned_values, \ "Expected %i (%i,%i) in list [%s] for %s" % (self. squares[row][col][0],row,col, ",". join(map(str,unassigned_values)), type_name)
unassigned_values.remove(self. squares[row][col][0]) else: unknown_entries.append((row,col)) assert len(unknown_entries) + len(known_values) == 9 assert len(unknown_entries) == len(unassigned_values) if len(unknown_entries) == 1: #This cell must be the only number 1-9 not in known_values x = unassigned_values[0] (row,col) = unknown_entries[0]
#assert x not in known_values
#print "Because its the last cell in its row/ col /3x3 entry (%i,%i) must be %i" \ #% (row, col,x) self. set_cell(row,col,x) """ for row in range(0,9): self.check_row(row) for col in range(0,9): self.check_col(col) #Check the 3x3 squares... for rows in TRIPLETS: for cols in TRIPLETS: for x in range(0,9): x_in_location=[] for row in rows: for col in cols: if x in self.squares[row][ col ]: x_in_location.append((row, col)) if len (x_in_location)==1: (row, col) = x_in_location[0] #This position MUST be be x if len (self.squares[row][ col ]) > 1: self.set_cell(row, col,x) """ return
def diagnosis (self): answer= "" df = long(1) for row in range(0,9): for col in range(0,9): if len(self. squares[row][col]) > 1: answer = answer + str(self. squares[row][col]) + "\n" df = df * len(self. squares[row][col]) answer = answer + "Degrees of freedom: %i" % df return answer
def overlapping_3x3_and_row_or_col (self): """Block and Column / Row Interactions (name from Simon Armstrong)
http://www.simes.clara.co.uk/programs/sudokutechnique3.htm
Also known as 'slicing and dicing' """ #For a given 3x3, and a given digit, want to see if #all the remaining candidates are in a single row or column.. #Want to see if x only occurs once in this row/ col /3x3... for check_list in TxT_ITER: for x in range(1,9+1): #1 to 9 inclusive #print "Checking %i in 3x3" % x, check_list rows_for_x = [] cols_for_x = [] for (row,col) in check_list: if x in self. squares[row][col]: #print "Found possible %i at (%i,%i)" % (x, row, col) if row not in rows_for_x: rows_for_x.append(row) if col not in cols_for_x: cols_for_x.append(col) #Are they all in the same row? if len(rows_for_x)==1 and len(cols_for_x) > 1: #print "%i must be in row %i using cols %s" % (x, rows_for_x[0]+1, ",".join(map(lambda i: str (i+1),cols_for_x))) #print self #This means, we can remove X from all the rest of the row... row = rows_for_x[0] for col in range(0,9): if col not in cols_for_x: self. cell_exclude(row,col,x) #We can also remove x from all the rest of this 3x3... for (row,col) in check_list: if col not in cols_for_x: if row not in rows_for_x: self. cell_exclude(row,col,x) #Are they all in the same col? if len(cols_for_x)==1 and len(rows_for_x) > 1: #print "%i must be in col %i using rows %s" % (x, cols_for_x[0]+1, ",".join(map(lambda i: str (i+1),rows_for_x))) #print self #This means, we can remove X from all the rest of the row... col = cols_for_x[0] for row in range(0,9): if row not in rows_for_x: self. cell_exclude(row,col,x) #We can also remove x from all the rest of this 3x3... for (row,col) in check_list: if col not in cols_for_x: if row not in rows_for_x: self. cell_exclude(row,col,x)
def one_level_supposition (self): """Probably what is known as ' Nishio ', try a number and see if it leads to a dead end. For all the ambigous squares, try each possible each entry and see if its OK, or if it leads to a contradiction. In the case of a contradiction we can remove it as a possibility... Two level suppositions (two guess) may be required for extreme puzzles...""" progress=True while progress: progress=False #print "Doing one level supposition..." for row in range(0,9): for col in range(0,9): if len(self. squares[row][col]) > 1: bad_x = [] for x in self. squares[row][col]: #print "/-- Trying setting (%i,%i) to %i" % (row, col,x) sudoku_copy = self. copy() try: sudoku_copy.set_cell(row,col,x) sudoku_copy.check(level=1) except AssertionError, e: #Leads to an error:) #This means that this square cannot be x #print e #print "%s cannot be %i" % (str (self.squares[row][ col ]), x) bad_x.append(x) del sudoku_copy #print "\-- End of exp " if len(bad_x) == 0: pass elif len(bad_x) < len(self. squares[row][col]): for x in bad_x: self. cell_exclude(row,col,x) self. check() progress=True else: assert False, "Bugger! All possible values for square (%i,%i) fail" \ % (row,col) #print "One level supposition done"
def two_level_supposition (self): progress=True while progress: progress=False #print "Doing two level supposition..." for row in range(0,9): for col in range(0,9): if len(self. squares[row][col]) > 1: bad_x = [] for x in self. squares[row][col]: #print "/-- Trying setting (%i,%i) to %i" % (row, col,x) sudoku_copy = self. copy() try: sudoku_copy.set_cell(row,col,x) #sudoku_copy.check() #sudoku_copy.one_level_supposition() sudoku_copy.check(level=2)
except AssertionError, e: bad_x.append(x) del sudoku_copy #print "\-- End of exp " if len(bad_x) == 0: pass elif len(bad_x) < len(self. squares[row][col]): for x in bad_x: self. cell_exclude(row,col,x) self. check() progress=True else: assert False, "Bugger! All possible values for square (%i,%i) fail" \ % (row,col)
|
|||||||
Последнее изменение этой страницы: 2016-12-13; просмотров: 172; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.145.8.42 (0.066 с.) |