github.com/joshprzybyszewski/masyu@v0.0.0-20230508015604-f31a025f6e7e/solve/crossings.go (about) 1 package solve 2 3 import ( 4 "github.com/joshprzybyszewski/masyu/model" 5 ) 6 7 type crossings struct { 8 // [col]numLines/AvoidsInThatCol 9 cols [maxPinsPerLine]model.Dimension 10 colsAvoid [maxPinsPerLine]model.Dimension 11 12 // [row]numLines/AvoidsInThatRow 13 rows [maxPinsPerLine]model.Dimension 14 rowsAvoid [maxPinsPerLine]model.Dimension 15 16 // This is the "target" for an _almost_ empty row/col 17 target model.Dimension 18 } 19 20 func newCrossings( 21 size model.Size, 22 ) crossings { 23 return crossings{ 24 target: model.Dimension(size) - 1, 25 } 26 } 27 28 func (c *crossings) lineHor( 29 col model.Dimension, 30 s *state, 31 ) { 32 if col == 0 { 33 return 34 } 35 c.cols[col]++ 36 if c.colsAvoid[col]+c.cols[col] == c.target { 37 c.completeCol(col, s) 38 } 39 40 } 41 42 func (c *crossings) avoidHor( 43 col model.Dimension, 44 s *state, 45 ) { 46 if col == 0 { 47 return 48 } 49 c.colsAvoid[col]++ 50 if c.colsAvoid[col]+c.cols[col] == c.target { 51 c.completeCol(col, s) 52 } 53 } 54 55 func (c *crossings) completeCol( 56 col model.Dimension, 57 s *state, 58 ) { 59 row := getEmptyCrossingInColumn(s, col) 60 if c.cols[col]%2 == 0 { 61 s.avoidHor(row, col) 62 } else { 63 s.lineHor(row, col) 64 } 65 } 66 67 func (c *crossings) lineVer( 68 row model.Dimension, 69 s *state, 70 ) { 71 if row == 0 { 72 return 73 } 74 c.rows[row]++ 75 if c.rowsAvoid[row]+c.rows[row] == c.target { 76 c.completeRow(row, s) 77 } 78 } 79 80 func (c *crossings) avoidVer( 81 row model.Dimension, 82 s *state, 83 ) { 84 if row == 0 { 85 return 86 } 87 c.rowsAvoid[row]++ 88 if c.rowsAvoid[row]+c.rows[row] == c.target { 89 c.completeRow(row, s) 90 } 91 } 92 93 func (c *crossings) completeRow( 94 row model.Dimension, 95 s *state, 96 ) { 97 col := getEmptyCrossingInRow(s, row) 98 if c.rows[row]%2 == 0 { 99 s.avoidVer(row, col) 100 } else { 101 s.lineVer(row, col) 102 } 103 } 104 105 func getEmptyCrossingInColumn( 106 s *state, 107 col model.Dimension, 108 ) model.Dimension { 109 for row := model.Dimension(1); row <= model.Dimension(s.size); row++ { 110 if !s.hasHorDefined(row, col) { 111 return row 112 } 113 } 114 return 0 115 } 116 117 func getEmptyCrossingInRow( 118 s *state, 119 row model.Dimension, 120 ) model.Dimension { 121 for col := model.Dimension(1); col <= model.Dimension(s.size); col++ { 122 if !s.hasVerDefined(row, col) { 123 return col 124 } 125 } 126 return 0 127 }