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