days
This commit is contained in:
291
2024/go/day06/day06.go
Normal file
291
2024/go/day06/day06.go
Normal file
@@ -0,0 +1,291 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user