/day03.go Secret
Created
December 3, 2019 05:25
AoC 2019 Day 3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package day3 | |
import ( | |
"bufio" | |
"fmt" | |
"io" | |
"strconv" | |
"strings" | |
) | |
type direction string | |
const ( | |
up direction = "U" | |
down direction = "D" | |
left direction = "L" | |
right direction = "R" | |
) | |
type move struct { | |
dir direction | |
mag int | |
} | |
type point struct { | |
x int | |
y int | |
} | |
type state struct { | |
point | |
steps int | |
} | |
type grid map[point]map[int]int | |
type Runner struct{ | |
a int | |
b int | |
} | |
func (r *Runner) PartA(in io.Reader) string { | |
if r.a == 0 { | |
r.run(in) | |
} | |
return fmt.Sprint(r.a) | |
} | |
func (r *Runner) PartB(in io.Reader) string { | |
if r.b == 0 { | |
r.run(in) | |
} | |
return fmt.Sprint(r.b) | |
} | |
func (r *Runner) run(in io.Reader) { | |
s := bufio.NewScanner(in) | |
data := [][]move{} | |
for s.Scan() { | |
l := s.Text() | |
s := strings.Split(l, ",") | |
moves := []move{} | |
for _, v := range s { | |
m := move{dir: direction(v[0])} | |
mag, err := strconv.Atoi(v[1:]) | |
if err != nil { | |
panic(err) | |
} | |
m.mag = mag | |
moves = append(moves, m) | |
} | |
data = append(data, moves) | |
} | |
g := make(grid) | |
for i := 0; i < len(data); i++ { | |
s0 := state{} | |
for j := 0; j < len(data[i]); j++ { | |
s0 = g.apply(s0, data[i][j], i) | |
} | |
} | |
minDist := 9999999999 | |
minDelay := minDist | |
origin := state{} | |
for k, v := range g { | |
if len(v) > 1 { | |
dst := dist(origin.point, k) | |
if dst < minDist { | |
minDist = dst | |
} | |
delay := v[0] + v[1] | |
if delay < minDelay { | |
minDelay = delay | |
} | |
} | |
} | |
r.a = minDist | |
r.b = minDelay | |
} | |
func abs(a int) int { | |
if a < 0 { | |
return -1 * a | |
} | |
return a | |
} | |
func min(a, b int) int { | |
if a < b { | |
return a | |
} | |
return b | |
} | |
func max(a, b int) int { | |
if a > b { | |
return a | |
} | |
return b | |
} | |
func dist(a, b point) int { | |
return abs(a.x-b.x) + abs(a.y-b.y) | |
} | |
func (g grid) apply(s state, m move, wire int) state { | |
switch m.dir { | |
case up: | |
for i := 0; i < m.mag; i++ { | |
s.y++ | |
s.steps++ | |
g.update(s, wire) | |
} | |
case down: | |
for i := 0; i < m.mag; i++ { | |
s.y-- | |
s.steps++ | |
g.update(s, wire) | |
} | |
case left: | |
for i := 0; i < m.mag; i++ { | |
s.x-- | |
s.steps++ | |
g.update(s, wire) | |
} | |
case right: | |
for i := 0; i < m.mag; i++ { | |
s.x++ | |
s.steps++ | |
g.update(s, wire) | |
} | |
} | |
return s | |
} | |
func (g grid) update(s state, wire int) { | |
if _, ok := g[s.point]; !ok { | |
g[s.point] = make(map[int]int) | |
} | |
if _, ok := g[s.point][wire]; !ok { | |
g[s.point][wire] = 9999999999 | |
} | |
g[s.point][wire] = min(g[s.point][wire], s.steps) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment