adventofcode/2023/day23/main.go

140 lines
2.9 KiB
Go

package main
import (
"fmt"
"os"
h "git.bullercodeworks.com/brian/adventofcode/helpers"
)
func main() {
inp := h.StdinToStringSlice()
if len(os.Args) == 1 || os.Args[1] != "-p2" {
part1(inp)
}
if len(os.Args) == 1 {
fmt.Println()
}
if len(os.Args) == 1 || os.Args[1] != "-p1" {
part2(inp)
}
}
var history map[string]int
func part1(input []string) {
history = make(map[string]int)
m := h.StringSliceToCoordByteMap(input)
start, _ := m.FindFirst('.')
start.Y++
end, _ := m.FindLast('.')
fmt.Println("# Part 1")
fmt.Println(len(findPath(&m, start, end, []h.Coordinate{})))
}
func part2(input []string) {
history = make(map[string]int)
m := h.StringSliceToCoordByteMap(input)
start, _ := m.FindFirst('.')
start.Y++
end, _ := m.FindLast('.')
m.ReplaceAll('^', '.')
m.ReplaceAll('>', '.')
m.ReplaceAll('v', '.')
m.ReplaceAll('<', '.')
fmt.Println("# Part 2")
fmt.Println(len(findPath(&m, start, end, []h.Coordinate{})))
}
func findPath(m *h.CoordByteMap, pos h.Coordinate, end h.Coordinate, path []h.Coordinate) []h.Coordinate {
ret := []h.Coordinate{pos}
if pos.Equals(end) {
//printPath(m, pos, path)
//time.Sleep(time.Second / 20)
return ret
}
path = append(path, pos)
switch m.Get(pos) {
case '^':
if inPath(pos.North(), path) {
return ret
} else {
return append(ret, findPath(m, pos.North(), end, path)...)
}
case '>':
if inPath(pos.East(), path) {
return ret
} else {
return append(ret, findPath(m, pos.East(), end, path)...)
}
case 'v':
if inPath(pos.South(), path) {
return ret
} else {
return append(ret, findPath(m, pos.South(), end, path)...)
}
case '<':
if inPath(pos.West(), path) {
return ret
} else {
return append(ret, findPath(m, pos.West(), end, path)...)
}
}
var longestPath []h.Coordinate
longest := h.MIN_INT
for _, chk := range []h.Coordinate{pos.North(), pos.East(), pos.South(), pos.West()} {
if m.Get(chk) == '#' || inPath(chk, path) || !m.ContainsCoord(chk) {
continue
}
var run bool
var v int
if v, run = history[chk.String()]; run {
run = v < len(path)+1
}
if run {
history[chk.String()] = len(path) + 1
chkPath := append(ret, findPath(m, chk, end, path)...)
if inPath(end, chkPath) && len(chkPath) > longest {
longest = len(chkPath)
longestPath = chkPath
}
}
}
return longestPath
}
func inPath(pos h.Coordinate, path []h.Coordinate) bool {
for _, chk := range path {
if chk.Equals(pos) {
return true
}
}
return false
}
func printPath(m *h.CoordByteMap, pos h.Coordinate, path []h.Coordinate) {
limit := (m.BRY - m.TLY) > 30
fmt.Print(h.CLEAR_SCREEN)
for y := m.TLY; y <= m.BRY; y++ {
if limit && h.Abs(pos.Y-y) > 15 {
continue
}
for x := m.TLX; x <= m.BRX; x++ {
chk := h.Coordinate{X: x, Y: y}
if chk.Equals(pos) {
fmt.Print("@")
} else {
if inPath(chk, path) {
fmt.Print("O")
} else {
fmt.Print(string(m.Get(chk)))
}
}
}
fmt.Println()
}
}