Day 21 Complete
Added String Permutation helper to helpers file
This commit is contained in:
		
							
								
								
									
										100
									
								
								2016/day21/input
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								2016/day21/input
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
			
		||||
swap letter e with letter h
 | 
			
		||||
swap letter f with letter g
 | 
			
		||||
move position 6 to position 3
 | 
			
		||||
reverse positions 1 through 6
 | 
			
		||||
swap letter b with letter a
 | 
			
		||||
swap letter a with letter f
 | 
			
		||||
rotate based on position of letter e
 | 
			
		||||
swap position 7 with position 2
 | 
			
		||||
rotate based on position of letter e
 | 
			
		||||
swap letter c with letter e
 | 
			
		||||
rotate based on position of letter f
 | 
			
		||||
rotate right 6 steps
 | 
			
		||||
swap letter c with letter f
 | 
			
		||||
reverse positions 3 through 7
 | 
			
		||||
swap letter c with letter b
 | 
			
		||||
swap position 1 with position 2
 | 
			
		||||
reverse positions 3 through 6
 | 
			
		||||
swap letter c with letter a
 | 
			
		||||
rotate left 0 steps
 | 
			
		||||
swap position 3 with position 0
 | 
			
		||||
swap letter b with letter e
 | 
			
		||||
reverse positions 4 through 7
 | 
			
		||||
move position 1 to position 4
 | 
			
		||||
swap position 6 with position 3
 | 
			
		||||
rotate left 6 steps
 | 
			
		||||
rotate right 0 steps
 | 
			
		||||
move position 7 to position 3
 | 
			
		||||
move position 3 to position 4
 | 
			
		||||
swap position 3 with position 2
 | 
			
		||||
reverse positions 1 through 6
 | 
			
		||||
move position 7 to position 5
 | 
			
		||||
reverse positions 4 through 5
 | 
			
		||||
rotate based on position of letter g
 | 
			
		||||
swap position 4 with position 2
 | 
			
		||||
reverse positions 1 through 5
 | 
			
		||||
rotate based on position of letter h
 | 
			
		||||
rotate based on position of letter f
 | 
			
		||||
rotate based on position of letter b
 | 
			
		||||
swap position 1 with position 4
 | 
			
		||||
swap letter b with letter h
 | 
			
		||||
rotate based on position of letter e
 | 
			
		||||
swap letter a with letter c
 | 
			
		||||
swap position 3 with position 5
 | 
			
		||||
rotate right 6 steps
 | 
			
		||||
rotate based on position of letter c
 | 
			
		||||
move position 2 to position 0
 | 
			
		||||
swap letter b with letter e
 | 
			
		||||
swap letter g with letter e
 | 
			
		||||
rotate based on position of letter d
 | 
			
		||||
swap position 6 with position 5
 | 
			
		||||
swap letter b with letter c
 | 
			
		||||
rotate based on position of letter e
 | 
			
		||||
rotate based on position of letter f
 | 
			
		||||
rotate based on position of letter f
 | 
			
		||||
move position 7 to position 0
 | 
			
		||||
rotate right 1 step
 | 
			
		||||
rotate right 7 steps
 | 
			
		||||
swap position 5 with position 6
 | 
			
		||||
move position 6 to position 7
 | 
			
		||||
rotate based on position of letter e
 | 
			
		||||
swap position 3 with position 1
 | 
			
		||||
swap position 4 with position 3
 | 
			
		||||
swap letter f with letter a
 | 
			
		||||
swap position 5 with position 2
 | 
			
		||||
rotate based on position of letter e
 | 
			
		||||
rotate left 3 steps
 | 
			
		||||
rotate left 1 step
 | 
			
		||||
rotate based on position of letter b
 | 
			
		||||
rotate left 6 steps
 | 
			
		||||
rotate based on position of letter b
 | 
			
		||||
rotate right 7 steps
 | 
			
		||||
swap position 0 with position 2
 | 
			
		||||
swap position 7 with position 5
 | 
			
		||||
rotate left 3 steps
 | 
			
		||||
reverse positions 4 through 5
 | 
			
		||||
move position 2 to position 5
 | 
			
		||||
swap letter c with letter f
 | 
			
		||||
swap letter g with letter e
 | 
			
		||||
rotate left 6 steps
 | 
			
		||||
swap position 4 with position 6
 | 
			
		||||
rotate based on position of letter h
 | 
			
		||||
rotate left 2 steps
 | 
			
		||||
swap letter c with letter a
 | 
			
		||||
rotate right 3 steps
 | 
			
		||||
rotate left 6 steps
 | 
			
		||||
swap letter b with letter f
 | 
			
		||||
swap position 6 with position 5
 | 
			
		||||
reverse positions 3 through 4
 | 
			
		||||
reverse positions 2 through 7
 | 
			
		||||
swap position 7 with position 4
 | 
			
		||||
rotate based on position of letter d
 | 
			
		||||
swap position 5 with position 3
 | 
			
		||||
swap letter c with letter b
 | 
			
		||||
swap position 7 with position 6
 | 
			
		||||
rotate based on position of letter c
 | 
			
		||||
reverse positions 0 through 7
 | 
			
		||||
reverse positions 2 through 4
 | 
			
		||||
rotate based on position of letter f
 | 
			
		||||
