202 lines
4.8 KiB
Go
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
|
|
} |