2021 Day 12 Complete!
This commit is contained in:
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())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user