reverse positions 1 through 4
 | 
			
		||||
rotate right 7 steps
 | 
			
		||||
							
								
								
									
										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)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										69
									
								
								2016/day21/problem
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								2016/day21/problem
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
			
		||||
Advent of Code
 | 
			
		||||
 | 
			
		||||
--- Day 21: Scrambled Letters and Hash ---
 | 
			
		||||
 | 
			
		||||
   The computer system you're breaking into uses a weird scrambling function to store its passwords. It shouldn't be much trouble to create
 | 
			
		||||
   your own scrambled password so you can add it to the system; you just have to implement the scrambler.
 | 
			
		||||
 | 
			
		||||
   The scrambling function is a series of operations (the exact list is provided in your puzzle input). Starting with the password to be
 | 
			
		||||
   scrambled, apply each operation in succession to the string. The individual operations behave as follows:
 | 
			
		||||
 | 
			
		||||
     • swap position X with position Y means that the letters at indexes X and Y (counting from 0) should be swapped.
 | 
			
		||||
     • swap letter X with letter Y means that the letters X and Y should be swapped (regardless of where they appear in the string).
 | 
			
		||||
     • rotate left/right X steps means that the whole string should be rotated; for example, one right rotation would turn abcd into dabc.
 | 
			
		||||
     • rotate based on position of letter X means that the whole string should be rotated to the right based on the index of letter X
 | 
			
		||||
       (counting from 0) as determined before this instruction does any rotations. Once the index is determined, rotate the string to the
 | 
			
		||||
       right one time, plus a number of times equal to that index, plus one additional time if the index was at least 4.
 | 
			
		||||
     • reverse positions X through Y means that the span of letters at indexes X through Y (including the letters at X and Y) should be
 | 
			
		||||
       reversed in order.
 | 
			
		||||
     • move position X to position Y means that the letter which is at index X should be removed from the string, then inserted such that
 | 
			
		||||
       it ends up at index Y.
 | 
			
		||||
 | 
			
		||||
   For example, suppose you start with abcde and perform the following operations:
 | 
			
		||||
 | 
			
		||||
     • swap position 4 with position 0 swaps the first and last letters, producing the input for the next step, ebcda.
 | 
			
		||||
     • swap letter d with letter b swaps the positions of d and b: edcba.
 | 
			
		||||
     • reverse positions 0 through 4 causes the entire string to be reversed, producing abcde.
 | 
			
		||||
     • rotate left 1 step shifts all letters left one position, causing the first letter to wrap to the end of the string: bcdea.
 | 
			
		||||
     • move position 1 to position 4 removes the letter at position 1 (c), then inserts it at position 4 (the end of the string): bdeac.
 | 
			
		||||
     • move position 3 to position 0 removes the letter at position 3 (a), then inserts it at position 0 (the front of the string): abdec.
 | 
			
		||||
     • rotate based on position of letter b finds the index of letter b (1), then rotates the string right once plus a number of times
 | 
			
		||||
       equal to that index (2): ecabd.
 | 
			
		||||
     • rotate based on position of letter d finds the index of letter d (4), then rotates the string right once, plus a number of times
 | 
			
		||||
       equal to that index, plus an additional time because the index was at least 4, for a total of 6 right rotations: decab.
 | 
			
		||||
 | 
			
		||||
   After these steps, the resulting scrambled password is decab.
 | 
			
		||||
 | 
			
		||||
   Now, you just need to generate a new scrambled password and you can access the system. Given the list of scrambling operations in your
 | 
			
		||||
   puzzle input, what is the result of scrambling abcdefgh?
 | 
			
		||||
 | 
			
		||||
   Your puzzle answer was ________.
 | 
			
		||||
 | 
			
		||||
--- Part Two ---
 | 
			
		||||
 | 
			
		||||
   You scrambled the password correctly, but you discover that you can't actually modify the password file on the system. You'll need to
 | 
			
		||||
   un-scramble one of the existing passwords by reversing the scrambling process.
 | 
			
		||||
 | 
			
		||||
   What is the un-scrambled version of the scrambled password fbgdceah?
 | 
			
		||||
 | 
			
		||||
   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/File_system_permissions
 | 
			
		||||
   . https://en.wikipedia.org/wiki/Passwd
 | 
			
		||||
   . http://adventofcode.com/2016
 | 
			
		||||
   . http://adventofcode.com/2016/day/21/input
 | 
			
		||||
							
								
								
									
										17
									
								
								helpers.go
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								helpers.go
									
									
									
									
									
								
							@@ -84,6 +84,23 @@ func PrintProgress(curr, total int) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StringPermutations(str string) []string {
 | 
			
		||||
	return stringPermHelper(str, 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func stringPermHelper(str string, i int) []string {
 | 
			
		||||
	ret := []string{str}
 | 
			
		||||
	if i != len(str) {
 | 
			
		||||
		r := []rune(str)
 | 
			
		||||
		for j := i; j < len(r); j++ {
 | 
			
		||||
			r[i], r[j] = r[j], r[i]
 | 
			
		||||
			ret = append(ret, stringPermHelper(string(r), i+1)...)
 | 
			
		||||
			r[i], r[j] = r[j], r[i]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return ret
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Some character code stuff for prettier output
 | 
			
		||||
const (
 | 
			
		||||
	BorderNS = "\u2502"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user