day 12
This commit is contained in:
parent
349e2a8f19
commit
6fe9d251bd
150
12/main.go
Normal file
150
12/main.go
Normal file
@ -0,0 +1,150 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
start := time.Now()
|
||||
partOne()
|
||||
duration := time.Since(start)
|
||||
partTwo()
|
||||
duration2 := time.Since(start)
|
||||
fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration)
|
||||
}
|
||||
|
||||
func makeScanner(test bool) *bufio.Scanner {
|
||||
var f *os.File
|
||||
if test {
|
||||
f, _ = os.Open("inputs/testinput")
|
||||
} else {
|
||||
f, _ = os.Open("inputs/input")
|
||||
}
|
||||
reader := bufio.NewReader(f)
|
||||
return bufio.NewScanner(reader)
|
||||
}
|
||||
|
||||
type room struct {
|
||||
name string
|
||||
links []string
|
||||
}
|
||||
|
||||
func isBigRoom(name string) bool {
|
||||
return strings.ToUpper(name) == name
|
||||
}
|
||||
|
||||
func canVisit(targetRoom room, visitedRooms []string) bool {
|
||||
if isBigRoom(targetRoom.name) {
|
||||
return true
|
||||
}
|
||||
for _, v := range visitedRooms {
|
||||
if targetRoom.name == v {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func doubleSmallAlready(visitedRooms []string) bool {
|
||||
counts := map[string]int{}
|
||||
for _, v := range visitedRooms {
|
||||
counts[v]++
|
||||
}
|
||||
for room, v := range counts {
|
||||
if v == 2 && !isBigRoom(room) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func descend(rooms map[string]room, currentRoom string, path []string, success chan bool, canVisitSmallRoomTwice bool) {
|
||||
var wg sync.WaitGroup
|
||||
if currentRoom == "end" {
|
||||
success <- true
|
||||
return
|
||||
}
|
||||
for _, link := range rooms[currentRoom].links {
|
||||
newPath := []string{currentRoom}
|
||||
newPath = append(newPath, path...)
|
||||
if canVisit(rooms[link], path) || // part one
|
||||
(canVisitSmallRoomTwice && !doubleSmallAlready(newPath) && link != "start") { // part two
|
||||
wg.Add(1)
|
||||
go func(link string, path []string) {
|
||||
defer wg.Done()
|
||||
descend(rooms, link, path, success, canVisitSmallRoomTwice)
|
||||
}(link, newPath)
|
||||
}
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func partOne() {
|
||||
scanner := makeScanner(false)
|
||||
|
||||
rooms := map[string]room{}
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
p := strings.Split(line, "-")
|
||||
// create rooms if we haven't seen them before
|
||||
if _, ok := rooms[p[0]]; !ok {
|
||||
rooms[p[0]] = room{name: p[0]}
|
||||
}
|
||||
if _, ok := rooms[p[1]]; !ok {
|
||||
rooms[p[1]] = room{name: p[1]}
|
||||
}
|
||||
// set up links
|
||||
a := rooms[p[0]]
|
||||
b := rooms[p[1]]
|
||||
a.links = append(a.links, rooms[p[1]].name)
|
||||
b.links = append(b.links, rooms[p[0]].name)
|
||||
rooms[p[0]] = a
|
||||
rooms[p[1]] = b
|
||||
}
|
||||
successes := make(chan bool, 10000)
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
descend(rooms, "start", []string{}, successes, false)
|
||||
}()
|
||||
wg.Wait()
|
||||
fmt.Printf("%+v\n", len(successes))
|
||||
}
|
||||
func partTwo() {
|
||||
scanner := makeScanner(false)
|
||||
|
||||
rooms := map[string]room{}
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
p := strings.Split(line, "-")
|
||||
// create rooms if we haven't seen them before
|
||||
if _, ok := rooms[p[0]]; !ok {
|
||||
rooms[p[0]] = room{name: p[0]}
|
||||
}
|
||||
if _, ok := rooms[p[1]]; !ok {
|
||||
rooms[p[1]] = room{name: p[1]}
|
||||
}
|
||||
// set up links
|
||||
a := rooms[p[0]]
|
||||
b := rooms[p[1]]
|
||||
a.links = append(a.links, rooms[p[1]].name)
|
||||
b.links = append(b.links, rooms[p[0]].name)
|
||||
rooms[p[0]] = a
|
||||
rooms[p[1]] = b
|
||||
}
|
||||
successes := make(chan bool, 200000)
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
descend(rooms, "start", []string{}, successes, true)
|
||||
}()
|
||||
wg.Wait()
|
||||
fmt.Printf("%+v\n", len(successes))
|
||||
}
|
Loading…
Reference in New Issue
Block a user