You are on page 1of 21

Projects

 5  and  6:  
Sudoku  
Part  1:    Constraint  propaga8on  
Part  2:  Back-­‐track  search  
(recursive  guess-­‐and-­‐check)  

• CIS 211
Sudoku  

Each  row,  column,  and  3x3  sub-­‐square  must  contain  each  of  the  digits  1..9  

• CIS 211
Two  part  project:    
Part  1  (due  Monday):    
 Constraint  propaga8on  to  solve  simple  puzzles  
and  recognize  correct  solu8ons  
     “Naked  single”  and  “hidden  single”  tac8cs  

Part  2  (one  week  later):  


 Search  for  a  solu8on  to  harder  puzzles  
 Depth-­‐first  recursive  search  with  back-­‐tracking  

• CIS 211
Check  &  Help  
Is  board  ok  so  far?        
 Check  uniqueness  of  symbols  in  each  row,  
column,  and  block  (ignoring  unfilled  cells)  

Help  with  unfilled  (“.”)  cells:    


 Allowed  symbols  in  a  8le  is  intersec8on  of  
     symbols  not  yet  used  in  row  
     symbols  not  yet  used  in  column  
     symbols  not  yet  used  in  square  
Two  tac8cs:    Naked  single,  hidden  single  
• CIS 211
Sudoku  help:  Par7al  boards  
We  will  use  the  “sadman  sudoku”  format:    
 “.”  marks  a  posi8on  that  has  not  been  chosen    

See  
hZp://www.sadmanso\ware.com/sudoku/
faq19.htm  

(We  will  use  the  minimal  puzzle  format.)  

• CIS 211
We  can  find  standard  solu7on  tac7cs  on  the  web  ...    

...  and  translate  to  design,  


then    pseudocode,  then  
code.  

• CIS 211
“Naked  single”  (aka  “sole  candidate”)  
Human  tac8c:      
 Start  with  9  candidates  in  each  cell  
 Cross  off  candidates  used  in  the  row,  column,  and  block  
 If  there  is  only  one  candidate  le\  in  a  cell,  choose  it  
Program  tac8c:  
 Each  cell  has  a  “candidates”  aZribute,  a  Python  set  
 For  each  row,  column,  and  block  
 Loop  through  the  group  to  find  used  symbols  
 Loop  again  to  remove  used  symbols  from  “possible”  
 If  len(possible)  is  1,  choose  that  symbol  

• CIS 211
. . . . . . . . .
. . . . . . . 1 .
. . . . . . . . .
. . . . . . 9 . .
. 2 . . 5 . . . 3
. . . . . . 7 . 8
. . . . . . . . .
. . . . . . . 4 .
. . . . . . . . .

Candidates
1 2 3 4 5 6 7 8 9

• CIS 211
. . . . . . . . .
. . . . . . . 1 .
. . . . . . . . .
. . . . . . 9 . .
. 2 . . 5 . . . 3
. . . . . . 7 . 8
. . . . . . . . .
. . . . . . . 4 .
. . . . . . . . .

Candidates
1 x2 x3 4 x
5 6 7 8 9

• CIS 211
. . . . . . . . .
. . . . . . . 1 .
. . . . . . . . .
. . . . . . 9 . .
. 2 . . 5 . . . 3
. . . . . . 7 . 8
. . . . . . . . .
. . . . . . . 4 .
. . . . . . . . .

Candidates
x
1 x
2 x 4 x
3 x 5 6 7 8 9
• CIS 211
. . . . . . . . .
. . . . . . . 1 .
. . . . . . . . .
. . . . . . 9 . .
. 2 . . 5 . . . 3
. . . . . . 7 . 8
. . . . . . . . .
. . . . . . . 4 .
. . . . . . . . .

Candidates
x
1 x
2 x 4 x
3 x 5 6 x7 x8 x
9
• CIS 211
. . . . . . . . .
. . . . . . . 1 .
. . . . . . . . .
. . . . . . 9 . .
. 2 . . 5 . . 6 3
. . . . . . 7 . 8
. . . . . . . . .
. . . . . . . 4 .
. . . . . . . . .

Candidates
x
1 x
2 x 4 x
3 x 5 6 x7 x8 x
9
• CIS 211
Keeping  an  invariant  
It  helps  to  establish  an  object  invariant:  

At  all  8mes,  the  Tile.candidates  includes  all  possible  


choices  for  the  Tile  object  
Tile.candidates  may  become  smaller  (lose  elements)  
when  we  discover  constraints,  but  it  never  becomes  
larger  during  constraint  propaga8on  
If  8le.candidates  has  only  one  element,  then  
8le.symbol  is  that  element  
Every  method  and  func8on  
maintains  the  invariant*  
• CIS 211 (*for  now  …  un8l  we  do  back-­‐track  search)  
Pseudocode:    Maintain  invariant  while  
reducing  the  “candidates”  sets  

