203 lines
3.7 KiB
Go
203 lines
3.7 KiB
Go
package main
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/jpillora/puzzler/harness/aoc"
|
|
)
|
|
|
|
func main() {
|
|
aoc.Harness(run)
|
|
}
|
|
|
|
// on code change, run will be executed 4 times:
|
|
// 1. with: false (part1), and example input
|
|
// 2. with: true (part2), and example input
|
|
// 3. with: false (part1), and user input
|
|
// 4. with: true (part2), and user input
|
|
// the return value of each run is printed to stdout
|
|
func run(part2 bool, input string) any {
|
|
// when you're ready to do part 2, remove this "not implemented" block
|
|
grids := make([][][]rune, 0)
|
|
|
|
thisGrid := make([][]rune, 0)
|
|
for _, l := range strings.Split(input, "\n") {
|
|
if l == "" {
|
|
grids = append(grids, thisGrid)
|
|
thisGrid = make([][]rune, 0)
|
|
continue
|
|
}
|
|
|
|
thisGridLine := make([]rune, 0)
|
|
for _, r := range strings.Split(l, "") {
|
|
thisGridLine = append(thisGridLine, rune(r[0]))
|
|
}
|
|
|
|
thisGrid = append(thisGrid, thisGridLine)
|
|
}
|
|
|
|
if part2 {
|
|
sum := 0
|
|
for _, g := range grids {
|
|
cv, ch := calcReflectionRemainder(g, -1, -1)
|
|
found := false
|
|
calcGrid:
|
|
for v := range g {
|
|
for h := range g[v] {
|
|
//fmt.Printf("Smudging [%v, %v]...", v, h)
|
|
if g[v][h] == '.' {
|
|
// try fix the smudge!
|
|
g[v][h] = '#'
|
|
|
|
nv, nh := calcReflectionRemainder(g, cv, ch)
|
|
newVal := -1
|
|
if nv != -1 {
|
|
newVal = (nv + 1) * 100
|
|
} else if nh != -1 {
|
|
newVal = nh + 1
|
|
}
|
|
//fmt.Printf(" (%v)\n", newVal)
|
|
|
|
if newVal != -1 {
|
|
// We've found it!
|
|
sum += newVal
|
|
found = true
|
|
break calcGrid
|
|
}
|
|
|
|
g[v][h] = '.'
|
|
} else {
|
|
// try fix the smudge!
|
|
g[v][h] = '.'
|
|
|
|
nv, nh := calcReflectionRemainder(g, cv, ch)
|
|
newVal := -1
|
|
if nv != -1 {
|
|
newVal = (nv + 1) * 100
|
|
} else if nh != -1 {
|
|
newVal = nh + 1
|
|
}
|
|
//fmt.Printf(" (%v)\n", newVal)
|
|
|
|
if newVal != -1 {
|
|
// We've found it!
|
|
//fmt.Printf("Found new: %v\n", newVal)
|
|
sum += newVal
|
|
found = true
|
|
break calcGrid
|
|
}
|
|
|
|
g[v][h] = '#'
|
|
}
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
panic("No new")
|
|
}
|
|
}
|
|
return sum
|
|
}
|
|
// solve part 1 here
|
|
|
|
p := 0
|
|
for _, g := range grids {
|
|
//fmt.Printf("Doing %v\n", g)
|
|
pv, ph := calcReflectionRemainder(g, -1, -1)
|
|
|
|
if pv != -1 {
|
|
p += (pv + 1) * 100
|
|
} else if ph != -1 {
|
|
p += ph + 1
|
|
} else {
|
|
panic("Could not find")
|
|
}
|
|
}
|
|
|
|
return p
|
|
}
|
|
|
|
func calcReflectionRemainder(grid [][]rune, exclV int, exclH int) (int, int) {
|
|
// Try horizontal
|
|
for v := 0; v < len(grid)-1; v++ {
|
|
if v == exclV {
|
|
continue
|
|
}
|
|
mirror := true
|
|
m1:
|
|
for h := 0; h < len(grid[v])-1; h++ {
|
|
if grid[v][h] != grid[v+1][h] {
|
|
mirror = false
|
|
break m1
|
|
}
|
|
}
|
|
|
|
if mirror {
|
|
// Confirm a mirror
|
|
lhs := v
|
|
rhs := v + 1
|
|
|
|
confirmedMirror := true
|
|
|
|
m2:
|
|
for lhs >= 0 && rhs < len(grid) {
|
|
for h := 0; h < len(grid[lhs]); h++ {
|
|
if grid[lhs][h] != grid[rhs][h] {
|
|
confirmedMirror = false
|
|
break m2
|
|
}
|
|
}
|
|
lhs -= 1
|
|
rhs += 1
|
|
}
|
|
|
|
if confirmedMirror {
|
|
//fmt.Printf("Found at horiz %v-%v\n", v, v+1)
|
|
return v, -1
|
|
}
|
|
}
|
|
}
|
|
|
|
// Else try vertical
|
|
for h := 0; h < len(grid[0])-1; h++ {
|
|
if h == exclH {
|
|
continue
|
|
}
|
|
mirror := true
|
|
m3:
|
|
for v := 0; v < len(grid)-1; v++ {
|
|
if grid[v][h] != grid[v][h+1] {
|
|
mirror = false
|
|
break m3
|
|
}
|
|
}
|
|
|
|
if mirror {
|
|
// Confirm a mirror
|
|
uhs := h
|
|
bhs := h + 1
|
|
|
|
confirmedMirror := true
|
|
|
|
m4:
|
|
for uhs >= 0 && bhs < len(grid[0]) {
|
|
for v := 0; v < len(grid); v++ {
|
|
if grid[v][uhs] != grid[v][bhs] {
|
|
confirmedMirror = false
|
|
break m4
|
|
}
|
|
}
|
|
uhs -= 1
|
|
bhs += 1
|
|
}
|
|
|
|
if confirmedMirror {
|
|
//fmt.Printf("Found at vert %v-%v\n", h, h+1)
|
|
return -1, h
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1, -1
|
|
}
|