140 lines
2.9 KiB
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()
|
||
|
}
|
||
|
}
|