Program  tac8c:  “naked  single”  or  “sole  candidate”  


 Each  Tile  has  a  “candidates”  aZribute,  a  Python  set  
 For  each  row,  column,  and  block  
 Loop  through  the  group  to  find  used  symbols  
 Loop  again  to  remove  used  symbols  from  “possible”  
 If  len(possible)  is  1,  choose  that  symbol  

• CIS 211
I  want  to  avoid  wri8ng  the  “check  unique  entries”  code  three  8mes  
     Once  looping  through  elements  in  a  row  
     Once  looping  through  elements  in  a  column  
     Once  looping  through  elements  in  a  square  

DRY:    “Don’t  Repeat  Yourself”  

How  can  I  factor  that  code  out?    

• CIS 211
I  want  to  avoid  wri8ng  the  “check  unique  entries”  code  three  
8mes  
     Once  looping  through  elements  in  a  row  
     Once  looping  through  elements  in  a  column  
     Once  looping  through  elements  in  a  square  

DRY:    “Don’t  Repeat  Yourself”  

How  can  I  factor  that  code  out?    

Write  it  just  once,  for  a  list  of  9  elements  

Board  provides  the  same  "les  in  different  lists,  by  row,  column,  
and  square  

• CIS 211
9 8 7 6 5 4 3 2 9 groups
2 4 6 1 7 3 9 8 5
3 5 1 9 2 8 7 4 6
1 2 8 5 3 7 6 9 4
6 3 4 8 9 2 1 5 7
5 1 9 2 8 6 4 7 3
7 9 5 4 6 1 8 3 2
4 7 2 3 1 9 5 6 8
8 6 3 7 4 5 2 1 9

Board  contains  only  one  copy  of  each  7le,    


but  each  7le  appears  in  three  different  
groups.  
Tile
Each  group  is  actually  a  Group  object,     row: 4
with  methods  for  constraint  propaga7on   col: 7
value: ‘5’
• CIS 211
candidates: { ‘5’ }
Hidden  single  tac7c  

A  2  has  got  to  go  somewhere  


in  that  middle  block.    
Can’t  go  in  first  column.  
Can’t  go  in  third  column.    
Must  go  in  the  only  place  it  
can.  

Let’s  turn  this  into  design  


and  pseudocode  
hRp://www.sadmansoTware.com/sudoku/
(Trickier  than  naked  single,     hiddensingle.htm  
and  works  only  in  combina8on  with    
reduc8on  of  candidates  sets  in  naked  single.)  

• CIS 211
Hidden  single  (pseudocode)  

LEFTOVERS  =    {  CHOICES  }  
for  8le  in  group:     Notes:    
             LEFTOVERS  -­‐=  {  8le.value}     In  Python,  an  empty  set  is  created  by  
set(),  and  a  set  containing  items  in  a  
for  value  in  LEFTOVERS:   list  li  is  created  as  set(  li  ).    Curly  braces  
           places  to  put  value  =  [    ]   are  not  used  because  curly  braces  
indicate  a  dict    (and  dicts  came  first;  
           for  8le  in  group:     sets  are  a  newer  feature  in  Python).  A  
                         can  value  go  in  8le?   set  containing  a  single  element  x  
                         if  it  can  go  there,     would  be  set([x]),  that  is,  the  set  
                                   add  to  places  to  put  value   containing  the  elements  in  a  list  that  
just  contains  x.    
         if  len(places  to  put  value)  ==  1:  
                   put  the  value  there!     “can  value  go  in  8le”  is  actually  a  
method  in  the  Tile  object,  although  it  
has  a  shorter  name.      

“put  the  value  there”  is  also  a  method  


of  Tile,  also  with  a  shorter  name.    

• CIS 211
sudoku

Code  
sdk_solver

organiza7on  
 (model  part)   sdk_board Board
tiles
groups

sdk_group
Group
tiles
naked_single_constrain
hidden_single_constrain

not  shown:    main  graphical  


sdk_tile
view  in  sdk_display.py,    
addi8onal  text  view  in   row
Tile

sdk_debugview.py,    MVC   col


value
plumbing  in  events.py   candidates
eliminate(Set[str])

• CIS 211
test_sdk sudoku

sdk_solver sdk_io

And  of  course  a  


test  suite  …   sdk_board Board
tiles
groups

sdk_group
Group
tiles
naked_single_constrain
hidden_single_constrain

sdk_tile
Tile
row
col
value
candidates
eliminate(Set[str])

• CIS 211

You might also like