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 }