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() } }