Day 21 Complete
Added String Permutation helper to helpers file
This commit is contained in:
110
2016/day21/main.go
Normal file
110
2016/day21/main.go
Normal file
@@ -0,0 +1,110 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"../../"
|
||||
)
|
||||
|
||||
func main() {
|
||||
pw := "fbgdceah" // Part 2 Puzzle input
|
||||
input := aoc.StdinToStringSlice()
|
||||
if aoc.ArgIsSet("-1") {
|
||||
pw = "abcdefgh" // Part 1 Puzzle input
|
||||
pw = scramblePassword(pw, input)
|
||||
fmt.Println(scramblePassword(pw, input))
|
||||
return
|
||||
}
|
||||
fmt.Println(unscramblePassword(pw, input))
|
||||
}
|
||||
|
||||
func unscramblePassword(pw string, inst []string) string {
|
||||
// Brute force it.
|
||||
// Just get all permutations of the runes and return the one
|
||||
// for which the instructions return the input
|
||||
tst := aoc.StringPermutations(pw)
|
||||
for i := range tst {
|
||||
if scramblePassword(tst[i], inst) == pw {
|
||||
return tst[i]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func scramblePassword(pw string, inst []string) string {
|
||||
for i := range inst {
|
||||
pts := strings.Fields(inst[i])
|
||||
switch pts[0] + " " + pts[1] {
|
||||
case "swap position":
|
||||
pw = swapPos(pw, aoc.Atoi(pts[2]), aoc.Atoi(pts[5]))
|
||||
case "swap letter":
|
||||
pw = swapLetter(pw, pts[2], pts[5])
|
||||
case "reverse positions":
|
||||
pw = reverse(pw, aoc.Atoi(pts[2]), aoc.Atoi(pts[4]))
|
||||
case "rotate left":
|
||||
pw = rotate(pw, aoc.Atoi(pts[2])*-1)
|
||||
case "rotate right":
|
||||
pw = rotate(pw, aoc.Atoi(pts[2]))
|
||||
case "rotate based":
|
||||
rotIdx := strings.Index(pw, pts[6])
|
||||
if rotIdx >= 4 {
|
||||
rotIdx++
|
||||
}
|
||||
rotIdx++
|
||||
pw = rotate(pw, rotIdx)
|
||||
case "move position":
|
||||
pw = move(pw, aoc.Atoi(pts[2]), aoc.Atoi(pts[5]))
|
||||
}
|
||||
}
|
||||
return pw
|
||||
}
|
||||
|
||||
func swapPos(pw string, x, y int) string {
|
||||
r := []rune(pw)
|
||||
r[x], r[y] = r[y], r[x]
|
||||
return string(r)
|
||||
}
|
||||
|
||||
func swapLetter(pw string, x, y string) string {
|
||||
xPos := strings.Index(pw, x)
|
||||
yPos := strings.Index(pw, y)
|
||||
return swapPos(pw, xPos, yPos)
|
||||
}
|
||||
|
||||
func rotate(pw string, steps int) string {
|
||||
r := []rune(pw)
|
||||
var x rune
|
||||
for steps < 0 {
|
||||
// Left rotate (shift & push)
|
||||
x, r = r[0], r[1:]
|
||||
r = append(r, x)
|
||||
steps++
|
||||
}
|
||||
for steps > 0 {
|
||||
// Right rotate (pop & unshift)
|
||||
x, r = r[len(r)-1], r[:len(r)-1]
|
||||
r = append([]rune{x}, r...)
|
||||
steps--
|
||||
}
|
||||
return string(r)
|
||||
}
|
||||
|
||||
func reverse(pw string, beg, end int) string {
|
||||
revStr := pw[beg : end+1]
|
||||
runes := []rune(revStr)
|
||||
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
|
||||
runes[i], runes[j] = runes[j], runes[i]
|
||||
}
|
||||
return pw[:beg] + string(runes) + pw[end+1:]
|
||||
}
|
||||
|
||||
func move(pw string, x, y int) string {
|
||||
r := []rune(pw)
|
||||
// Cut element at x
|
||||
mov := r[x]
|
||||
r = append(r[:x], r[x+1:]...)
|
||||
// Insert at y
|
||||
r = append(r[:y], append([]rune{mov}, r[y:]...)...)
|
||||
return string(r)
|
||||
}
|
||||
Reference in New Issue
Block a user