Files
adventofcode/2023/go/day16/day16.go
2024-12-01 08:01:55 +00:00

202 lines
4.8 KiB
Go

package day16
import (
_ "adventofcode2023/utils"
"adventofcode2023/utils/grid2d"
_ "adventofcode2023/utils/grid2d"
"adventofcode2023/utils/inputs"
"fmt"
_ "strings"
)
type Tile struct {
object rune
energized int
}
type Beam struct {
dir rune
r int
c int
rm bool
}
var startBeams []Beam
func Part1(input string) int {
beams := []Beam{}
beams = addBeam(beams, Beam{'s', 0, 3, false})
grid := inputs.ToGrid2D[Tile](input, "\n", "", Tile{}, func(c string) Tile { return Tile{ object: rune(c[0]), energized: 0}})
return score(grid, beams)
}
func Part2(input string) int {
grid := inputs.ToGrid2D[Tile](input, "\n", "", Tile{}, func(c string) Tile { return Tile{ object: rune(c[0]), energized: 0}})
G := grid.Matrix()
R := len(G)
C := len(G[0])
ans := 0
for r:=0;r<R;r++{
beams := []Beam{}
grid := inputs.ToGrid2D[Tile](input, "\n", "", Tile{}, func(c string) Tile { return Tile{ object: rune(c[0]), energized: 0}})
beams = addBeam(beams, Beam{'e', r, 0, false})
ans = max(ans, score(grid, beams))
beams = []Beam{}
beams = addBeam(beams, Beam{'w', r, C-1, false})
grid = inputs.ToGrid2D[Tile](input, "\n", "", Tile{}, func(c string) Tile { return Tile{ object: rune(c[0]), energized: 0}})
ans = max(ans, score(grid, beams))
}
for c:=0;c<C;c++{
beams := []Beam{}
grid := inputs.ToGrid2D[Tile](input, "\n", "", Tile{}, func(c string) Tile { return Tile{ object: rune(c[0]), energized: 0}})
beams = addBeam(beams, Beam{'s', 0, c, false})
ans = max(ans, score(grid, beams))
beams = []Beam{}
beams = addBeam(beams, Beam{'n', R-1, c, false})
grid = inputs.ToGrid2D[Tile](input, "\n", "", Tile{}, func(c string) Tile { return Tile{ object: rune(c[0]), energized: 0}})
ans = max(ans, score(grid, beams))
}
return ans
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func score(grid *grid2d.Grid[Tile], beams []Beam) int {
fmt.Println(grid.StringWithFormatter(func(t Tile, x int, y int) string { return string(t.object)}))
G := grid.Matrix()
R := len(G)
C := len(G[0])
fmt.Println("r:", R, "c:", C, "tiles:", R*C )
for i:=0;i<1000;i++ {
beams = rmBeams(beams)
fmt.Println(i, ":", len(beams), ":", energy(G))
for i, _ := range beams {
r := beams[i].r
c := beams[i].c
if r >= 0 && r < R && c >= 0 && c < C {
G[r][c].energized++
switch beams[i].dir {
case 'n':
tile := &G[r][c]
switch tile.object {
case '.':
beams[i].r--
case '|':
beams[i].r--
case '-':
beams[i].dir = 'e'
beams[i].c++
beams = addBeam(beams, Beam{'w', beams[i].r, beams[i].c-1, false})
case '\\':
beams[i].dir = 'w'
beams[i].c--
case '/':
beams[i].dir = 'e'
beams[i].c++
}
case 'e':
tile := &G[r][c]
switch tile.object {
case '.':
beams[i].c++
case '-':
beams[i].c++
case '|':
beams[i].dir = 'n'
beams[i].r--
beams = addBeam(beams, Beam{'s', beams[i].r+1, beams[i].c, false})
case '\\':
beams[i].dir = 's'
beams[i].r++
case '/':
beams[i].dir = 'n'
beams[i].r--
}
case 's':
tile := &G[r][c]
switch tile.object {
case '.':
beams[i].r++
case '|':
beams[i].r++
case '-':
beams[i].dir = 'e'
beams[i].c++
beams = addBeam(beams, Beam{'w', beams[i].r, beams[i].c-1, false})
case '\\':
beams[i].dir = 'e'
beams[i].c++
case '/':
beams[i].dir = 'w'
beams[i].c--
}
case 'w':
tile := &G[r][c]
switch tile.object {
case '.':
beams[i].c--
case '-':
beams[i].c--
case '|':
beams[i].dir = 'n'
beams[i].r--
beams = addBeam(beams, Beam{'s', beams[i].r+1, beams[i].c, false})
case '\\':
beams[i].dir = 'n'
beams[i].r--
case '/':
beams[i].dir = 's'
beams[i].r++
}
}
} else {
beams[i].rm = true
}
}
fmt.Println(grid.StringWithFormatter(func(t Tile, x int, y int) string { if t.energized > 0 {return "#"}; return "."}))
}
fmt.Println(grid.StringWithFormatter(func(t Tile, x int, y int) string { if t.energized > 0 {return "#"}; return "."}))
return energy(G)
}
func rmBeams(slice []Beam) []Beam {
var result []Beam
for _, value := range slice {
if ! value.rm {
result = append(result, value)
}
}
return result
}
func addBeam(beams []Beam, beam Beam) []Beam {
for _, value := range startBeams {
if value == beam { return beams }
}
startBeams = append(startBeams, beam)
for _, value := range beams {
if value == beam { return beams }
}
return append(beams, beam)
}
func energy(G [][]Tile) int {
ans := 0
R := len(G)
C := len(G[0])
for r:=0;r<R;r++ {
for c:=0;c<C;c++ {
if G[r][c].energized > 0 {
ans++
}
}
}
return ans
}