Advertisement
Guest User

Untitled

a guest
Jun 25th, 2017
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.71 KB | None | 0 0
  1. /* By Peter Klein and Bryan Watts"
  2. /*
  3.     Implements a concurrent Sudoku solver.
  4.  
  5.     A full Sudoku grid is called a board.  Each small square that may
  6.     contain a single number is called a cell.  We refer to the number of
  7.     cells along one side of the board as its size.  For a board of size
  8.     n, it's divided into n n matrices of size sqrt(n).
  9.  
  10.     A board is valid if none of its rows, columns, or matrices contain
  11.     duplicate values.  Cells in a valid board may, however, be blank.
  12.  
  13.     A board is solved if it is valid and has no blanks.
  14.  
  15.     by Curtis Clifton
  16.     Oct 29, 2010
  17. */
  18. package sudoku
  19.  
  20. import "fmt"
  21.  
  22. // Size is the number of cells across the full Sudoku board.
  23. const (
  24.     // implementation of parsing and display don't handle Size > 3
  25.     RootOfSize = 3
  26.     Size = RootOfSize * RootOfSize
  27. )
  28.  
  29. // repeat constructs a string by concatenating count instances of the string s.
  30. func repeat(s string, count int) string {
  31.     r := ""
  32.     for i:=0; i<count ; i++ {
  33.         r += s
  34.     }
  35.     return r
  36. }
  37.  
  38. // Punctuation is used to divide a board into matrices for printing.
  39. var (
  40.     verticalLine = "|"
  41.     horizontalLine = repeat("-", Size + RootOfSize - 1)  + "\n"
  42. )
  43.  
  44. // -----------------------------------------------------------------------------
  45.  
  46. // BitSet is an efficient set representation.  Valid set elements are integers
  47. // between 1 and 16 inclusively.
  48. type BitSet uint16
  49.  
  50. // Add adds the given value to the set, returning true if the value was not
  51. // already in the set.
  52. func (s *BitSet) Add(v int) (wasNew bool) {
  53.     var mask uint16 = 1 << uint16(v-1)
  54.     var ptr *uint16 = (*uint16)(s)
  55.     if *ptr & mask != 0 {
  56.     return false
  57.     }
  58.     *ptr |= mask
  59.     return true
  60. }
  61.  
  62. // Clear empties the given set.
  63. func (s *BitSet) Clear() {
  64.     *s = 0
  65. }
  66.  
  67. // Remove removes the given value from the set.
  68. func (s *BitSet) Remove(v int) {
  69.     var mask uint16 = 1 << uint16(v-1)
  70.     var ptr *uint16 = (*uint16)(s)
  71.     *ptr &^= mask
  72. }
  73.  
  74. // Contain checks whether the given value is in the set.
  75. func (s *BitSet) Contains(v int) bool {
  76.     var mask uint16 = 1 << uint16(v-1)
  77.     var ptr *uint16 = (*uint16)(s)
  78.     return *ptr & mask != 0
  79. }
  80.  
  81. func (s *BitSet) String() string {
  82.     r := "{ "
  83.     v := uint16(*s)
  84.     for i:= 1; i <= Size; i, v = i + 1, v >> 1 {
  85.         if uint16(1) & v != 0 {
  86.             r += fmt.Sprint(i, " ")
  87.         }
  88.     }
  89.     r += "}"
  90.     return r
  91. }
  92.  
  93. // -----------------------------------------------------------------------------
  94.  
  95. // Board represents a Sudoku board.
  96. type Board struct {
  97.     backingSlice []int
  98. }
  99.  
  100. // index converts row and column values--zero-based--into an index into a
  101. // board's backingSlice.
  102. func index(r, c int) int {
  103.     return r * Size + c
  104. }
  105.  
  106. // coord converts an index into a board's backingSlice into row and
  107. // column values--zero-based.
  108. func coord(index int) (r, c int) {
  109.     c = index % Size
  110.     r = index / Size
  111.     return
  112. }
  113.  
  114. // Parse takes a string representing a Sudoku board and returns a Board.
  115. // The representation should use digits between 1 and Size, inclusive, to
  116. // indicate filled cells.  Blank cells are indicate by an underscore.  Rows
  117. // in the representation should be separated by newlines.
  118. func Parse(bs string) (b *Board, ok bool)  {
  119.     ok = true
  120.     rep := make([]int, Size*Size)
  121.     next := 0
  122.     for _, v := range bs {
  123.         switch {
  124.             case '0' < v && v <= '0' + Size:
  125.                 rep[next] = v - '0'
  126.                 next++
  127.             case v == '_':
  128.                 rep[next] = 0
  129.                 next++
  130.             case v == '\n':
  131.                 // ignore
  132.             default:
  133.                 ok = false
  134.         }
  135.     }
  136.     return &Board{rep}, ok
  137. }
  138.  
  139. // EmptyBoard returns a new, empty board where every cell is blank.
  140. func EmptyBoard() *Board {
  141.     return &Board{make([]int, Size*Size)}
  142. }
  143.  
  144. // Copy makes a deep copy of the board so that the original board and the new
  145. // board have no shared memory.
  146. func (b *Board) Copy() *Board {
  147.     newBack := make([]int, Size*Size)
  148.     copy(newBack, b.backingSlice)
  149.     return &Board{newBack}
  150. }
  151.  
  152. // at returns the value in the cell at the given row and column.  Zero
  153. // indicates a blank cell.
  154. func (b *Board) at(r, c int) int {
  155.     return b.backingSlice[index(r,c)]
  156. }
  157.  
  158. // set sets the value for the cell at the given row and column.  Zero
  159. // indicates a blank cell.
  160. func (b *Board) set(r, c, val int) {
  161.     b.backingSlice[index(r,c)] = val
  162. }
  163.  
  164. // String returns a human-readable representation of the board, with
  165. // punctuation to divide the board into matrices.
  166. func (b *Board) String() string {
  167.     s := ""
  168.     for r := 0; r < Size; r++ {
  169.         if r != 0 && r % RootOfSize == 0 {
  170.             s += horizontalLine
  171.         }
  172.         for c := 0; c < Size; c++ {
  173.             if c != 0 && c % RootOfSize == 0 {
  174.                 s += verticalLine
  175.             }
  176.             switch v := b.at(r,c); v {
  177.                 case 0:
  178.                     s += " "
  179.                 default:
  180.                     s += fmt.Sprint(b.at(r,c))
  181.             }
  182.         }
  183.         if r != Size -1 {
  184.             s += "\n"
  185.         }
  186.     }
  187.     return s
  188. }
  189.  
  190. // IsFull returns true iff every cell of the board has a value; otherwise,
  191. // it returns the coordinates of the first blank cell in scan-line order.
  192. func (b *Board) IsFull() (full bool, r, c int) {
  193.     for r:= 0; r < Size; r++ {
  194.         for c:= 0; c < Size; c++ {
  195.             if b.at(r,c) == 0{
  196.                 return false, r, c
  197.             }
  198.         }
  199.     }
  200.     return true, 0, 0
  201. }
  202.  
  203. // IsValid returns true iff every row, column, and matrix is free of
  204. // duplicates.  A valid board may contain blanks.
  205. func (b *Board) IsValid() bool {
  206.     for x := 0; x < Size; x++{
  207.         var bsr BitSet// := make([]int,10)
  208.         var bsc BitSet//checkc := make([]int,10)
  209.         var bss BitSet//checks := make([]int,10)
  210.         for y:= 0; y < Size; y++ {
  211.             //Rows
  212.             rv := b.at(x,y)
  213.             if rv > 0{
  214.                 if bsr.Contains(rv){//checkr[cr] != 0{
  215.                     return false
  216.                 } else {
  217.                     bsr.Add(rv)//checkr[cr] = 1
  218.                 }
  219.             }
  220.             //Cols
  221.             cv := b.at(y,x)
  222.             if cv > 0{
  223.                 if bsc.Contains(cv) {
  224.                     return false
  225.                 } else {
  226.                     bsc.Add(cv)
  227.                 }
  228.             }
  229.             //Squares
  230.             sv := b.at(3*(x/3)+(y/3),3*(x%3)+(y%3))
  231.             if sv > 0{
  232.                 if bss.Contains(sv) {
  233.                     return false
  234.                 } else {
  235.                     bss.Add(sv)
  236.                 }
  237.             }
  238.         }
  239.  
  240.     }
  241.     return true
  242. }
  243.  
  244. // ValidGuesses calculates what values could be legally placed in the cell at
  245. // the given row and column, based on the rest of that cell's row, column, and
  246. // matrix.
  247. func (b *Board) ValidGuesses(r, c int) BitSet {
  248.     var s BitSet
  249.     for i := 1; i <= Size; i++ {
  250.         s.Add(i)
  251.     }
  252.     for i := 0; i < Size; i++ {
  253.         s.Remove(b.at(r,i))
  254.         s.Remove(b.at(i,c))
  255.         s.Remove(b.at(3*(r/3)+i/3,3*(c/3)+i%3))
  256.     }
  257.     return s
  258. }
  259.  
  260. // Solve takes a Sudoku board and either solves it or reports that it cannot
  261. // be solved.  This version solves the puzzle with recursion, but not
  262. // using concurrency.
  263. func (b *Board) Solve() (result *Board, success bool) {
  264.     full,r,c := b.IsFull()
  265.     if full {
  266.         return b.Copy(), b.IsValid();
  267.     }
  268.     s := b.ValidGuesses(r,c)
  269.     for i := 1; i <= Size; i++ {
  270.         if s.Contains(i) {
  271.             b.set(r,c,i)
  272.             bs,solved := b.Solve()
  273.             if solved { return bs, solved }
  274.             b.set(r,c,0)
  275.         }
  276.     }
  277.     return EmptyBoard(), false
  278. }
  279.  
  280. const (
  281.     SOLVED = -1
  282. )
  283.  
  284.  
  285. // ConcSolve takes a Sudoku board and either solves it or reports that it cannot
  286. // be solved.  This version solves the puzzle using concurrency.
  287. func (b *Board) ConcSolve() (result *Board, success bool) {
  288.     solution := make(chan *Board,1)
  289.     status := make(chan int)
  290.     b.ConcHelper(solution, status)
  291.     grcount := 1
  292.     for {
  293.         s := <-status
  294.         switch {
  295.             case s > 0:
  296.                 grcount += s // Number in channel will be number of processes spawned
  297.                 grcount -= 1 // Subtract one since it sends this number when it's done
  298.             case s == SOLVED:
  299.                 return <-solution, true
  300.         }
  301.         if grcount == 0 {
  302.             return EmptyBoard(), false
  303.         }
  304.     }
  305.     return EmptyBoard(), false
  306. }
  307.  
  308. func (b *Board) ConcHelper(solution chan *Board, status chan int) {
  309.     go func() {
  310.         full,r,c := b.IsFull()
  311.         if full {
  312.             if b.IsValid() {
  313.                 status <- SOLVED
  314.                 solution <- b.Copy()
  315.             } else {
  316.                 status <- 0
  317.             }
  318.         } else {
  319.             calls := 0
  320.             s := b.ValidGuesses(r,c)
  321.             for i := 1; i <= Size; i++ {
  322.                 if s.Contains(i) {
  323.                     calls += 1
  324.                     b.set(r,c,i)
  325.                     b.Copy().ConcHelper(solution, status)
  326.                     b.set(r,c,0)
  327.                 }
  328.             }
  329.             status <- calls
  330.         }
  331.     } ()
  332. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement