221 lines
5.4 KiB
Go
221 lines
5.4 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
|
|
type BeamSect struct {
|
|
Direction rune
|
|
Y int
|
|
X int
|
|
}
|
|
|
|
type Beam struct {
|
|
Direction rune
|
|
Path []BeamSect
|
|
EnergizedTiles int
|
|
}
|
|
|
|
type Tile struct {
|
|
Type rune
|
|
ShineN bool
|
|
ShineE bool
|
|
ShineS bool
|
|
ShineW bool
|
|
X int
|
|
Y int
|
|
}
|
|
|
|
func calcEnergized(grid [][]Tile, start Tile) int {
|
|
|
|
tilesChanged := []Tile{start}
|
|
|
|
for len(tilesChanged) > 0 {
|
|
// Contagion
|
|
stillChanged := make([]Tile, 0)
|
|
for _, t := range tilesChanged {
|
|
if t.ShineE && t.X < len(grid[t.Y])-1 {
|
|
eX := t.X + 1
|
|
eY := t.Y
|
|
|
|
shineInto := &grid[eY][eX]
|
|
|
|
if (shineInto.Type == '.' || shineInto.Type == '-') && !shineInto.ShineE {
|
|
// Change!
|
|
shineInto.ShineE = true
|
|
stillChanged = append(stillChanged, *shineInto)
|
|
} else if shineInto.Type == '|' && (!shineInto.ShineN || !shineInto.ShineS) {
|
|
shineInto.ShineN = true
|
|
shineInto.ShineS = true
|
|
stillChanged = append(stillChanged, *shineInto)
|
|
} else if shineInto.Type == '/' && !shineInto.ShineN {
|
|
shineInto.ShineN = true
|
|
stillChanged = append(stillChanged, *shineInto)
|
|
} else if shineInto.Type == '\\' && !shineInto.ShineS {
|
|
shineInto.ShineS = true
|
|
stillChanged = append(stillChanged, *shineInto)
|
|
}
|
|
}
|
|
|
|
if t.ShineW && t.X > 0 {
|
|
wX := t.X - 1
|
|
wY := t.Y
|
|
|
|
shineInto := &grid[wY][wX]
|
|
|
|
if (shineInto.Type == '.' || shineInto.Type == '-') && !shineInto.ShineW {
|
|
// Change!
|
|
shineInto.ShineW = true
|
|
stillChanged = append(stillChanged, *shineInto)
|
|
} else if shineInto.Type == '|' && (!shineInto.ShineN || !shineInto.ShineS) {
|
|
shineInto.ShineN = true
|
|
shineInto.ShineS = true
|
|
stillChanged = append(stillChanged, *shineInto)
|
|
} else if shineInto.Type == '/' && !shineInto.ShineS {
|
|
shineInto.ShineS = true
|
|
stillChanged = append(stillChanged, *shineInto)
|
|
} else if shineInto.Type == '\\' && !shineInto.ShineN {
|
|
shineInto.ShineN = true
|
|
stillChanged = append(stillChanged, *shineInto)
|
|
}
|
|
}
|
|
|
|
if t.ShineN && t.Y > 0 {
|
|
nX := t.X
|
|
nY := t.Y - 1
|
|
|
|
shineInto := &grid[nY][nX]
|
|
|
|
if (shineInto.Type == '.' || shineInto.Type == '|') && !shineInto.ShineN {
|
|
// Change!
|
|
shineInto.ShineN = true
|
|
stillChanged = append(stillChanged, *shineInto)
|
|
} else if shineInto.Type == '-' && (!shineInto.ShineE || !shineInto.ShineW) {
|
|
shineInto.ShineE = true
|
|
shineInto.ShineW = true
|
|
stillChanged = append(stillChanged, *shineInto)
|
|
} else if shineInto.Type == '/' && !shineInto.ShineE {
|
|
shineInto.ShineE = true
|
|
stillChanged = append(stillChanged, *shineInto)
|
|
} else if shineInto.Type == '\\' && !shineInto.ShineW {
|
|
shineInto.ShineW = true
|
|
stillChanged = append(stillChanged, *shineInto)
|
|
}
|
|
|
|
}
|
|
|
|
if t.ShineS && t.Y < len(grid)-1 {
|
|
sX := t.X
|
|
sY := t.Y + 1
|
|
|
|
shineInto := &grid[sY][sX]
|
|
|
|
if (shineInto.Type == '.' || shineInto.Type == '|') && !shineInto.ShineS {
|
|
// Change!
|
|
shineInto.ShineS = true
|
|
stillChanged = append(stillChanged, *shineInto)
|
|
} else if shineInto.Type == '-' && (!shineInto.ShineE || !shineInto.ShineW) {
|
|
shineInto.ShineE = true
|
|
shineInto.ShineW = true
|
|
stillChanged = append(stillChanged, *shineInto)
|
|
} else if shineInto.Type == '/' && !shineInto.ShineW {
|
|
shineInto.ShineW = true
|
|
stillChanged = append(stillChanged, *shineInto)
|
|
} else if shineInto.Type == '\\' && !shineInto.ShineE {
|
|
shineInto.ShineE = true
|
|
stillChanged = append(stillChanged, *shineInto)
|
|
}
|
|
|
|
}
|
|
}
|
|
tilesChanged = stillChanged
|
|
}
|
|
|
|
energized := 0
|
|
for v := range grid {
|
|
for h := range grid[v] {
|
|
if grid[v][h].ShineE || grid[v][h].ShineN || grid[v][h].ShineS || grid[v][h].ShineW {
|
|
energized += 1
|
|
}
|
|
}
|
|
}
|
|
|
|
return energized
|
|
}
|
|
|
|
func resetGrid(grid [][]Tile) {
|
|
for v := range grid {
|
|
for h := range grid[v] {
|
|
grid[h][v].ShineE = false
|
|
grid[h][v].ShineN = false
|
|
grid[h][v].ShineS = false
|
|
grid[h][v].ShineW = false
|
|
}
|
|
}
|
|
}
|
|
|
|
func run(part2 bool, input string) any {
|
|
// when you're ready to do part 2, remove this "not implemented" block
|
|
grid := make([][]Tile, 0)
|
|
for _, l := range strings.Split(input, "\n") {
|
|
if l == "" {
|
|
continue
|
|
}
|
|
|
|
gridLine := make([]Tile, 0)
|
|
for r := range l {
|
|
gridLine = append(gridLine, Tile{Type: rune(l[r]), X: len(gridLine), Y: len(grid)})
|
|
}
|
|
grid = append(grid, gridLine)
|
|
}
|
|
|
|
if part2 {
|
|
maxEnergized := -1
|
|
|
|
for v := range grid {
|
|
testE := calcEnergized(grid, Tile{ShineE: true, X: -1, Y: v})
|
|
resetGrid(grid)
|
|
if testE > maxEnergized {
|
|
maxEnergized = testE
|
|
}
|
|
|
|
testW := calcEnergized(grid, Tile{ShineW: true, X: len(grid[v]), Y: v})
|
|
resetGrid(grid)
|
|
if testW > maxEnergized {
|
|
maxEnergized = testW
|
|
}
|
|
}
|
|
|
|
for h := range grid[0] {
|
|
testN := calcEnergized(grid, Tile{ShineN: true, X: h, Y: len(grid)})
|
|
resetGrid(grid)
|
|
if testN > maxEnergized {
|
|
maxEnergized = testN
|
|
}
|
|
|
|
testS := calcEnergized(grid, Tile{ShineS: true, X: h, Y: -1})
|
|
resetGrid(grid)
|
|
if testS > maxEnergized {
|
|
maxEnergized = testS
|
|
}
|
|
}
|
|
|
|
return maxEnergized
|
|
}
|
|
// solve part 1 her
|
|
|
|
return calcEnergized(grid, Tile{ShineE: true, X: -1, Y: 0})
|
|
}
|