292 lines
6.0 KiB
Go
292 lines
6.0 KiB
Go
package day06
|
|
|
|
import (
|
|
"adventofcode2024/utils/grid2d"
|
|
"adventofcode2024/utils/inputs"
|
|
"fmt"
|
|
_ "strings"
|
|
)
|
|
|
|
type Direction int
|
|
|
|
const (
|
|
_ Direction = iota
|
|
Up
|
|
Down
|
|
Left
|
|
Right
|
|
)
|
|
|
|
type Pos struct {
|
|
x int
|
|
y int
|
|
}
|
|
type Loc struct {
|
|
dir Direction
|
|
pos Pos
|
|
count int
|
|
}
|
|
|
|
type Point struct {
|
|
dirs []Direction
|
|
display string
|
|
}
|
|
|
|
func (d Direction) String() string {
|
|
return [...]string{"-", "Up", "Down", "Left", "Right"}[d]
|
|
}
|
|
|
|
func (l Loc) String() string {
|
|
return fmt.Sprintf("Direction: %s, Position: %d %d", l.dir, l.pos.x, l.pos.y)
|
|
}
|
|
|
|
func Part1(input string) int {
|
|
var loc Loc
|
|
grid := inputs.ToGrid2D(input, "\n", "", "", func(c string) string { return c })
|
|
for x := 0; x < grid.SizeX(); x++ {
|
|
for y := 0; y < grid.SizeY(); y++ {
|
|
if grid.Get(x, y) == "^" {
|
|
loc = Loc{dir: Up, pos: Pos{x: x, y: y}}
|
|
}
|
|
if grid.Get(x, y) == "v" {
|
|
loc = Loc{dir: Down, pos: Pos{x: x, y: y}}
|
|
}
|
|
if grid.Get(x, y) == ">" {
|
|
loc = Loc{dir: Right, pos: Pos{x: x, y: y}}
|
|
}
|
|
if grid.Get(x, y) == "<" {
|
|
loc = Loc{dir: Left, pos: Pos{x: x, y: y}}
|
|
}
|
|
}
|
|
}
|
|
fmt.Println(grid.Matrix())
|
|
fmt.Printf("%v\n", loc)
|
|
grid.Set(loc.pos.x, loc.pos.y, "X")
|
|
loc.count = 1
|
|
move1(&loc, grid)
|
|
return loc.count
|
|
}
|
|
|
|
func Part2(input string) int {
|
|
var loc Loc
|
|
grid := inputs.ToGrid2D(input, "\n", "", Point{}, func(c string) Point { return Point{dirs: make([]Direction, 1), display: c} })
|
|
for x := 0; x < grid.SizeX(); x++ {
|
|
for y := 0; y < grid.SizeY(); y++ {
|
|
if grid.Get(x, y).display == "^" {
|
|
loc = Loc{dir: Up, pos: Pos{x: x, y: y}}
|
|
}
|
|
if grid.Get(x, y).display == "v" {
|
|
loc = Loc{dir: Down, pos: Pos{x: x, y: y}}
|
|
}
|
|
if grid.Get(x, y).display == ">" {
|
|
loc = Loc{dir: Right, pos: Pos{x: x, y: y}}
|
|
}
|
|
if grid.Get(x, y).display == "<" {
|
|
loc = Loc{dir: Left, pos: Pos{x: x, y: y}}
|
|
}
|
|
}
|
|
}
|
|
fmt.Println(grid.Matrix())
|
|
fmt.Printf("%v\n", loc)
|
|
point := grid.Get(loc.pos.x, loc.pos.y)
|
|
grid.Set(loc.pos.x, loc.pos.y, Point{dirs: append(point.dirs, Up), display: "X"})
|
|
for x := 0; x < grid.SizeX(); x++ {
|
|
for y := 0; y < grid.SizeY(); y++ {
|
|
grid = inputs.ToGrid2D(input, "\n", "", Point{}, func(c string) Point { return Point{dirs: make([]Direction, 1), display: c} })
|
|
p := grid.Get(x, y)
|
|
if p.display == "." {
|
|
grid.Set(x, y, Point{dirs: p.dirs, display: "#"})
|
|
l := loc
|
|
if isLoop(&l, grid) {
|
|
loc.count++
|
|
}
|
|
grid.Set(x, y, Point{dirs: p.dirs, display: "."})
|
|
}
|
|
}
|
|
}
|
|
return loc.count
|
|
}
|
|
|
|
func isLoop(loc *Loc, grid *grid2d.Grid[Point]) bool {
|
|
for {
|
|
_, _, err := move2(loc, grid)
|
|
if err != nil { return false }
|
|
if contains(loc.dir, grid.Get(loc.pos.x, loc.pos.y)) {
|
|
return true
|
|
} else {
|
|
p := grid.Get(loc.pos.x, loc.pos.y)
|
|
grid.Set(loc.pos.x, loc.pos.y, Point{dirs: append(p.dirs, loc.dir), display: "X"})
|
|
}
|
|
}
|
|
}
|
|
|
|
func Part2b(input string) int {
|
|
var loc Loc
|
|
grid := inputs.ToGrid2D(input, "\n", "", Point{}, func(c string) Point { return Point{dirs: make([]Direction, 1), display: c} })
|
|
for x := 0; x < grid.SizeX(); x++ {
|
|
for y := 0; y < grid.SizeY(); y++ {
|
|
if grid.Get(x, y).display == "^" {
|
|
loc = Loc{dir: Up, pos: Pos{x: x, y: y}}
|
|
}
|
|
if grid.Get(x, y).display == "v" {
|
|
loc = Loc{dir: Down, pos: Pos{x: x, y: y}}
|
|
}
|
|
if grid.Get(x, y).display == ">" {
|
|
loc = Loc{dir: Right, pos: Pos{x: x, y: y}}
|
|
}
|
|
if grid.Get(x, y).display == "<" {
|
|
loc = Loc{dir: Left, pos: Pos{x: x, y: y}}
|
|
}
|
|
}
|
|
}
|
|
fmt.Println(grid.Matrix())
|
|
fmt.Printf("%v\n", loc)
|
|
point := grid.Get(loc.pos.x, loc.pos.y)
|
|
grid.Set(loc.pos.x, loc.pos.y, Point{dirs: append(point.dirs, Up), display: "X"})
|
|
loc.count = 0
|
|
for {
|
|
_, _, err := move2(&loc, grid)
|
|
if err != nil {
|
|
break
|
|
}
|
|
if contains(loc.dir, grid.Get(loc.pos.x, loc.pos.y)) {
|
|
loc.count++
|
|
break
|
|
}
|
|
}
|
|
return loc.count
|
|
}
|
|
|
|
func move1(loc *Loc, grid *grid2d.Grid[string]) int {
|
|
return -1
|
|
}
|
|
|
|
func move2(loc *Loc, grid *grid2d.Grid[Point]) (int, int, error) {
|
|
x, y, err := doMove(loc, grid)
|
|
if err != nil {
|
|
return x, y, err
|
|
}
|
|
if x == loc.pos.x && y == loc.pos.y {
|
|
move2(loc, grid)
|
|
}
|
|
return x, y, nil
|
|
}
|
|
|
|
func canBlock(loc *Loc, point Point) bool {
|
|
val := false
|
|
switch loc.dir {
|
|
case Up:
|
|
if contains(Right, point) {
|
|
val = true
|
|
}
|
|
case Down:
|
|
if contains(Left, point) {
|
|
val = true
|
|
}
|
|
case Left:
|
|
if contains(Up, point) {
|
|
val = true
|
|
}
|
|
case Right:
|
|
if contains(Down, point) {
|
|
val = true
|
|
}
|
|
}
|
|
return val
|
|
}
|
|
|
|
func contains(v Direction, point Point) bool {
|
|
for _, d := range point.dirs {
|
|
if d == v {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func checkMove(loc *Loc, grid *grid2d.Grid[string]) bool {
|
|
switch loc.dir {
|
|
case Down:
|
|
if loc.pos.y+1 >= grid.SizeY() {
|
|
return false
|
|
}
|
|
if grid.Get(loc.pos.x, loc.pos.y+1) == "#" {
|
|
loc.dir = Left
|
|
} else {
|
|
loc.pos.y++
|
|
}
|
|
case Up:
|
|
if loc.pos.y-1 < 0 {
|
|
return false
|
|
}
|
|
if grid.Get(loc.pos.x, loc.pos.y-1) == "#" {
|
|
loc.dir = Right
|
|
} else {
|
|
loc.pos.y--
|
|
}
|
|
case Left:
|
|
if loc.pos.x-1 < 0 {
|
|
return false
|
|
}
|
|
if grid.Get(loc.pos.x-1, loc.pos.y) == "#" {
|
|
loc.dir = Up
|
|
} else {
|
|
loc.pos.x--
|
|
}
|
|
case Right:
|
|
if loc.pos.x+1 >= grid.SizeX() {
|
|
return false
|
|
}
|
|
if grid.Get(loc.pos.x+1, loc.pos.y) == "#" {
|
|
loc.dir = Down
|
|
} else {
|
|
loc.pos.x++
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func doMove(loc *Loc, grid *grid2d.Grid[Point]) (int, int, error) {
|
|
x := loc.pos.x
|
|
y := loc.pos.y
|
|
switch loc.dir {
|
|
case Down:
|
|
if loc.pos.y+1 >= grid.SizeY() {
|
|
return x, y, fmt.Errorf("outside")
|
|
}
|
|
if grid.Get(loc.pos.x, loc.pos.y+1).display == "#" {
|
|
loc.dir = Left
|
|
} else {
|
|
loc.pos.y++
|
|
}
|
|
case Up:
|
|
if loc.pos.y-1 < 0 {
|
|
return x, y, fmt.Errorf("outside")
|
|
}
|
|
if grid.Get(loc.pos.x, loc.pos.y-1).display == "#" {
|
|
loc.dir = Right
|
|
} else {
|
|
loc.pos.y--
|
|
}
|
|
case Left:
|
|
if loc.pos.x-1 < 0 {
|
|
return x, y, fmt.Errorf("outside")
|
|
}
|
|
if grid.Get(loc.pos.x-1, loc.pos.y).display == "#" {
|
|
loc.dir = Up
|
|
} else {
|
|
loc.pos.x--
|
|
}
|
|
case Right:
|
|
if loc.pos.x+1 >= grid.SizeX() {
|
|
return x, y, fmt.Errorf("outside")
|
|
}
|
|
if grid.Get(loc.pos.x+1, loc.pos.y).display == "#" {
|
|
loc.dir = Down
|
|
} else {
|
|
loc.pos.x++
|
|
}
|
|
}
|
|
return x, y, nil
|
|
}
|