147 lines
2.5 KiB
Go
147 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 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)
|
||
|
}
|