Day 17 Complete
This commit is contained in:
parent
a6e0380b18
commit
5ccafb37c4
1
2016/day17/input
Normal file
1
2016/day17/input
Normal file
@ -0,0 +1 @@
|
|||||||
|
pvhmgsws
|
111
2016/day17/main.go
Normal file
111
2016/day17/main.go
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"../../"
|
||||||
|
)
|
||||||
|
|
||||||
|
var gridWidth, gridHeight int
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var passcode string
|
||||||
|
gridWidth, gridHeight = 4, 4
|
||||||
|
|
||||||
|
if len(os.Args) < 2 {
|
||||||
|
printUsageAndExit()
|
||||||
|
}
|
||||||
|
passcode = os.Args[1]
|
||||||
|
if len(os.Args) >= 4 {
|
||||||
|
gridWidth = aoc.Atoi(os.Args[2])
|
||||||
|
gridHeight = aoc.Atoi(os.Args[3])
|
||||||
|
}
|
||||||
|
foundPaths := findPaths("", passcode)
|
||||||
|
if len(foundPaths) == 0 {
|
||||||
|
fmt.Println("Couldn't find a valid path!")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
shortestPath := foundPaths[0]
|
||||||
|
longestPath := foundPaths[0]
|
||||||
|
for i := range foundPaths {
|
||||||
|
if len(foundPaths[i]) < len(shortestPath) {
|
||||||
|
shortestPath = foundPaths[i]
|
||||||
|
}
|
||||||
|
if len(foundPaths[i]) > len(longestPath) {
|
||||||
|
longestPath = foundPaths[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("Shortest Path:", shortestPath)
|
||||||
|
fmt.Println("Longest Path Length:", len(longestPath))
|
||||||
|
}
|
||||||
|
|
||||||
|
func findPaths(path, passcode string) []string {
|
||||||
|
var ret []string
|
||||||
|
cX, cY := currPos(path)
|
||||||
|
if cY == gridHeight-1 && cX == gridWidth-1 {
|
||||||
|
return []string{path}
|
||||||
|
}
|
||||||
|
if cY > 0 && doorIsOpen(path, passcode, 'U') {
|
||||||
|
ret = append(ret, findPaths(path+"U", passcode)...)
|
||||||
|
}
|
||||||
|
if cY < (gridHeight-1) && doorIsOpen(path, passcode, 'D') {
|
||||||
|
ret = append(ret, findPaths(path+"D", passcode)...)
|
||||||
|
}
|
||||||
|
if cX > 0 && doorIsOpen(path, passcode, 'L') {
|
||||||
|
ret = append(ret, findPaths(path+"L", passcode)...)
|
||||||
|
}
|
||||||
|
if cX < (gridWidth-1) && doorIsOpen(path, passcode, 'R') {
|
||||||
|
ret = append(ret, findPaths(path+"R", passcode)...)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// We cache the last hash calculated
|
||||||
|
// It should speed things up a little
|
||||||
|
var lastHashInput string
|
||||||
|
var lastHash string
|
||||||
|
|
||||||
|
func doorIsOpen(path, passcode string, dir rune) bool {
|
||||||
|
if lastHashInput != passcode+path {
|
||||||
|
lastHashInput = passcode + path
|
||||||
|
lastHash = fmt.Sprintf("%x", md5.Sum([]byte(lastHashInput)))
|
||||||
|
}
|
||||||
|
switch dir {
|
||||||
|
case 'U':
|
||||||
|
return lastHash[0] >= 'b' && lastHash[0] <= 'f'
|
||||||
|
case 'D':
|
||||||
|
return lastHash[1] >= 'b' && lastHash[1] <= 'f'
|
||||||
|
case 'L':
|
||||||
|
return lastHash[2] >= 'b' && lastHash[2] <= 'f'
|
||||||
|
case 'R':
|
||||||
|
return lastHash[3] >= 'b' && lastHash[3] <= 'f'
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func currPos(path string) (int, int) {
|
||||||
|
var cX, cY int
|
||||||
|
for i := range path {
|
||||||
|
switch path[i] {
|
||||||
|
case 'U':
|
||||||
|
cY--
|
||||||
|
case 'D':
|
||||||
|
cY++
|
||||||
|
case 'L':
|
||||||
|
cX--
|
||||||
|
case 'R':
|
||||||
|
cX++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cX, cY
|
||||||
|
}
|
||||||
|
|
||||||
|
func PrintState(path, passcode string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func printUsageAndExit() {
|
||||||
|
fmt.Println("Usage: ./day17 <passcode> <gridWidth> <gridHeight>")
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
94
2016/day17/problem
Normal file
94
2016/day17/problem
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
Advent of Code
|
||||||
|
|
||||||
|
--- Day 17: Two Steps Forward ---
|
||||||
|
|
||||||
|
You're trying to access a secure vault protected by a 4x4 grid of small rooms connected by
|
||||||
|
doors. You start in the top-left room (marked S), and you can access the vault (marked V) once
|
||||||
|
you reach the bottom-right room:
|
||||||
|
|
||||||
|
#########
|
||||||
|
#S| | | #
|
||||||
|
#-#-#-#-#
|
||||||
|
# | | | #
|
||||||
|
#-#-#-#-#
|
||||||
|
# | | | #
|
||||||
|
#-#-#-#-#
|
||||||
|
# | | |
|
||||||
|
####### V
|
||||||
|
|
||||||
|
Fixed walls are marked with #, and doors are marked with - or |.
|
||||||
|
|
||||||
|
The doors in your current room are either open or closed (and locked) based on the hexadecimal
|
||||||
|
MD5 hash of a passcode (your puzzle input) followed by a sequence of uppercase characters
|
||||||
|
representing the path you have taken so far (U for up, D for down, L for left, and R for
|
||||||
|
right).
|
||||||
|
|
||||||
|
Only the first four characters of the hash are used; they represent, respectively, the doors
|
||||||
|
up, down, left, and right from your current position. Any b, c, d, e, or f means that the
|
||||||
|
corresponding door is open; any other character (any number or a) means that the corresponding
|
||||||
|
door is closed and locked.
|
||||||
|
|
||||||
|
To access the vault, all you need to do is reach the bottom-right room; reaching this room
|
||||||
|
opens the vault and all doors in the maze.
|
||||||
|
|
||||||
|
For example, suppose the passcode is hijkl. Initially, you have taken no steps, and so your
|
||||||
|
path is empty: you simply find the MD5 hash of hijkl alone. The first four characters of this
|
||||||
|
hash are ced9, which indicate that up is open (c), down is open (e), left is open (d), and
|
||||||
|
right is closed and locked (9). Because you start in the top-left corner, there are no "up" or
|
||||||
|
"left" doors to be open, so your only choice is down.
|
||||||
|
|
||||||
|
Next, having gone only one step (down, or D), you find the hash of hijklD. This produces f2bc,
|
||||||
|
which indicates that you can go back up, left (but that's a wall), or right. Going right means
|
||||||
|
hashing hijklDR to get 5745 - all doors closed and locked. However, going up instead is
|
||||||
|
worthwhile: even though it returns you to the room you started in, your path would then be DU,
|
||||||
|
opening a different set of doors.
|
||||||
|
|
||||||
|
After going DU (and then hashing hijklDU to get 528e), only the right door is open; after
|
||||||
|
going DUR, all doors lock. (Fortunately, your actual passcode is not hijkl).
|
||||||
|
|
||||||
|
Passcodes actually used by Easter Bunny Vault Security do allow access to the vault if you
|
||||||
|
know the right path. For example:
|
||||||
|
|
||||||
|
• If your passcode were ihgpwlah, the shortest path would be DDRRRD.
|
||||||
|
• With kglvqrro, the shortest path would be DDUDRLRRUDRD.
|
||||||
|
• With ulqzkmiv, the shortest would be DRURDRUDDLLDLUURRDULRLDUUDDDRR.
|
||||||
|
|
||||||
|
Given your vault's passcode, what is the shortest path (the actual path, not just the length)
|
||||||
|
to reach the vault?
|
||||||
|
|
||||||
|
Your puzzle answer was __________________.
|
||||||
|
|
||||||
|
--- Part Two ---
|
||||||
|
|
||||||
|
You're curious how robust this security solution really is, and so you decide to find longer
|
||||||
|
and longer paths which still provide access to the vault. You remember that paths always end
|
||||||
|
the first time they reach the bottom-right room (that is, they can never pass through it, only
|
||||||
|
end in it).
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
• If your passcode were ihgpwlah, the longest path would take 370 steps.
|
||||||
|
• With kglvqrro, the longest path would be 492 steps long.
|
||||||
|
• With ulqzkmiv, the longest path would be 830 steps long.
|
||||||
|
|
||||||
|
What is the length of the longest path that reaches the vault?
|
||||||
|
|
||||||
|
Your puzzle answer was _______.
|
||||||
|
|
||||||
|
References
|
||||||
|
|
||||||
|
Visible links
|
||||||
|
. http://adventofcode.com/
|
||||||
|
. http://adventofcode.com/2016/about
|
||||||
|
. http://adventofcode.com/2016/support
|
||||||
|
. http://adventofcode.com/2016/events
|
||||||
|
. http://adventofcode.com/2016/settings
|
||||||
|
. http://adventofcode.com/2016/auth/logout
|
||||||
|
. http://adventofcode.com/2016
|
||||||
|
. http://adventofcode.com/2016
|
||||||
|
. http://adventofcode.com/2016/leaderboard
|
||||||
|
. http://adventofcode.com/2016/stats
|
||||||
|
. http://adventofcode.com/2016/sponsors
|
||||||
|
. http://adventofcode.com/2016/sponsors
|
||||||
|
. https://en.wikipedia.org/wiki/MD5
|
||||||
|
. http://adventofcode.com/2016
|
16
helpers.go
16
helpers.go
@ -3,12 +3,13 @@ package aoc
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func stdinToStringSlice() []string {
|
func StdinToStringSlice() []string {
|
||||||
var input []string
|
var input []string
|
||||||
scanner := bufio.NewScanner(os.Stdin)
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
@ -17,7 +18,7 @@ func stdinToStringSlice() []string {
|
|||||||
return input
|
return input
|
||||||
}
|
}
|
||||||
|
|
||||||
func atoi(i string) int {
|
func Atoi(i string) int {
|
||||||
var ret int
|
var ret int
|
||||||
var err error
|
var err error
|
||||||
if ret, err = strconv.Atoi(i); err != nil {
|
if ret, err = strconv.Atoi(i); err != nil {
|
||||||
@ -26,11 +27,11 @@ func atoi(i string) int {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func itoa(i int) string {
|
func Itoa(i int) string {
|
||||||
return strconv.Itoa(i)
|
return strconv.Itoa(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
func stdinToString() string {
|
func StdinToString() string {
|
||||||
var input string
|
var input string
|
||||||
scanner := bufio.NewScanner(os.Stdin)
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
@ -39,11 +40,12 @@ func stdinToString() string {
|
|||||||
return input
|
return input
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileToString(fn string) string {
|
func FileToString(fn string) string {
|
||||||
var c []byte
|
var c []byte
|
||||||
c, err = ioutil.Readfile(filename)
|
var err error
|
||||||
|
c, err = ioutil.ReadFile(fn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Unable to read file: " + filename)
|
fmt.Println("Unable to read file: " + fn)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
return string(c)
|
return string(c)
|
||||||
|
Loading…
Reference in New Issue
Block a user