summaryrefslogtreecommitdiff
path: root/day10/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'day10/main.go')
-rw-r--r--day10/main.go102
1 files changed, 102 insertions, 0 deletions
diff --git a/day10/main.go b/day10/main.go
new file mode 100644
index 0000000..e122082
--- /dev/null
+++ b/day10/main.go
@@ -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
+}