123 lines
2 KiB
Go
123 lines
2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
|
|
"github.com/jdkaplan/advent-of-code/aoc"
|
|
)
|
|
|
|
type Point struct {
|
|
x, y int
|
|
}
|
|
|
|
func (p Point) Plus(dx, dy int) Point {
|
|
return Point{x: p.x + dx, y: p.y + dy}
|
|
}
|
|
|
|
type Line struct {
|
|
p1, p2 Point
|
|
}
|
|
|
|
func (l Line) Slope() float64 {
|
|
dx := float64(l.p2.x - l.p1.x)
|
|
dy := float64(l.p2.y - l.p1.y)
|
|
return dy / dx
|
|
}
|
|
|
|
func (l Line) Delta() (dx, dy int) {
|
|
switch s := l.Slope(); s {
|
|
case 0:
|
|
if l.p1.x < l.p2.x {
|
|
return 1, 0
|
|
}
|
|
return -1, 0
|
|
case math.Inf(+1):
|
|
if l.p1.y < l.p2.y {
|
|
return 0, 1
|
|
}
|
|
return 0, -1
|
|
case +1:
|
|
if l.p1.x < l.p2.x {
|
|
return 1, 1
|
|
}
|
|
return -1, -1
|
|
case -1:
|
|
if l.p1.x < l.p2.x {
|
|
return 1, -1
|
|
}
|
|
return -1, 1
|
|
default:
|
|
panic(s)
|
|
}
|
|
}
|
|
|
|
func parse(flines []string) (lines []Line) {
|
|
for _, l := range flines {
|
|
s, e := aoc.Cut(l, " -> ")
|
|
x1, y1 := aoc.Cut(s, ",")
|
|
x2, y2 := aoc.Cut(e, ",")
|
|
p1 := Point{
|
|
x: aoc.MustInt(x1),
|
|
y: aoc.MustInt(y1),
|
|
}
|
|
p2 := Point{
|
|
x: aoc.MustInt(x2),
|
|
y: aoc.MustInt(y2),
|
|
}
|
|
if p1.x > p2.x || p1.y > p2.y {
|
|
// This point is backwards!
|
|
p1, p2 = p2, p1
|
|
}
|
|
lines = append(lines, Line{p1: p1, p2: p2})
|
|
}
|
|
return
|
|
}
|
|
func part1(flines []string) int {
|
|
grid := make(map[Point]int)
|
|
for _, l := range parse(flines) {
|
|
switch l.Slope() {
|
|
case 0:
|
|
y := l.p1.y
|
|
for x := l.p1.x; x <= l.p2.x; x++ {
|
|
grid[Point{x: x, y: y}]++
|
|
}
|
|
case math.Inf(+1), math.Inf(-1):
|
|
x := l.p1.x
|
|
for y := l.p1.y; y <= l.p2.y; y++ {
|
|
grid[Point{x: x, y: y}]++
|
|
}
|
|
}
|
|
}
|
|
var count int
|
|
for _, c := range grid {
|
|
if c > 1 {
|
|
count++
|
|
}
|
|
}
|
|
return count
|
|
}
|
|
|
|
func part2(flines []string) int {
|
|
grid := make(map[Point]int)
|
|
for _, l := range parse(flines) {
|
|
dx, dy := l.Delta()
|
|
for p := l.p1; p != l.p2; p = p.Plus(dx, dy) {
|
|
grid[p]++
|
|
}
|
|
grid[l.p2]++
|
|
}
|
|
var count int
|
|
for _, c := range grid {
|
|
if c > 1 {
|
|
count++
|
|
}
|
|
}
|
|
return count
|
|
}
|
|
|
|
func main() {
|
|
lines := aoc.Input().ReadLines("day5.txt")
|
|
fmt.Println(part1(lines))
|
|
fmt.Println(part2(lines))
|
|
}
|