Day 10
This commit is contained in:
102
day10/main.go
Normal file
102
day10/main.go
Normal file
@ -0,0 +1,102 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(find(readData("example.txt")))
|
||||
fmt.Println(36, 81)
|
||||
fmt.Println(find(readData("data.txt")))
|
||||
}
|
||||
|
||||
type Candidate struct {
|
||||
X, Y int
|
||||
Alt byte
|
||||
Head *TrailHead
|
||||
}
|
||||
|
||||
func (c Candidate) Identity() int {
|
||||
return (c.X << 16) | c.Y
|
||||
}
|
||||
|
||||
type TrailHead struct {
|
||||
Reaches map[int]bool
|
||||
}
|
||||
|
||||
func findNextCandidates(x, y int, targetAlt byte, head *TrailHead, topo [][]byte) (result []Candidate) {
|
||||
if x > 0 && topo[y][x-1] == targetAlt {
|
||||
result = append(result, Candidate{x - 1, y, targetAlt, head})
|
||||
}
|
||||
if x < len(topo[y])-1 && topo[y][x+1] == targetAlt {
|
||||
result = append(result, Candidate{x + 1, y, targetAlt, head})
|
||||
}
|
||||
if y > 0 && topo[y-1][x] == targetAlt {
|
||||
result = append(result, Candidate{x, y - 1, targetAlt, head})
|
||||
}
|
||||
if y < len(topo)-1 && topo[y+1][x] == targetAlt {
|
||||
result = append(result, Candidate{x, y + 1, targetAlt, head})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func find(topo [][]byte) (resultPart1, resultPart2 int) {
|
||||
candidates := make([]Candidate, 0)
|
||||
for y, line := range topo {
|
||||
for x, alt := range line {
|
||||
if alt == 0 {
|
||||
trailhead := &TrailHead{make(map[int]bool)}
|
||||
candidate := Candidate{x, y, alt, trailhead}
|
||||
candidates = append(candidates, candidate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for len(candidates) > 0 {
|
||||
current := candidates[len(candidates)-1]
|
||||
candidates = candidates[:len(candidates)-1]
|
||||
|
||||
nextCandidates := findNextCandidates(current.X, current.Y, current.Alt+1, current.Head, topo)
|
||||
if current.Alt == 8 {
|
||||
for _, summit := range nextCandidates {
|
||||
id := summit.Identity()
|
||||
_, alreadyIn := summit.Head.Reaches[id]
|
||||
if !alreadyIn {
|
||||
summit.Head.Reaches[id] = true
|
||||
resultPart1++
|
||||
}
|
||||
}
|
||||
resultPart2 += len(nextCandidates)
|
||||
} else {
|
||||
candidates = append(candidates, nextCandidates...)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func readData(fileName string) (topo [][]byte) {
|
||||
fp, err := os.Open(fileName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(fp)
|
||||
for scanner.Scan() {
|
||||
line := []byte(strings.TrimSpace(scanner.Text()))
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
for i := range line {
|
||||
line[i] = line[i] - '0'
|
||||
}
|
||||
|
||||
topo = append(topo, line)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user