[gnome-games] gnome-sudoku: Style cleanup in sudoku.py
- From: Zhang Sen <zhangsen src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnome-games] gnome-sudoku: Style cleanup in sudoku.py
- Date: Tue, 12 May 2009 08:42:33 -0400 (EDT)
commit 39827c18eb125402e2631e9d63e1cc2fc491c3aa
Author: Zhang Sen <zh jesse gmail com>
Date: Tue May 12 20:11:20 2009 +0800
gnome-sudoku: Style cleanup in sudoku.py
Nothing but adding spaces and newlines. Part of bug 578903.
---
gnome-sudoku/src/lib/sudoku.py | 433 +++++++++++++++++++++-------------------
1 files changed, 228 insertions(+), 205 deletions(-)
diff --git a/gnome-sudoku/src/lib/sudoku.py b/gnome-sudoku/src/lib/sudoku.py
index 8974811..7a83de5 100644
--- a/gnome-sudoku/src/lib/sudoku.py
+++ b/gnome-sudoku/src/lib/sudoku.py
@@ -10,11 +10,12 @@ TYPE_ROW = 0
TYPE_COLUMN = 1
TYPE_BOX = 2
-digit_set = range(1,GROUP_SIZE+1)
+digit_set = range(1, GROUP_SIZE + 1)
sets = [digit_set] * 9
def is_set (row):
- if len(row)==len(set(row)): return True
+ if len(row) == len(set(row)):
+ return True
def is_sudoku (rows):
# check rows
@@ -23,20 +24,22 @@ def is_sudoku (rows):
return False
for i in range(len(rows[0])):
rw = [r[i] for r in rows]
- if not is_set(rw): return False
+ if not is_set(rw):
+ return False
# check boxes
width = int(math.sqrt(len(rows)))
# there should be 3x3 boxes, or 4x4 if we got funky, etc.
# boxes will be indices
- box_coordinates = [[n*width,
- (n+1)*width] for n in range(width)]
+ box_coordinates = [[n * width,
+ (n + 1) * width] for n in range(width)]
for x in box_coordinates:
for y in box_coordinates:
box = []
for xrow in [rows[ri] for ri in range(*y)]:
for i in range(*x):
box.append(xrow[i])
- if not is_set(box): return False
+ if not is_set(box):
+ return False
return True
class UnsolvablePuzzle (TypeError):
@@ -46,7 +49,7 @@ class UnsolvablePuzzle (TypeError):
class ConflictError (ValueError):
def __init__ (self, conflict_type, coordinates, value):
- self.args = conflict_type,coordinates,value
+ self.args = conflict_type, coordinates, value
self.type = conflict_type
self.coordinates = coordinates
self.x = coordinates[0]
@@ -57,94 +60,97 @@ class AlreadySetError (ValueError):
pass
class SudokuGrid:
- def __init__ (self, grid=False, verbose=False, group_size=9):
+ def __init__ (self, grid = False, verbose = False, group_size = 9):
self.grid = []
self.cols = []
self.rows = []
self.boxes = []
self.group_size = int(group_size)
- self.verbose=False
- self.gen_set = set(range(1,self.group_size+1))
+ self.verbose = False
+ self.gen_set = set(range(1, self.group_size + 1))
for n in range(self.group_size):
self.cols.append(set())
self.rows.append(set())
self.boxes.append(set())
- self.grid.append([0]*self.group_size)
+ self.grid.append([0] * self.group_size)
self.box_by_coords = {}
self.box_coords = {}
self.calculate_box_coords() # sets box_coords and box_by_coords
self.row_coords = {}
- for n,row in enumerate([[(x,y) for x in range(self.group_size)] for y in range(self.group_size)]):
- self.row_coords[n]=row
+ for n, row in enumerate([[(x, y) for x in range(self.group_size)] for y in range(self.group_size)]):
+ self.row_coords[n] = row
self.col_coords = {}
- for n,col in enumerate([[(x,y) for y in range(self.group_size)] for x in range(self.group_size)]):
- self.col_coords[n]=col
+ for n, col in enumerate([[(x, y) for y in range(self.group_size)] for x in range(self.group_size)]):
+ self.col_coords[n] = col
if grid:
- if type(grid)==str:
- g=re.split("\s+",grid)
+ if type(grid) == str:
+ g = re.split("\s+", grid)
side = int(math.sqrt(len(g)))
grid = []
for row in range(side):
- start = row*int(side)
- grid.append([int(i) for i in g[start:start+side]])
+ start = row * int(side)
+ grid.append([int(i) for i in g[start:start + side]])
self.populate_from_grid(grid)
- self.verbose=verbose
+ self.verbose = verbose
def calculate_box_coords (self):
width = int(math.sqrt(self.group_size))
- box_coordinates = [[n*width,
- (n+1)*width] for n in range(width)]
+ box_coordinates = [[n * width,
+ (n + 1) * width] for n in range(width)]
box_num = 0
for xx in box_coordinates:
for yy in box_coordinates:
- self.box_coords[box_num]=[]
+ self.box_coords[box_num] = []
for x in range(*xx):
for y in range(*yy):
- self.box_by_coords[(x,y)]=box_num
- self.box_coords[box_num].append((x,y))
+ self.box_by_coords[(x, y)] = box_num
+ self.box_coords[box_num].append((x, y))
box_num += 1
- def add (self, x, y, val, force=False):
- if not val: pass
- if self._get_(x,y):
+ def add (self, x, y, val, force = False):
+ if not val:
+ pass
+ if self._get_(x, y):
if force:
try:
- self.remove(x,y)
+ self.remove(x, y)
except:
- print 'Strange: problem with add(',x,y,val,force,')'
+ print 'Strange: problem with add(', x, y, val, force, ')'
import traceback
traceback.print_exc()
else:
#FIXME: This is called when the fill button
#is clicked multiple times, which causes this exception:
#raise AlreadySetError
- return;
+ return
if val in self.rows[y]:
- raise ConflictError(TYPE_ROW,(x,y),val)
+ raise ConflictError(TYPE_ROW, (x, y), val)
if val in self.cols[x]:
- raise ConflictError(TYPE_COLUMN,(x,y),val)
- box=self.box_by_coords[(x,y)]
+ raise ConflictError(TYPE_COLUMN, (x, y), val)
+ box = self.box_by_coords[(x, y)]
if val in self.boxes[box]:
- raise ConflictError(TYPE_BOX,(x,y),val)
+ raise ConflictError(TYPE_BOX, (x, y), val)
# do the actual adding
self.rows[y].add(val)
self.cols[x].add(val)
self.boxes[box].add(val)
- self._set_(x,y,val)
+ self._set_(x, y, val)
def remove (self, x, y):
- val = self._get_(x,y)
+ val = self._get_(x, y)
self.rows[y].remove(val)
self.cols[x].remove(val)
- self.boxes[self.box_by_coords[(x,y)]].remove(val)
- self._set_(x,y,0)
+ self.boxes[self.box_by_coords[(x, y)]].remove(val)
+ self._set_(x, y, 0)
- def _get_ (self, x, y): return self.grid[y][x]
+ def _get_ (self, x, y):
+ return self.grid[y][x]
- def _set_ (self, x, y, val): self.grid[y][x]=val
+ def _set_ (self, x, y, val):
+ self.grid[y][x] = val
def possible_values (self, x, y):
- return self.gen_set - self.rows[y] - self.cols[x] - self.boxes[self.box_by_coords[(x,y)]]
+ return self.gen_set - self.rows[y] - self.cols[x] - self.boxes[self.box_by_coords[(x, y)]]
def pretty_print (self):
print 'SUDOKU'
@@ -155,10 +161,10 @@ class SudokuGrid:
print
def populate_from_grid (self, grid):
- for y,row in enumerate(grid):
- for x,cell in enumerate(row):
+ for y, row in enumerate(grid):
+ for x, cell in enumerate(row):
if cell:
- self.add(x,y,cell)
+ self.add(x, y, cell)
def __repr__ (self):
s = "<Grid\n "
@@ -172,31 +178,31 @@ class SudokuGrid:
possibilities = {}
for x in range(self.group_size):
for y in range(self.group_size):
- if not self._get_(x,y):
- possibilities[(x,y)]=self.possible_values(x,y)
+ if not self._get_(x, y):
+ possibilities[(x, y)] = self.possible_values(x, y)
return possibilities
- def find_conflicts (self, x, y, val, conflict_type=None):
+ def find_conflicts (self, x, y, val, conflict_type = None):
'''Find all squares that conflict with value val at position x,y.
If conflict_type is specified, we only find conflicts of given
type (ROW, COLUMN OR BOX).
'''
- if conflict_type==TYPE_ROW:
+ if conflict_type == TYPE_ROW:
coords = self.row_coords[y]
- elif conflict_type==TYPE_COLUMN:
+ elif conflict_type == TYPE_COLUMN:
coords = self.col_coords[x]
- elif conflict_type==TYPE_BOX:
- coords = self.box_coords[self.box_by_coords[(x,y)]]
+ elif conflict_type == TYPE_BOX:
+ coords = self.box_coords[self.box_by_coords[(x, y)]]
else:
coords = (self.row_coords[y]
+ self.col_coords[x]
- + self.box_coords[self.box_by_coords[(x,y)]]
+ + self.box_coords[self.box_by_coords[(x, y)]]
)
conflicting_coordinates = []
- for x,y in coords:
- if self._get_(x,y)==val:
- conflicting_coordinates.append((x,y))
+ for x, y in coords:
+ if self._get_(x, y) == val:
+ conflicting_coordinates.append((x, y))
return conflicting_coordinates
def to_string (self):
@@ -214,9 +220,9 @@ def is_valid_puzzle (p):
corrupted puzzles).
"""
try:
- p = p.replace(' ','')
- assert(len(p.replace(' ',''))==81)
- [int(c) for c in p.replace(' ','')]
+ p = p.replace(' ', '')
+ assert(len(p.replace(' ', '')) == 81)
+ [int(c) for c in p.replace(' ', '')]
except:
#import traceback; traceback.print_exc()
return False
@@ -225,15 +231,17 @@ def is_valid_puzzle (p):
def sudoku_grid_from_string (s):
"""Given an 81 character string, return a grid."""
- s=s.replace(' ','')
- assert(len(s)<=GROUP_SIZE**2)
+ s = s.replace(' ', '')
+ assert(len(s)<=GROUP_SIZE ** 2)
grid = []
i = 0
for x in range(GROUP_SIZE):
row = []
for y in range(GROUP_SIZE):
- if len(s) <= i: n = 0
- else: n = s[i]
+ if len(s) <= i:
+ n = 0
+ else:
+ n = s[i]
try:
n = int(n)
except:
@@ -249,44 +257,45 @@ def sudoku_grid_from_string (s):
class SudokuSolver (SudokuGrid):
"""A SudokuGrid that can solve itself."""
- def __init__ (self, grid=False, verbose=False,group_size=9):
+ def __init__ (self, grid = False, verbose = False, group_size = 9):
self.current_guess = None
- self.initialized=False
- SudokuGrid.__init__(self,grid,verbose=verbose,group_size=group_size)
+ self.initialized = False
+ SudokuGrid.__init__(self, grid, verbose = verbose, group_size = group_size)
self.virgin = SudokuGrid(grid)
self.guesses = GuessList()
self.breadcrumbs = BreadcrumbTrail()
self.backtraces = 0
- self.initialized=True
+ self.initialized = True
self.solved = False
self.trail = []
def auto_fill_for_xy (self, x, y):
"""Fill the square x,y if possible."""
- possible = self.gen_set - self.rows[y] - self.cols[x] - self.boxes[self.box_by_coords[(x,y)]]
+ possible = self.gen_set - self.rows[y] - self.cols[x] - self.boxes[self.box_by_coords[(x, y)]]
changed = []
- if len(possible)==1:
+ if len(possible) == 1:
val = possible.pop()
- self.add(x,y,val)
- return ((x,y),val)
- if len(possible)==0:
+ self.add(x, y, val)
+ return ((x, y), val)
+ if len(possible) == 0:
return -1
# check our column...
- for coord_set,filled_set in [(self.col_coords[x],self.cols[x]),
- (self.row_coords[y],self.rows[y]),
- (self.box_coords[self.box_by_coords[(x,y)]],
- self.boxes[self.box_by_coords[(x,y)]])
+ for coord_set, filled_set in [(self.col_coords[x], self.cols[x]),
+ (self.row_coords[y], self.rows[y]),
+ (self.box_coords[self.box_by_coords[(x, y)]],
+ self.boxes[self.box_by_coords[(x, y)]])
]:
needed_set = self.gen_set - filled_set
for coord in coord_set:
- if self._get_(*coord): continue
- elif (x,y)!=coord:
+ if self._get_(*coord):
+ continue
+ elif (x, y) != coord:
needed_set = needed_set - self.possible_values(*coord)
- if needed_set and len(needed_set)==1:
+ if needed_set and len(needed_set) == 1:
val = needed_set.pop()
if val in possible:
- self.add(x,y,val)
- return ((x,y),val)
+ self.add(x, y, val)
+ return ((x, y), val)
else:
return -1
if len(needed_set)>1:
@@ -294,8 +303,10 @@ class SudokuSolver (SudokuGrid):
def auto_fill (self):
changed = []
- try: changed = self.fill_must_fills()
- except UnsolvablePuzzle: return changed
+ try:
+ changed = self.fill_must_fills()
+ except UnsolvablePuzzle:
+ return changed
try:
changed.extend(self.fill_deterministically())
finally:
@@ -303,11 +314,11 @@ class SudokuSolver (SudokuGrid):
def fill_must_fills (self):
changed = []
- for label,coord_dic,filled_dic in [('Column',self.col_coords,self.cols),
- ('Row',self.row_coords,self.rows),
- ('Box',self.box_coords,self.boxes)]:
- for n,coord_set in coord_dic.items():
- needs = dict([(n,False) for n in range(1,self.group_size+1)])
+ for label, coord_dic, filled_dic in [('Column', self.col_coords, self.cols),
+ ('Row', self.row_coords, self.rows),
+ ('Box', self.box_coords, self.boxes)]:
+ for n, coord_set in coord_dic.items():
+ needs = dict([(n, False) for n in range(1, self.group_size + 1)])
for coord in coord_set:
val = self._get_(*coord)
if val:
@@ -319,48 +330,56 @@ class SudokuSolver (SudokuGrid):
for v in self.possible_values(*coord):
# if we don't yet have a possible number, plug ourselves in
if needs.has_key(v):
- if not needs[v]: needs[v]=coord
- else: del needs[v]
- for n,coords in needs.items():
+ if not needs[v]:
+ needs[v] = coord
+ else:
+ del needs[v]
+ for n, coords in needs.items():
if not coords:
- raise UnsolvablePuzzle('Missing a %s in %s'%(n,label))
+ raise UnsolvablePuzzle('Missing a %s in %s' % (n, label))
else:
try:
- self.add(coords[0],coords[1],n)
- changed.append((coords,n))
+ self.add(coords[0], coords[1], n)
+ changed.append((coords, n))
except AlreadySetError:
raise UnsolvablePuzzle(
- "%s,%s must be two values at once!"%(coords)
+ "%s,%s must be two values at once!" % (coords)
)
return changed
def fill_deterministically (self):
poss = self.calculate_open_squares().items()
- one_choice=filter(lambda x: len(x[1])==1,poss)
+ one_choice = filter(lambda x: len(x[1]) == 1, poss)
retval = []
- for coords,choices in one_choice:
- if self.verbose: print 'Deterministically adding ',coords,choices
+ for coords, choices in one_choice:
+ if self.verbose:
+ print 'Deterministically adding ', coords, choices
val = choices.pop()
- self.add(coords[0],coords[1],val)
- retval.append([(coords[0],coords[1]),val])
- if self.verbose: print 'deterministically returning ',retval
+ self.add(coords[0], coords[1], val)
+ retval.append([(coords[0], coords[1]), val])
+ if self.verbose:
+ print 'deterministically returning ', retval
return retval
def solve (self):
self.auto_fill()
- while not self.guess_least_open_square(): 1
- if self.verbose: print 'Solved!\n', self
+ while not self.guess_least_open_square():
+ pass
+ if self.verbose:
+ print 'Solved!\n', self
self.solved = True
def solution_finder (self):
self.auto_fill()
- while not self.guess_least_open_square(): 1
- self.solved=True
+ while not self.guess_least_open_square():
+ pass
+ self.solved = True
yield tuple([tuple(r) for r in self.grid[0:]])
while self.breadcrumbs:
self.unwrap_guess(self.breadcrumbs[-1])
try:
- while not self.guess_least_open_square(): 1
+ while not self.guess_least_open_square():
+ pass
except UnsolvablePuzzle:
break
else:
@@ -370,19 +389,22 @@ class SudokuSolver (SudokuGrid):
def has_unique_solution (self):
sf = self.solution_finder()
sf.next()
- if sf.next(): return False
- else: return True
+ if sf.next():
+ return False
+ else:
+ return True
def guess_least_open_square (self):
# get open squares and check them
poss = self.calculate_open_squares().items()
# if there are no open squares, we're done!
if not poss:
- if self.verbose: print 'Solved!'
+ if self.verbose:
+ print 'Solved!'
return True
# otherwise, find the possibility with the least possibilities
- poss.sort(lambda a,b: len(a[1])>len(b[1]) and 1 or len(a[1])<len(b[1]) and -1 or \
- a[0]>b[0] and 1 or a[1]<b[1] and -1 or 0)
+ poss.sort(lambda a, b: len(a[1]) > len(b[1]) and 1 or len(a[1]) < len(b[1]) and -1 or \
+ a[0] > b[0] and 1 or a[1] < b[1] and -1 or 0)
least = poss[0]
# remove anything we've already guessed
possible_values = least[1] - self.guesses.guesses_for_coord(*least[0])
@@ -394,22 +416,22 @@ class SudokuSolver (SudokuGrid):
else:
raise UnsolvablePuzzle("Unsolvable %s.\n \
Out of guesses for %s. Already guessed\n \
- %s (other guesses are %s)"%(self,
+ %s (other guesses are %s)" % (self,
least[0],
self.guesses.guesses_for_coord(*least[0]),
self.guesses))
guess = random.choice(list(possible_values))
# Create guess object
- guess_obj = Guess(least[0][0],least[0][1],guess)
+ guess_obj = Guess(least[0][0], least[0][1], guess)
if self.breadcrumbs:
self.breadcrumbs[-1].children.append(guess_obj)
self.current_guess = None #reset (we're tracked via guess.child)
- self.add(least[0][0],least[0][1],guess)
+ self.add(least[0][0], least[0][1], guess)
self.current_guess = guess_obj # (All deterministic additions
# get added to our
# consequences)
self.guesses.append(guess_obj)
- self.trail.append(('+',guess_obj))
+ self.trail.append(('+', guess_obj))
self.breadcrumbs.append(guess_obj)
try:
filled = self.auto_fill()
@@ -423,47 +445,38 @@ class SudokuSolver (SudokuGrid):
return self.guess_least_open_square()
def unwrap_guess (self, guess):
- self.trail.append(('-',guess))
- if self._get_(guess.x,guess.y): self.remove(guess.x,guess.y)
+ self.trail.append(('-', guess))
+ if self._get_(guess.x, guess.y):
+ self.remove(guess.x, guess.y)
for consequence in guess.consequences.keys():
- if self._get_(*consequence): self.remove(*consequence)
+ if self._get_(*consequence):
+ self.remove(*consequence)
for child in guess.children:
self.unwrap_guess(child)
- if child in self.guesses: self.guesses.remove(child)
- if guess in self.breadcrumbs: self.breadcrumbs.remove(guess)
-
- def print_possibilities (self):
- poss = self.calculate_open_squares()
- poss_list = poss.items()
- poss_list.sort(lambda a,b: len(a[1])>len(b[1]) and 1 or len(a[1])<len(b[1]) and -1 or 0)
- most_poss = len(poss_list[-1][1])
- for y in range(len(self.cols)):
- for x in range(len(self.rows)):
- if self.grid[y][x]: val = self.grid[y][x]
- else:
- val="".join([str(s) for s in poss[(x,y)]])
- print self.pad(val,most_poss+2),
- for n in range(most_poss + 2): print
+ if child in self.guesses:
+ self.guesses.remove(child)
+ if guess in self.breadcrumbs:
+ self.breadcrumbs.remove(guess)
def pad (self, n, pad_to):
n = str(n)
padding = int(pad_to) - len(n)
second_half = padding / 2
first_half = second_half + padding % 2
- return " "*first_half + n + " "*second_half
+ return " " * first_half + n + " " * second_half
- def add (self, x,y,val,*args,**kwargs):
+ def add (self, x, y, val, *args, **kwargs):
if self.current_guess:
- self.current_guess.add_consequence(x,y,val)
- SudokuGrid.add(self,x,y,val,*args,**kwargs)
+ self.current_guess.add_consequence(x, y, val)
+ SudokuGrid.add(self, x, y, val, *args, **kwargs)
class InteractiveSudoku (SudokuSolver):
"""A subclass of SudokuSolver that provides some convenience
functions for helping along a human.who is in the midst of
solving."""
- def __init__ (self, grid=False, verbose=False, group_size=9):
- SudokuSolver.__init__(self,grid,verbose,group_size)
+ def __init__ (self, grid = False, verbose = False, group_size = 9):
+ SudokuSolver.__init__(self, grid, verbose, group_size)
def to_string (self):
return self.virgin.to_string() + '\n' + SudokuSolver.to_string(self)
@@ -472,12 +485,12 @@ class InteractiveSudoku (SudokuSolver):
"""Return a list of impossibilities implied by the users actions."""
row_cells = self.row_coords[y]
col_cells = self.col_coords[x]
- box = self.box_by_coords[(x,y)]
+ box = self.box_by_coords[(x, y)]
box_cells = self.box_coords[box]
- for coord_set in [row_cells,col_cells,box_cells]:
+ for coord_set in [row_cells, col_cells, box_cells]:
broken = []
# just work on the open squares
- coord_set = filter(lambda coords: not self._get_(*coords),coord_set)
+ coord_set = filter(lambda coords: not self._get_(*coords), coord_set)
for coords in coord_set:
if not self.possible_values(*coords):
broken.append(coords)
@@ -485,15 +498,15 @@ class InteractiveSudoku (SudokuSolver):
def check_for_completeness (self):
for r in self.rows:
- if len(r)!=self.group_size:
+ if len(r) != self.group_size:
return False
for c in self.cols:
- if len(c)!=self.group_size:
+ if len(c) != self.group_size:
return False
return True
def is_changed (self):
- return (self.grid!=self.virgin.grid)
+ return (self.grid != self.virgin.grid)
class DifficultyRating:
@@ -502,17 +515,17 @@ class DifficultyRating:
medium = _('Medium')
easy = _('Easy')
- very_hard_range = (0.75,10)
- hard_range = (0.6,0.75)
- medium_range = (0.45,0.6)
- easy_range = (-10,0.45)
+ very_hard_range = (0.75, 10)
+ hard_range = (0.6, 0.75)
+ medium_range = (0.45, 0.6)
+ easy_range = (-10, 0.45)
categories = {'very hard':very_hard_range,
'hard':hard_range,
'medium':medium_range,
'easy':easy_range}
- ordered_categories = ['easy','medium','hard','very hard']
+ ordered_categories = ['easy', 'medium', 'hard', 'very hard']
label_by_cat = {'easy':easy,
'medium':medium,
'hard':hard,
@@ -538,9 +551,9 @@ class DifficultyRating:
else:
self.instant_elimination_fillable = 0.0
- self.proportion_instant_elimination_fillable = self.instant_elimination_fillable/self.squares_filled
+ self.proportion_instant_elimination_fillable = self.instant_elimination_fillable / self.squares_filled
# some more numbers that may be crazy...
- self.proportion_instant_fill_fillable = self.instant_fill_fillable/self.squares_filled
+ self.proportion_instant_fill_fillable = self.instant_fill_fillable / self.squares_filled
self.elimination_ease = add_with_diminishing_importance(
self.count_values(self.elimination_fillables)
)
@@ -550,51 +563,60 @@ class DifficultyRating:
self.value = self.calculate()
def count_values (self, dct):
- kk=dct.keys()
+ kk = dct.keys()
kk.sort()
return [len(dct[k]) for k in kk]
def calculate (self):
- return 1 - float(self.fillable_ease)/self.squares_filled \
- - float(self.elimination_ease)/self.squares_filled \
- + len(self.guesses)/self.squares_filled \
- + self.backtraces/self.squares_filled
+ return 1 - float(self.fillable_ease) / self.squares_filled \
+ - float(self.elimination_ease) / self.squares_filled \
+ + len(self.guesses) / self.squares_filled \
+ + self.backtraces / self.squares_filled
- def __repr__ (self): return '<DifficultyRating %s>'%self.value
+ def __repr__ (self):
+ return '<DifficultyRating %s>' % self.value
def pretty_print (self):
- for name,stat in [('Number of moves instantly fillable by elimination',
+ for name, stat in [('Number of moves instantly fillable by elimination',
self.instant_elimination_fillable),
('Percentage of moves instantly fillable by elimination',
- self.proportion_instant_elimination_fillable*100),
+ self.proportion_instant_elimination_fillable * 100),
('Number of moves instantly fillable by filling',
self.instant_fill_fillable),
('Percentage of moves instantly fillable by filling',
- self.proportion_instant_fill_fillable*100),
+ self.proportion_instant_fill_fillable * 100),
('Number of guesses made',
len(self.guesses)),
('Number of backtraces', self.backtraces),
- ('Ease by filling',self.fillable_ease),
- ('Ease by elimination',self.elimination_ease),
- ('Calculated difficulty',self.value)
+ ('Ease by filling', self.fillable_ease),
+ ('Ease by elimination', self.elimination_ease),
+ ('Calculated difficulty', self.value)
]:
- print name,': ',stat
+ print name, ': ', stat
def value_string (self):
- if self.value > self.very_hard_range[0]: return _(self.very_hard)
- elif self.value > self.hard_range[0]: return _(self.hard)
- elif self.value > self.medium_range[0]: return _(self.medium)
- else: return _(self.easy)
+ if self.value > self.very_hard_range[0]:
+ return _(self.very_hard)
+ elif self.value > self.hard_range[0]:
+ return _(self.hard)
+ elif self.value > self.medium_range[0]:
+ return _(self.medium)
+ else:
+ return _(self.easy)
def value_category (self):
"""Get category string, without i18n or capitalization
For use in categorizing category.
"""
- if self.value > self.very_hard_range[0]: return 'very hard'
- elif self.value > self.hard_range[0]: return 'hard'
- elif self.value > self.medium_range[0]: return 'medium'
- else: return 'easy'
+ if self.value > self.very_hard_range[0]:
+ return 'very hard'
+ elif self.value > self.hard_range[0]:
+ return 'hard'
+ elif self.value > self.medium_range[0]:
+ return 'medium'
+ else:
+ return 'easy'
def get_difficulty_category_name (diff_float):
return DifficultyRating.label_by_cat.get(
@@ -603,14 +625,14 @@ def get_difficulty_category_name (diff_float):
)
def get_difficulty_category (diff_float):
- for category,range in DifficultyRating.categories.items():
+ for category, range in DifficultyRating.categories.items():
if range[0] <= diff_float < range[1]:
return category
class SudokuRater (SudokuSolver):
- def __init__ (self, grid=False, verbose=False, group_size=9):
- self.initialized=False
+ def __init__ (self, grid = False, verbose = False, group_size = 9):
+ self.initialized = False
self.guessing = False
self.fake_add = False
self.fake_additions = []
@@ -618,21 +640,21 @@ class SudokuRater (SudokuSolver):
self.fill_must_fillables = {}
self.elimination_fillables = {}
self.tier = 0
- SudokuSolver.__init__(self,grid,verbose,group_size)
+ SudokuSolver.__init__(self, grid, verbose, group_size)
- def add (self,*args,**kwargs):
+ def add (self, *args, **kwargs):
if not self.fake_add:
if self.initialized and not self.guessing:
self.scan_fillables()
for delayed_args in self.add_me_queue:
- coords = (delayed_args[0],delayed_args[1])
+ coords = (delayed_args[0], delayed_args[1])
if not self._get_(*coords):
- SudokuSolver.add(self,*delayed_args)
- if not self._get_(args[0],args[1]):
- SudokuSolver.add(self,*args)
+ SudokuSolver.add(self, *delayed_args)
+ if not self._get_(args[0], args[1]):
+ SudokuSolver.add(self, *args)
self.tier += 1
else:
- SudokuSolver.add(self,*args,**kwargs)
+ SudokuSolver.add(self, *args, **kwargs)
else:
self.fake_additions.append(args)
@@ -645,15 +667,15 @@ class SudokuRater (SudokuSolver):
self.fill_must_fills()
except:
pass
- self.fill_must_fillables[self.tier]=set(self.fake_additions[:])-self.filled
+ self.fill_must_fillables[self.tier] = set(self.fake_additions[:]) - self.filled
self.add_me_queue = self.fake_additions[:]
self.fake_additions = []
try:
self.fill_deterministically()
except:
pass
- self.elimination_fillables[self.tier] = set(self.fake_additions[:])-self.filled
- self.filled = self.filled|self.fill_must_fillables[self.tier]|self.elimination_fillables[self.tier]
+ self.elimination_fillables[self.tier] = set(self.fake_additions[:]) - self.filled
+ self.filled = self.filled | self.fill_must_fillables[self.tier] | self.elimination_fillables[self.tier]
self.add_me_queue.extend(self.fake_additions[:])
self.fake_add = False
@@ -662,13 +684,14 @@ class SudokuRater (SudokuSolver):
return SudokuSolver.guess_least_open_square(self)
def difficulty (self):
- if not self.solved: self.solve()
+ if not self.solved:
+ self.solve()
self.clues = 0
# Add up the number of our initial clues through some nifty mapping calls
- map(lambda r: map(lambda i: setattr(self,'clues',self.clues.__add__(i and 1 or 0)),
+ map(lambda r: map(lambda i: setattr(self, 'clues', self.clues.__add__(i and 1 or 0)),
r),
self.virgin.grid)
- self.numbers_added = self.group_size**2 - self.clues
+ self.numbers_added = self.group_size ** 2 - self.clues
rating = DifficultyRating(self.fill_must_fillables,
self.elimination_fillables,
self.guesses,
@@ -678,12 +701,12 @@ class SudokuRater (SudokuSolver):
class GuessList (list):
- def __init__ (self,*guesses):
- list.__init__(self,*guesses)
+ def __init__ (self, *guesses):
+ list.__init__(self, *guesses)
- def guesses_for_coord (self,x,y):
- return set([guess.val for guess in filter(lambda guess: guess.x==x and guess.y==y,self)])
+ def guesses_for_coord (self, x, y):
+ return set([guess.val for guess in filter(lambda guess: guess.x == x and guess.y == y, self)])
def remove_children (self, guess):
removed = []
@@ -696,10 +719,10 @@ class GuessList (list):
def remove_guesses_for_coord (self, x, y):
nuking = False
nuked = []
- for i in range(len(self)-1):
- g = self[i-len(nuked)]
- if g.x==x and g.y == y:
- nuking=True
+ for i in range(len(self) - 1):
+ g = self[i - len(nuked)]
+ if g.x == x and g.y == y:
+ nuking = True
if nuking:
self.remove(g)
nuked += [g]
@@ -708,10 +731,10 @@ class GuessList (list):
class BreadcrumbTrail (GuessList):
def append (self, guess):
# Raise an error if we add something to ourselves twice
- if self.guesses_for_coord(guess.x,guess.y):
- raise ValueError("We already have crumbs on %s,%s"%(guess.x,guess.y))
+ if self.guesses_for_coord(guess.x, guess.y):
+ raise ValueError("We already have crumbs on %s, %s" % (guess.x, guess.y))
else:
- list.append(self,guess)
+ list.append(self, guess)
class Guess:
def __init__ (self, x, y, val):
@@ -722,20 +745,20 @@ class Guess:
self.consequences = {}
def add_consequence (self, x, y, val):
- self.consequences[(x,y)]=val
+ self.consequences[(x, y)] = val
def __repr__ (self):
- s = "<Guess (%s,%s)=%s"%(self.x,self.y,self.val)
+ s = "<Guess (%s, %s)=%s" % (self.x, self.y, self.val)
if self.consequences:
s += " implies: "
- s += ", ".join(["%s->%s"%(k,v) for k,v in self.consequences.items()])
+ s += ", ".join(["%s->%s" % (k, v) for k, v in self.consequences.items()])
s += ">"
return s
-def add_with_diminishing_importance (lst, diminish_by=lambda x: x+1):
+def add_with_diminishing_importance (lst, diminish_by = lambda x: x + 1):
sum = 0
- for i,n in enumerate(lst):
+ for i, n in enumerate(lst):
sum += float(n) / diminish_by(i)
return sum
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]