AdventOfCode2021/05/main.go

141 lines
2.5 KiB
Go

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 []int
func (g *grid) AddLine(start, end point, includeHorizontal bool) {
for _, p := range LineFromPoints(start, end, includeHorizontal) {
(*g)[p.x+p.y*1000]++
}
}
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 := make(grid, 1_000_000)
for scanner.Scan() {
line := scanner.Text()
start, end := parsePoints(line)
grid.AddLine(start, end, false)
}
var danger int
for i := range grid {
if grid[i] > 1 {
danger++
}
}
fmt.Println(danger)
}
func partTwo() {
scanner := makeScanner(false)
grid := make(grid, 1_000_000)
for scanner.Scan() {
line := scanner.Text()
start, end := parsePoints(line)
grid.AddLine(start, end, true)
}
var danger int
for i := range grid {
if grid[i] > 1 {
danger++
}
}
fmt.Println(danger)
}