diff --git a/05/main.go b/05/main.go new file mode 100644 index 0000000..f00d576 --- /dev/null +++ b/05/main.go @@ -0,0 +1,146 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "strconv" + "time" +) + +func main() { + start := time.Now() + partOne() + duration := time.Since(start) + partTwo() + duration2 := time.Since(start) + fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration) +} + +func makeScanner(test bool) *bufio.Scanner { + var f *os.File + if test { + f, _ = os.Open("inputs/testinput") + } else { + f, _ = os.Open("inputs/input") + } + reader := bufio.NewReader(f) + return bufio.NewScanner(reader) +} + +func mustAtoi(line []byte) int { + i, err := strconv.Atoi(string(line)) + if err != nil { + panic(err) + } + return i +} + +type point struct { + x int + y int +} + +type grid struct { + m map[point]int +} + +func (g *grid) AddLine(start, end point, includeHorizontal bool) { + for _, p := range LineFromPoints(start, end, includeHorizontal) { + g.m[p]++ + } +} + +func LineFromPoints(start, end point, includeHorizontal bool) []point { + if start.x != end.x && start.y != end.y && !includeHorizontal { + return []point{} + } + var xstep, ystep int + if start.x > end.x { + xstep = -1 + } + if start.x < end.x { + xstep = 1 + } + if start.y > end.y { + ystep = -1 + } + if start.y < end.y { + ystep = 1 + } + points := []point{} + for i, j := start.x, start.y; i != end.x+xstep || j != end.y+ystep; i, j = i+xstep, j+ystep { + points = append(points, point{x: i, y: j}) + } + return points +} + +func parsePoints(line string) (point, point) { + var start, end point + var num []byte // accumulator + var state int // parser state: 0: x1 1: y1 2: x2 3: y2 + for i := 0; i < len(line); i++ { + switch line[i] { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + num = append(num, line[i]) + case ' ': + start.y = mustAtoi(num) + num = []byte{} + i += 3 // jump past '-> ' + state = 2 + case ',': + if state == 0 { + start.x = mustAtoi(num) + num = []byte{} + state = 1 + } + if state == 2 { + end.x = mustAtoi(num) + num = []byte{} + state = 3 + } + } + } + end.y = mustAtoi(num) + return start, end +} + +func partOne() { + scanner := makeScanner(false) + + grid := &grid{ + m: map[point]int{}, + } + for scanner.Scan() { + line := scanner.Text() + start, end := parsePoints(line) + grid.AddLine(start, end, false) + } + var danger int + for i := range grid.m { + if grid.m[i] > 1 { + danger++ + } + } + fmt.Println(danger) +} + +func partTwo() { + scanner := makeScanner(false) + + grid := &grid{ + m: map[point]int{}, + } + for scanner.Scan() { + line := scanner.Text() + start, end := parsePoints(line) + grid.AddLine(start, end, true) + } + var danger int + for i := range grid.m { + if grid.m[i] > 1 { + danger++ + } + } + fmt.Println(danger) +}