diff --git a/2021/12/go.mod b/2021/12/go.mod new file mode 100644 index 0000000..40c9284 --- /dev/null +++ b/2021/12/go.mod @@ -0,0 +1,9 @@ +module AoC/2021/12 + +require AoC/2021/common v0.0.0 + +require github.com/joho/godotenv v1.4.0 // indirect + +replace AoC/2021/common v0.0.0 => ../common + +go 1.17 diff --git a/2021/12/go.sum b/2021/12/go.sum new file mode 100644 index 0000000..8c9f290 --- /dev/null +++ b/2021/12/go.sum @@ -0,0 +1,2 @@ +github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= +github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= diff --git a/2021/12/main.go b/2021/12/main.go new file mode 100644 index 0000000..e486afb --- /dev/null +++ b/2021/12/main.go @@ -0,0 +1,144 @@ +package main + +import ( + aoc "AoC/2021/common" + "bufio" + "strings" +) + +type cave struct { + large bool + connected []string +} + +func connect(system map[string] cave, a string, b string) map[string] cave { + if _, exists := system[a]; !exists { + c := cave{strings.ToUpper(a) == a, make([]string, 0)} + system[a] = c + } + + c := system[a] + c.connected = append(c.connected, b) + system[a] = c + + return system +} + +func processInput(input *bufio.Scanner) map[string] cave { + system := make(map[string] cave) + + for input.Scan() { + line := input.Text() + + connection := strings.Split(line, "-") + + system = connect(system, connection[0], connection[1]) + system = connect(system, connection[1], connection[0]) + + } + + return system +} + +func router1(system map[string] cave, visited []string, current string) int { + if current == "end" { + return 1 + } + + sum := 0 + outer: + for _, c := range system[current].connected { + for _, v := range visited { + if v == c { + if !system[c].large { + continue outer + } + break + } + } + + var s int + s = router1(system, append(visited, c), c) + sum += s + } + + return sum +} + +func router2(system map[string] cave, visited []string, current string, twiced bool) int { + if current == "end" { + return 1 + } + + sum := 0 + outer: + for _, c := range system[current].connected { + t := twiced + for _, v := range visited { + if v == c { + if !system[c].large { + if twiced || c == "start" { + continue outer + } + t = true + } + break + } + } + + s := router2(system, append(visited, c), c, t) + sum += s + } + + return sum +} + +func main() { + challenge := aoc.New(2021, 12) + + challenge.Test(`start-A +start-b +A-c +A-b +b-d +A-end +b-end`, []int{10, 36}) + + challenge.Test(`dc-end +HN-start +start-kj +dc-start +dc-HN +LN-dc +HN-end +kj-sa +kj-HN +kj-dc`, []int{19, 103}) + + challenge.Test(`fs-end +he-DX +fs-he +start-DX +pj-DX +end-zg +zg-sl +zg-pj +pj-he +RW-he +fs-DX +pj-RW +zg-RW +start-pj +he-WI +zg-he +pj-fs +start-RW`, []int{226, 3509}) + + challenge.Solution(1, func (input *bufio.Scanner) int { + return router1(processInput(input), []string{"start"}, "start") + }) + + challenge.Solution(2, func (input *bufio.Scanner) int { + return router2(processInput(input), []string{"start"}, "start", false) + }) +}