2021 Day 4 & Day 5 Complete
This commit is contained in:
203
2021/day05/main.go
Normal file
203
2021/day05/main.go
Normal file
@@ -0,0 +1,203 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||
)
|
||||
|
||||
var minX, maxX, minY, maxY int
|
||||
|
||||
func main() {
|
||||
maxX = h.MIN_INT
|
||||
minX = h.MAX_INT
|
||||
maxY = h.MIN_INT
|
||||
minY = h.MAX_INT
|
||||
inp := h.StdinToStringSlice()
|
||||
lines := parseLines(inp)
|
||||
|
||||
fmt.Println("# Part 1")
|
||||
findDangerSpots(filterStraight(lines))
|
||||
fmt.Println("# Part 2")
|
||||
findDangerSpots(lines)
|
||||
}
|
||||
|
||||
var ventMap map[h.Coordinate]int
|
||||
|
||||
var dangerSpots []h.Coordinate
|
||||
|
||||
func dingMap(c h.Coordinate) {
|
||||
s := ventMap[c]
|
||||
s++
|
||||
if s == 2 {
|
||||
dangerSpots = append(dangerSpots, c)
|
||||
}
|
||||
ventMap[c] = s
|
||||
}
|
||||
|
||||
func findDangerSpots(lines []Line) {
|
||||
ventMap = make(map[h.Coordinate]int)
|
||||
for i := range lines {
|
||||
updateMinMax(lines[i])
|
||||
}
|
||||
for _, l := range lines {
|
||||
// Find all points on this line
|
||||
// All lines are 0 or 45 deg, so slope should always be 0,1,-1,INF,-INF
|
||||
if l.start.X == l.end.X { // INF, -INF: vertical
|
||||
for y := l.lowestY(); y <= l.highestY(); y++ {
|
||||
dingMap(h.Coordinate{X: l.start.X, Y: y})
|
||||
}
|
||||
} else if l.start.Y == l.end.Y { //0: horizontal
|
||||
for x := l.start.X; x <= l.end.X; x++ {
|
||||
dingMap(h.Coordinate{Y: l.start.Y, X: x})
|
||||
}
|
||||
} else { // 1 or -1
|
||||
y := l.start.Y
|
||||
x := l.start.X
|
||||
dingMap(h.Coordinate{Y: y, X: x})
|
||||
|
||||
diffY := -1
|
||||
if l.start.Y < l.end.Y {
|
||||
diffY = 1
|
||||
}
|
||||
|
||||
for x != l.end.X && y != l.end.Y {
|
||||
x += 1
|
||||
y += diffY
|
||||
dingMap(h.Coordinate{Y: y, X: x})
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println("Danger Spots:", len(dangerSpots))
|
||||
}
|
||||
|
||||
type Line struct {
|
||||
start h.Coordinate
|
||||
end h.Coordinate
|
||||
|
||||
stX float64
|
||||
stY float64
|
||||
edX float64
|
||||
edY float64
|
||||
|
||||
slope float64
|
||||
}
|
||||
|
||||
func (l *Line) lowestY() int {
|
||||
if l.start.Y < l.end.Y {
|
||||
return l.start.Y
|
||||
}
|
||||
return l.end.Y
|
||||
}
|
||||
|
||||
func (l *Line) highestY() int {
|
||||
if l.start.Y > l.end.Y {
|
||||
return l.start.Y
|
||||
}
|
||||
return l.end.Y
|
||||
}
|
||||
|
||||
func (l *Line) intersects(c h.Coordinate) bool {
|
||||
ptX := float64(c.X)
|
||||
ptY := float64(c.Y)
|
||||
if (c.X == l.start.X && c.Y == l.start.Y) || (c.X == l.end.X && c.Y == l.end.Y) {
|
||||
return true
|
||||
}
|
||||
if c.X < l.start.X || c.X > l.end.X {
|
||||
return false
|
||||
}
|
||||
if (c.Y < l.start.Y && c.Y < l.end.Y) || (c.Y > l.start.Y && c.Y > l.end.Y) {
|
||||
return false
|
||||
}
|
||||
// Check if our slope is infinite
|
||||
if l.start.X == l.end.X {
|
||||
if l.start.Y < l.end.Y {
|
||||
return c.X == l.start.X && c.Y >= l.start.Y && c.Y <= l.end.Y
|
||||
} else {
|
||||
return c.X == l.start.X && c.Y <= l.start.Y && c.Y >= l.end.Y
|
||||
}
|
||||
}
|
||||
return slope(ptX, ptY, l.stX, l.stY) == l.slope
|
||||
}
|
||||
|
||||
func (l Line) String() string {
|
||||
return fmt.Sprintf("%d,%d -> %d,%d; [%f]", l.start.X, l.start.Y, l.end.X, l.end.Y, l.slope)
|
||||
}
|
||||
|
||||
func LineFromString(str string) Line {
|
||||
start := h.Coordinate{}
|
||||
end := h.Coordinate{}
|
||||
r := strings.NewReader(str)
|
||||
_, err := fmt.Fscanf(r, "%d,%d -> %d,%d", &start.X, &start.Y, &end.X, &end.Y)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var l Line
|
||||
if start.X < end.X {
|
||||
l = Line{
|
||||
start: start,
|
||||
end: end,
|
||||
}
|
||||
} else {
|
||||
l = Line{
|
||||
start: end,
|
||||
end: start,
|
||||
}
|
||||
}
|
||||
l.stX = float64(l.start.X)
|
||||
l.stY = float64(l.start.Y)
|
||||
l.edX = float64(l.end.X)
|
||||
l.edY = float64(l.end.Y)
|
||||
l.slope = slope(l.stX, l.stY, l.edX, l.edY)
|
||||
return l
|
||||
}
|
||||
|
||||
func updateMinMax(line Line) {
|
||||
if line.start.X < minX {
|
||||
minX = line.start.X
|
||||
}
|
||||
if line.start.X > maxX {
|
||||
maxX = line.start.X
|
||||
}
|
||||
if line.end.X < minX {
|
||||
minX = line.end.X
|
||||
}
|
||||
if line.end.X > maxX {
|
||||
maxX = line.end.X
|
||||
}
|
||||
if line.start.Y < minY {
|
||||
minY = line.start.Y
|
||||
}
|
||||
if line.start.Y > maxY {
|
||||
maxY = line.start.Y
|
||||
}
|
||||
if line.end.Y < minY {
|
||||
minY = line.end.Y
|
||||
}
|
||||
if line.end.Y > maxY {
|
||||
maxY = line.end.Y
|
||||
}
|
||||
}
|
||||
|
||||
func parseLines(inp []string) []Line {
|
||||
var ret []Line
|
||||
for i := range inp {
|
||||
ret = append(ret, LineFromString(inp[i]))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func filterStraight(lines []Line) []Line {
|
||||
var ret []Line
|
||||
for i := range lines {
|
||||
if lines[i].start.X == lines[i].end.X || lines[i].start.Y == lines[i].end.Y {
|
||||
ret = append(ret, lines[i])
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func slope(x1, y1, x2, y2 float64) float64 {
|
||||
return (y1 - y2) / (x1 - x2)
|
||||
}
|
||||
Reference in New Issue
Block a user