104 lines
2.3 KiB
Go
104 lines
2.3 KiB
Go
package main
|
|
|
|
import (
|
|
"log"
|
|
"os"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/thoas/go-funk"
|
|
)
|
|
|
|
func main() {
|
|
inputBytes, _ := os.ReadFile("input.txt")
|
|
inputs := strings.Split(string(inputBytes), "\n")
|
|
|
|
log.Println("Puzzle 1:", puzzle1(inputs))
|
|
log.Println("Puzzle 2:", puzzle2(inputs))
|
|
}
|
|
|
|
func puzzle1(input []string) int {
|
|
return do(input, false)
|
|
}
|
|
|
|
func puzzle2(input []string) int {
|
|
return do(input, true)
|
|
}
|
|
|
|
type lineEnd struct {
|
|
x, y int
|
|
}
|
|
|
|
type line struct {
|
|
start, end lineEnd
|
|
}
|
|
|
|
func do(input []string, puzzle2 bool) int {
|
|
// Parse input into lines of form "x1,y1 -> x2,y2"
|
|
lineRegex := regexp.MustCompile(`(\d+),(\d+)\s\->\s(\d+),(\d+)`)
|
|
lines := []line{}
|
|
for _, inputRow := range input {
|
|
lineMatch := lineRegex.FindStringSubmatch(inputRow)
|
|
x1, _ := strconv.Atoi(lineMatch[1])
|
|
y1, _ := strconv.Atoi(lineMatch[2])
|
|
x2, _ := strconv.Atoi(lineMatch[3])
|
|
y2, _ := strconv.Atoi(lineMatch[4])
|
|
lines = append(lines, line{
|
|
start: lineEnd{x1, y1},
|
|
end: lineEnd{x2, y2},
|
|
})
|
|
}
|
|
// Get maximum x and y values
|
|
maxX, maxY := 0, 0
|
|
for _, l := range lines {
|
|
if l.start.x > maxX {
|
|
maxX = l.start.x
|
|
}
|
|
if l.start.y > maxY {
|
|
maxY = l.start.y
|
|
}
|
|
if l.end.x > maxX {
|
|
maxX = l.end.x
|
|
}
|
|
if l.end.y > maxY {
|
|
maxY = l.end.y
|
|
}
|
|
}
|
|
// Create a 2D array of zeros
|
|
diagram := make([][]int, maxY+1)
|
|
for i := range diagram {
|
|
diagram[i] = make([]int, maxX+1)
|
|
}
|
|
// For each line, increment the value of the cells it crosses
|
|
for _, l := range lines {
|
|
if l.start.x == l.end.x || l.start.y == l.end.y {
|
|
// Vertical line or horizontal line
|
|
for x := funk.MinInt([]int{l.start.x, l.end.x}); x <= funk.MaxInt([]int{l.start.x, l.end.x}); x++ {
|
|
for y := funk.MinInt([]int{l.start.y, l.end.y}); y <= funk.MaxInt([]int{l.start.y, l.end.y}); y++ {
|
|
diagram[y][x]++
|
|
}
|
|
}
|
|
} else if puzzle2 && (l.start.x-l.end.x == l.start.y-l.end.y || l.start.x-l.end.x == l.end.y-l.start.y) {
|
|
// 45-degree diagonal line
|
|
xDir := funk.ShortIf(l.start.x > l.end.x, -1, 1).(int)
|
|
yDir := funk.ShortIf(l.start.y > l.end.y, -1, 1).(int)
|
|
x := l.start.x
|
|
for y := l.start.y; y != l.end.y+yDir; y += yDir {
|
|
diagram[y][x]++
|
|
x += xDir
|
|
}
|
|
}
|
|
}
|
|
// Count the number of cells that have more than one line crossing them
|
|
count := 0
|
|
for _, row := range diagram {
|
|
for _, cell := range row {
|
|
if cell > 1 {
|
|
count++
|
|
}
|
|
}
|
|
}
|
|
return count
|
|
}
|