Skip to content

Commit 440b932

Browse files
committed
working day20b solution!!!
1 parent 439070a commit 440b932

File tree

1 file changed

+173
-132
lines changed

1 file changed

+173
-132
lines changed

2020/day20.go

Lines changed: 173 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@ import (
99
)
1010

1111
var inputFile = flag.String("inputFile", "inputs/day20.input", "Relative file path to use as input.")
12-
var debug = flag.Bool("debug", false, "Whether to print debug output along the way.")
13-
14-
var SeaMonster = strings.Split(` #
15-
# ## ## ###
16-
# # # # # # `, "\n")
1712

1813
type Tile [10][10]bool
1914
type Edge uint16
@@ -25,71 +20,6 @@ const (
2520
LEFT
2621
)
2722

28-
type Cropped [8][8]bool
29-
30-
// This is assumed to be pre-rotated/flipped.
31-
type Mosaic [][]Tile
32-
33-
func (m Mosaic) PixelAtCoord(r, c int) bool {
34-
mosaicRow := r / 8
35-
mosaicCol := c / 8
36-
cropped := m[mosaicRow][mosaicCol].Crop()
37-
row := r % 8
38-
col := c % 8
39-
return cropped[row][col]
40-
}
41-
42-
func (m Mosaic) FlipX() Mosaic {
43-
var ret Mosaic
44-
for r := range m {
45-
var row []Tile
46-
for c := range m[r] {
47-
row = append(row, m[len(m)-1-r][c].FlipX())
48-
}
49-
ret = append(ret, row)
50-
}
51-
return ret
52-
}
53-
54-
func (m Mosaic) RotCW() Mosaic {
55-
var ret Mosaic
56-
for r := range m {
57-
var row []Tile
58-
for c := range m[r] {
59-
row = append(row, m[len(m[0])-1-c][r].RotCW())
60-
}
61-
ret = append(ret, row)
62-
}
63-
return ret
64-
}
65-
66-
func (m Mosaic) MonsterTopLeftCoord(r, c int) bool {
67-
for rOffset, row := range SeaMonster {
68-
for cOffset, char := range row {
69-
if char != '#' {
70-
continue
71-
}
72-
if !m.PixelAtCoord(r+rOffset, c+cOffset) {
73-
return false
74-
}
75-
}
76-
}
77-
return true
78-
}
79-
80-
func (m Mosaic) FindMonsters() int {
81-
// Find the sea monster.
82-
var monstersFound int
83-
for r := 0; r+len(SeaMonster) < 8*len(m); r++ {
84-
for c := 0; c+len(SeaMonster[0]) < 8*len(m[0]); c++ {
85-
if m.MonsterTopLeftCoord(r, c) {
86-
monstersFound++
87-
}
88-
}
89-
}
90-
return monstersFound
91-
}
92-
9323
func (t Tile) Crop() Cropped {
9424
var ret Cropped
9525
for r := 1; r < 9; r++ {
@@ -165,6 +95,174 @@ func (e Edge) Flip() Edge {
16595
return ret
16696
}
16797

98+
type Cropped [8][8]bool
99+
100+
// This is assumed to be pre-rotated/flipped.
101+
type Mosaic [][]Tile
102+
103+
func (m Mosaic) PixelAtCoord(r, c int) bool {
104+
mosaicRow := r / 8
105+
mosaicCol := c / 8
106+
cropped := m[mosaicRow][mosaicCol].Crop()
107+
row := r % 8
108+
col := c % 8
109+
return cropped[row][col]
110+
}
111+
112+
func (m Mosaic) FlipX() Mosaic {
113+
var ret Mosaic
114+
for r := range m {
115+
var row []Tile
116+
for c := range m[r] {
117+
row = append(row, m[len(m)-1-r][c].FlipX())
118+
}
119+
ret = append(ret, row)
120+
}
121+
return ret
122+
}
123+
124+
func (m Mosaic) RotCW() Mosaic {
125+
var ret Mosaic
126+
for r := range m {
127+
var row []Tile
128+
for c := range m[r] {
129+
row = append(row, m[len(m[0])-1-c][r].RotCW())
130+
}
131+
ret = append(ret, row)
132+
}
133+
return ret
134+
}
135+
136+
func (m Mosaic) CheckSingleEdge(t Tile, r, c, dir int) bool {
137+
oDir := (dir + 2) % 4
138+
var otherR, otherC int
139+
switch dir {
140+
case TOP:
141+
if r-1 < 0 {
142+
return true
143+
}
144+
otherC = c
145+
otherR = r - 1
146+
case BOTTOM:
147+
if r+1 >= len(m) {
148+
return true
149+
}
150+
otherC = c
151+
otherR = r + 1
152+
case LEFT:
153+
if c-1 < 0 {
154+
return true
155+
}
156+
otherC = c - 1
157+
otherR = r
158+
case RIGHT:
159+
if c+1 >= len(m[0]) {
160+
return true
161+
}
162+
otherC = c + 1
163+
otherR = r
164+
}
165+
otherTile := m[otherR][otherC]
166+
var empty Tile
167+
if otherTile == empty {
168+
return true
169+
}
170+
return otherTile.Edges()[oDir] == t.Edges()[dir].Flip()
171+
}
172+
173+
func (m Mosaic) CheckFit(t Tile, r, c int) bool {
174+
// Check up, if exists.
175+
if !m.CheckSingleEdge(t, r, c, TOP) {
176+
return false
177+
}
178+
// Check down, if exists.
179+
if !m.CheckSingleEdge(t, r, c, BOTTOM) {
180+
return false
181+
}
182+
// Check left, if exists.
183+
if !m.CheckSingleEdge(t, r, c, LEFT) {
184+
return false
185+
}
186+
// Check right, if exists.
187+
if !m.CheckSingleEdge(t, r, c, RIGHT) {
188+
return false
189+
}
190+
191+
return true
192+
}
193+
194+
func (m Mosaic) Traverse(allTiles map[Tile]int, used map[int]bool, r, c int, dir int) int {
195+
var rIncr, cIncr int
196+
switch dir {
197+
case RIGHT:
198+
cIncr = 1
199+
case BOTTOM:
200+
rIncr = 1
201+
case LEFT:
202+
cIncr = -1
203+
case TOP:
204+
rIncr = -1
205+
}
206+
i := 1
207+
outer:
208+
for ; ; i++ {
209+
row := r + rIncr*i
210+
col := c + cIncr*i
211+
if row < 0 || row >= len(m) {
212+
break
213+
}
214+
if row < 0 || col >= len(m[0]) {
215+
break
216+
}
217+
for t, s := range allTiles {
218+
if used[s] {
219+
// Don't re-use the same piece twice.
220+
continue
221+
}
222+
if m.CheckFit(t, row, col) {
223+
used[s] = true
224+
m[row][col] = t
225+
continue outer
226+
}
227+
// This piece hasn't matched, continue on to other pieces.
228+
}
229+
// We didn't match any pieces, abort.
230+
return 0
231+
}
232+
return i - 1
233+
}
234+
235+
var SeaMonster = strings.Split(` #
236+
# ## ## ###
237+
# # # # # # `, "\n")
238+
239+
func (m Mosaic) MonsterTopLeftCoord(r, c int) bool {
240+
for rOffset, row := range SeaMonster {
241+
for cOffset, char := range row {
242+
if char != '#' {
243+
continue
244+
}
245+
if !m.PixelAtCoord(r+rOffset, c+cOffset) {
246+
return false
247+
}
248+
}
249+
}
250+
return true
251+
}
252+
253+
func (m Mosaic) FindMonsters() int {
254+
// Find the sea monster.
255+
var monstersFound int
256+
for r := 0; r+len(SeaMonster) < 8*len(m); r++ {
257+
for c := 0; c+len(SeaMonster[0]) < 8*len(m[0]); c++ {
258+
if m.MonsterTopLeftCoord(r, c) {
259+
monstersFound++
260+
}
261+
}
262+
}
263+
return monstersFound
264+
}
265+
168266
func main() {
169267
flag.Parse()
170268
bytes, err := ioutil.ReadFile(*inputFile)
@@ -195,16 +293,6 @@ func main() {
195293
}
196294
tiles[n] = tile
197295
}
198-
if *debug {
199-
for i, t := range tiles {
200-
edges := t.Edges()
201-
var flipped [4]Edge
202-
for i, e := range edges {
203-
flipped[i] = e.Flip()
204-
}
205-
fmt.Printf("Tile %d: %v (flipped: %v)\n", i, edges, flipped)
206-
}
207-
}
208296
allEdges := make(map[Edge][]int)
209297
for i, t := range tiles {
210298
edges := t.Edges()
@@ -235,9 +323,6 @@ func main() {
235323
}
236324
}
237325
fmt.Println(product)
238-
if *debug {
239-
fmt.Printf("Number of corners found: %d; number of sides found: %d\n", len(corners), len(sides))
240-
}
241326

242327
var image Mosaic
243328
for r := 0; r*r < len(tiles); r++ {
@@ -276,23 +361,23 @@ func main() {
276361
}
277362

278363
count := image.Traverse(allTiles, used, 0, 0, RIGHT)
279-
if count == 0 {
364+
if count != len(image[0])-1 {
280365
fmt.Println("Failed to traverse right from what should be top left.")
281366
return
282367
}
283368

284-
for c := 0; c*c < len(tiles); c++ {
369+
for c := 0; c < len(image[0]); c++ {
285370
count = image.Traverse(allTiles, used, 0, c, BOTTOM)
286-
if count == 0 {
371+
if count != len(image)-1 {
287372
fmt.Printf("Failed to traverse down column %d\n", c)
288373
return
289374
}
290375
}
291376

292377
var monsterCount int
293378
outer:
294-
for rot := 0; rot < 4; rot++ {
295-
for flip := 0; flip < 2; flip++ {
379+
for flip := 0; flip < 2; flip++ {
380+
for rot := 0; rot < 4; rot++ {
296381
monsterCount = image.FindMonsters()
297382
if monsterCount != 0 {
298383
break outer
@@ -312,47 +397,3 @@ outer:
312397
}
313398
fmt.Println(sum - monsterPixels)
314399
}
315-
316-
func (m Mosaic) Traverse(allTiles map[Tile]int, used map[int]bool, r, c int, dir int) int {
317-
loose := m[r][c].Edges()[dir]
318-
var rIncr, cIncr int
319-
switch dir {
320-
case RIGHT:
321-
cIncr = 1
322-
case BOTTOM:
323-
rIncr = 1
324-
case LEFT:
325-
cIncr = -1
326-
case TOP:
327-
rIncr = -1
328-
}
329-
i := 1
330-
outer:
331-
for ; ; i++ {
332-
row := r + rIncr*i
333-
col := c + cIncr*i
334-
if row < 0 || row >= len(m) {
335-
break
336-
}
337-
if row < 0 || col >= len(m[0]) {
338-
break
339-
}
340-
for t, s := range allTiles {
341-
if used[s] {
342-
// Don't re-use the same piece twice.
343-
continue
344-
}
345-
edges := t.Edges()
346-
if loose.Flip() == edges[(dir+2)%4] {
347-
used[s] = true
348-
loose = edges[dir]
349-
m[row][col] = t
350-
continue outer
351-
}
352-
// This piece hasn't matched, continue on to other pieces.
353-
}
354-
// We didn't match any pieces, abort.
355-
return 0
356-
}
357-
return i - 1
358-
}

0 commit comments

Comments
 (0)