Watch
1
0
Fork
You've already forked advent-of-code
0

2021 Day 5

This commit is contained in:
Jeremy Kaplan 2021-12-04 22:10:09 -08:00
commit 6e64e705b3
2 changed files with 171 additions and 0 deletions

View file

@ -2,6 +2,8 @@ package aoc
import ( import (
"bufio" "bufio"
"io"
"io/fs"
"os" "os"
"strconv" "strconv"
"strings" "strings"
@ -36,3 +38,49 @@ func MustInt(s string) int {
} }
return i return i
} }
type Inputs struct {
fs fs.FS
}
func (i Inputs) ReadLines(path string) (lines []string) {
f, err := i.fs.Open(path)
if err != nil {
panic(err)
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return lines
}
func (i Inputs) ReadFile(path string) string {
f, err := i.fs.Open(path)
if err != nil {
panic(err)
}
defer f.Close()
b, err := io.ReadAll(f)
if err != nil {
panic(err)
}
return strings.TrimSpace(string(b))
}
func Input() Inputs {
if len(os.Args) > 1 {
return Inputs{os.DirFS(os.Args[1])}
}
return Inputs{os.DirFS("./input")}
}
// Cut will be added to strings in Go 1.18, so hack it in for now!
func Cut(s, sep string) (before, after string) {
if i := strings.Index(s, sep); i >= 0 {
return s[:i], s[i+len(sep):]
}
panic("Separator was not found in string")
}

123
2021/day5/main.go Normal file
View file

@ -0,0 +1,123 @@
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))
}