2021 Day 12 Complete!
This commit is contained in:
parent
6c3dc59afc
commit
00f1bff786
23
2021/day12/input
Normal file
23
2021/day12/input
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
pn-TY
|
||||||
|
rp-ka
|
||||||
|
az-aw
|
||||||
|
al-IV
|
||||||
|
pn-co
|
||||||
|
end-rp
|
||||||
|
aw-TY
|
||||||
|
rp-pn
|
||||||
|
al-rp
|
||||||
|
end-al
|
||||||
|
IV-co
|
||||||
|
end-TM
|
||||||
|
co-TY
|
||||||
|
TY-ka
|
||||||
|
aw-pn
|
||||||
|
aw-IV
|
||||||
|
pn-IV
|
||||||
|
IV-ka
|
||||||
|
TM-rp
|
||||||
|
aw-PD
|
||||||
|
start-IV
|
||||||
|
start-co
|
||||||
|
start-pn
|
158
2021/day12/main.go
Normal file
158
2021/day12/main.go
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
inp := h.StdinToStringSlice()
|
||||||
|
part1(BuildCaves(inp))
|
||||||
|
fmt.Println()
|
||||||
|
part2(BuildCaves(inp))
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildCaves(inp []string) map[string]Cave {
|
||||||
|
ret := make(map[string]Cave)
|
||||||
|
for i := range inp {
|
||||||
|
pts := strings.Split(inp[i], "-")
|
||||||
|
var c1, c2 Cave
|
||||||
|
var ok bool
|
||||||
|
if c1, ok = ret[pts[0]]; !ok {
|
||||||
|
c1 = NewCave(pts[0])
|
||||||
|
}
|
||||||
|
if c2, ok = ret[pts[1]]; !ok {
|
||||||
|
c2 = NewCave(pts[1])
|
||||||
|
}
|
||||||
|
if !c1.ExitsTo(c2) {
|
||||||
|
c1.Exits = append(c1.Exits, c2.Name)
|
||||||
|
}
|
||||||
|
if !c2.ExitsTo(c1) {
|
||||||
|
c2.Exits = append(c2.Exits, c1.Name)
|
||||||
|
}
|
||||||
|
ret[c1.Name] = c1
|
||||||
|
ret[c2.Name] = c2
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func part1(inp map[string]Cave) {
|
||||||
|
curr, _ := inp["start"]
|
||||||
|
res := part1_findPaths([]Cave{curr}, inp)
|
||||||
|
fmt.Println("# Part 1")
|
||||||
|
fmt.Println("There are", len(res), "paths")
|
||||||
|
}
|
||||||
|
|
||||||
|
func part1_shouldVisit(c string, path []Cave) bool {
|
||||||
|
if c[0] < 'A' || c[0] > 'Z' {
|
||||||
|
for i := range path {
|
||||||
|
if path[i].Name == c {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func part1_findPaths(path []Cave, system map[string]Cave) [][]Cave {
|
||||||
|
var ret [][]Cave
|
||||||
|
curr := path[len(path)-1]
|
||||||
|
if curr.Name == "end" {
|
||||||
|
return append(ret, path)
|
||||||
|
}
|
||||||
|
for _, c := range curr.Exits {
|
||||||
|
if part1_shouldVisit(c, path) {
|
||||||
|
newPaths := part1_findPaths(append(path, system[c]), system)
|
||||||
|
ret = append(ret, newPaths...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func part2(inp map[string]Cave) {
|
||||||
|
curr, _ := inp["start"]
|
||||||
|
res := part2_findPaths([]Cave{curr}, inp)
|
||||||
|
fmt.Println("# Part 2")
|
||||||
|
fmt.Println("There are", len(res), "paths")
|
||||||
|
}
|
||||||
|
|
||||||
|
func part2_shouldVisit(c string, path []Cave) bool {
|
||||||
|
if path[len(path)-1].Name == "end" {
|
||||||
|
// If the previous spot was end, we shouldn't visit anything
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if c[0] < 'A' || c[0] > 'Z' {
|
||||||
|
if c == "start" { // We never return to start
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Check if we've already visited this cave
|
||||||
|
visits := make(map[string]int)
|
||||||
|
var visited, twice bool
|
||||||
|
for i := range path {
|
||||||
|
if path[i].Name == c {
|
||||||
|
visited = true
|
||||||
|
}
|
||||||
|
visits[path[i].Name]++
|
||||||
|
if !path[i].Big && visits[path[i].Name] > 1 {
|
||||||
|
twice = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if visited && twice {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func part2_findPaths(path []Cave, system map[string]Cave) [][]Cave {
|
||||||
|
var ret [][]Cave
|
||||||
|
curr := path[len(path)-1]
|
||||||
|
if curr.Name == "end" {
|
||||||
|
return append(ret, path)
|
||||||
|
}
|
||||||
|
for _, c := range curr.Exits {
|
||||||
|
if part2_shouldVisit(c, path) {
|
||||||
|
newPaths := part2_findPaths(append(path, system[c]), system)
|
||||||
|
ret = append(ret, newPaths...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
type Cave struct {
|
||||||
|
Name string
|
||||||
|
Big bool
|
||||||
|
Exits []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCave(n string) Cave {
|
||||||
|
return Cave{
|
||||||
|
Name: n,
|
||||||
|
Big: (n[0] >= 'A' && n[0] <= 'Z'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Cave) ExitsTo(e Cave) bool {
|
||||||
|
for i := range c.Exits {
|
||||||
|
if c.Exits[i] == e.Name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Cave) String() string {
|
||||||
|
return c.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Cave) Detail() string {
|
||||||
|
return fmt.Sprintf("{%s -> %s}", c.Name, c.Exits)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PrintMap(inp map[string]Cave) {
|
||||||
|
for k := range inp {
|
||||||
|
fmt.Println(inp[k].Detail())
|
||||||
|
}
|
||||||
|
}
|
189
2021/day12/problem
Normal file
189
2021/day12/problem
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
# Advent of Code
|
||||||
|
|
||||||
|
--- Day 12: Passage Pathing ---
|
||||||
|
|
||||||
|
With your submarine's subterranean subsystems subsisting suboptimally, the only way you're getting out of this cave anytime soon is by finding a
|
||||||
|
path yourself. Not just a path - the only way to know if you've found the best path is to find all of them.
|
||||||
|
|
||||||
|
Fortunately, the sensors are still mostly working, and so you build a rough map of the remaining caves (your puzzle input). For example:
|
||||||
|
|
||||||
|
start-A
|
||||||
|
start-b
|
||||||
|
A-c
|
||||||
|
A-b
|
||||||
|
b-d
|
||||||
|
A-end
|
||||||
|
b-end
|
||||||
|
|
||||||
|
This is a list of how all of the caves are connected. You start in the cave named start, and your destination is the cave named end. An entry
|
||||||
|
like b-d means that cave b is connected to cave d - that is, you can move between them.
|
||||||
|
|
||||||
|
So, the above cave system looks roughly like this:
|
||||||
|
|
||||||
|
start
|
||||||
|
/ \
|
||||||
|
c--A-----b--d
|
||||||
|
\ /
|
||||||
|
end
|
||||||
|
|
||||||
|
Your goal is to find the number of distinct paths that start at start, end at end, and don't visit small caves more than once. There are two
|
||||||
|
types of caves: big caves (written in uppercase, like A) and small caves (written in lowercase, like b). It would be a waste of time to visit any
|
||||||
|
small cave more than once, but big caves are large enough that it might be worth visiting them multiple times. So, all paths you find should
|
||||||
|
visit small caves at most once, and can visit big caves any number of times.
|
||||||
|
|
||||||
|
Given these rules, there are 10 paths through this example cave system:
|
||||||
|
|
||||||
|
start,A,b,A,c,A,end
|
||||||
|
start,A,b,A,end
|
||||||
|
start,A,b,end
|
||||||
|
start,A,c,A,b,A,end
|
||||||
|
start,A,c,A,b,end
|
||||||
|
start,A,c,A,end
|
||||||
|
start,A,end
|
||||||
|
start,b,A,c,A,end
|
||||||
|
start,b,A,end
|
||||||
|
start,b,end
|
||||||
|
|
||||||
|
(Each line in the above list corresponds to a single path; the caves visited by that path are listed in the order they are visited and separated
|
||||||
|
by commas.)
|
||||||
|
|
||||||
|
Note that in this cave system, cave d is never visited by any path: to do so, cave b would need to be visited twice (once on the way to cave d
|
||||||
|
and a second time when returning from cave d), and since cave b is small, this is not allowed.
|
||||||
|
|
||||||
|
Here is a slightly larger example:
|
||||||
|
|
||||||
|
dc-end
|
||||||
|
HN-start
|
||||||
|
start-kj
|
||||||
|
dc-start
|
||||||
|
dc-HN
|
||||||
|
LN-dc
|
||||||
|
HN-end
|
||||||
|
kj-sa
|
||||||
|
kj-HN
|
||||||
|
kj-dc
|
||||||
|
|
||||||
|
The 19 paths through it are as follows:
|
||||||
|
|
||||||
|
start,HN,dc,HN,end
|
||||||
|
start,HN,dc,HN,kj,HN,end
|
||||||
|
start,HN,dc,end
|
||||||
|
start,HN,dc,kj,HN,end
|
||||||
|
start,HN,end
|
||||||
|
start,HN,kj,HN,dc,HN,end
|
||||||
|
start,HN,kj,HN,dc,end
|
||||||
|
start,HN,kj,HN,end
|
||||||
|
start,HN,kj,dc,HN,end
|
||||||
|
start,HN,kj,dc,end
|
||||||
|
start,dc,HN,end
|
||||||
|
start,dc,HN,kj,HN,end
|
||||||
|
start,dc,end
|
||||||
|
start,dc,kj,HN,end
|
||||||
|
start,kj,HN,dc,HN,end
|
||||||
|
start,kj,HN,dc,end
|
||||||
|
start,kj,HN,end
|
||||||
|
start,kj,dc,HN,end
|
||||||
|
start,kj,dc,end
|
||||||
|
|
||||||
|
Finally, this even larger example has 226 paths through it:
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
How many paths through this cave system are there that visit small caves at most once?
|
||||||
|
|
||||||
|
Your puzzle answer was 4413.
|
||||||
|
|
||||||
|
--- Part Two ---
|
||||||
|
|
||||||
|
After reviewing the available paths, you realize you might have time to visit a single small cave twice. Specifically, big caves can be visited
|
||||||
|
any number of times, a single small cave can be visited at most twice, and the remaining small caves can be visited at most once. However, the
|
||||||
|
caves named start and end can only be visited exactly once each: once you leave the start cave, you may not return to it, and once you reach the
|
||||||
|
end cave, the path must end immediately.
|
||||||
|
|
||||||
|
Now, the 36 possible paths through the first example above are:
|
||||||
|
|
||||||
|
start,A,b,A,b,A,c,A,end
|
||||||
|
start,A,b,A,b,A,end
|
||||||
|
start,A,b,A,b,end
|
||||||
|
start,A,b,A,c,A,b,A,end
|
||||||
|
start,A,b,A,c,A,b,end
|
||||||
|
start,A,b,A,c,A,c,A,end
|
||||||
|
start,A,b,A,c,A,end
|
||||||
|
start,A,b,A,end
|
||||||
|
start,A,b,d,b,A,c,A,end
|
||||||
|
start,A,b,d,b,A,end
|
||||||
|
start,A,b,d,b,end
|
||||||
|
start,A,b,end
|
||||||
|
start,A,c,A,b,A,b,A,end
|
||||||
|
start,A,c,A,b,A,b,end
|
||||||
|
start,A,c,A,b,A,c,A,end
|
||||||
|
start,A,c,A,b,A,end
|
||||||
|
start,A,c,A,b,d,b,A,end
|
||||||
|
start,A,c,A,b,d,b,end
|
||||||
|
start,A,c,A,b,end
|
||||||
|
start,A,c,A,c,A,b,A,end
|
||||||
|
start,A,c,A,c,A,b,end
|
||||||
|
start,A,c,A,c,A,end
|
||||||
|
start,A,c,A,end
|
||||||
|
start,A,end
|
||||||
|
start,b,A,b,A,c,A,end
|
||||||
|
start,b,A,b,A,end
|
||||||
|
start,b,A,b,end
|
||||||
|
start,b,A,c,A,b,A,end
|
||||||
|
start,b,A,c,A,b,end
|
||||||
|
start,b,A,c,A,c,A,end
|
||||||
|
start,b,A,c,A,end
|
||||||
|
start,b,A,end
|
||||||
|
start,b,d,b,A,c,A,end
|
||||||
|
start,b,d,b,A,end
|
||||||
|
start,b,d,b,end
|
||||||
|
start,b,end
|
||||||
|
|
||||||
|
The slightly larger example above now has 103 paths through it, and the even larger example now has 3509 paths through it.
|
||||||
|
|
||||||
|
Given these new rules, how many paths through this cave system are there?
|
||||||
|
|
||||||
|
Your puzzle answer was 118803.
|
||||||
|
|
||||||
|
Both parts of this puzzle are complete! They provide two gold stars: **
|
||||||
|
|
||||||
|
At this point, you should return to your Advent calendar and try another puzzle.
|
||||||
|
|
||||||
|
If you still want to see it, you can get your puzzle input.
|
||||||
|
|
||||||
|
References
|
||||||
|
|
||||||
|
Visible links
|
||||||
|
. https://adventofcode.com/
|
||||||
|
. https://adventofcode.com/2021/about
|
||||||
|
. https://adventofcode.com/2021/events
|
||||||
|
. https://adventofcode.com/2021/settings
|
||||||
|
. https://adventofcode.com/2021/auth/logout
|
||||||
|
. Advent of Code Supporter
|
||||||
|
https://adventofcode.com/2021/support
|
||||||
|
. https://adventofcode.com/2021
|
||||||
|
. https://adventofcode.com/2021
|
||||||
|
. https://adventofcode.com/2021/support
|
||||||
|
. https://adventofcode.com/2021/sponsors
|
||||||
|
. https://adventofcode.com/2021/leaderboard
|
||||||
|
. https://adventofcode.com/2021/stats
|
||||||
|
. https://adventofcode.com/2021/sponsors
|
||||||
|
. https://adventofcode.com/2021
|
||||||
|
. https://adventofcode.com/2021/day/12/input
|
7
2021/day12/testinput
Normal file
7
2021/day12/testinput
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
start-A
|
||||||
|
start-b
|
||||||
|
A-c
|
||||||
|
A-b
|
||||||
|
b-d
|
||||||
|
A-end
|
||||||
|
b-end
|
10
2021/day12/testinput2
Normal file
10
2021/day12/testinput2
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
dc-end
|
||||||
|
HN-start
|
||||||
|
start-kj
|
||||||
|
dc-start
|
||||||
|
dc-HN
|
||||||
|
LN-dc
|
||||||
|
HN-end
|
||||||
|
kj-sa
|
||||||
|
kj-HN
|
||||||
|
kj-dc
|
18
2021/day12/testinput3
Normal file
18
2021/day12/testinput3
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
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
|
Loading…
Reference in New Issue
Block a user