In [26]:
import numpy as np
import re
SWAP_POS = re.compile('swap position (\d+) with position (\d+)')
SWAP_LETTER = re.compile('swap letter ([a-z]) with letter ([a-z])')
ROTATE_LEFT = re.compile('rotate left (\d+) step')
ROTATE_RIGHT = re.compile('rotate right (\d+) step')
ROTATE_LETTER = re.compile('rotate based on position of letter ([a-z])')
REVERSE = re.compile('reverse positions (\d+) through (\d+)')
MOVE = re.compile('move position (\d+) to position (\d+)')
class Password(object):
def __init__(self, word):
self.word = word
def get(self):
return str(self.word)
def swap_position(self, x, y):
a = self.word[x]
self.word = [self.word[i] if i != x else self.word[y] for i in range(len(self.word))]
self.word[y] = a
self.word = ''.join(self.word)
def swap_letter(self, a, b):
pos_a = [j for j, k in enumerate(list(self.word)) if k == a]
pos_b = [j for j, k in enumerate(list(self.word)) if k == b]
self.word = [self.word[i] if i not in pos_a else b for i in range(len(self.word))]
self.word = ''.join([self.word[i] if i not in pos_b else a for i in range(len(self.word))])
def rotate_right(self, x):
self.word = ''.join(np.roll(list(self.word), x))
def rotate_left(self, x):
self.word = ''.join(np.roll(list(self.word), -x))
def rotate_letter(self, a):
ind = self.word.index(a)
self.rotate_right((ind + 2)*(ind >= 4) + (ind + 1)*(ind < 4))
def reverse_positions(self, x, y):
l = list(self.word)
q = l[x:y+1]
q.reverse()
self.word = ''.join(l[:x] + q + l[y+1:])
def move_position(self, x, y):
l = list(self.word)
a = l.pop(x)
q = l[:y] + [a] + l[y:]
self.word = ''.join(q)
def use(self, instr):
m = SWAP_POS.match(instr)
if m:
x, y = m.groups()
self.swap_position(int(x), int(y))
m = SWAP_LETTER.match(instr)
if m:
a, b = m.groups()
self.swap_letter(a, b)
m = ROTATE_RIGHT.match(instr)
if m:
x = m.groups()
self.rotate_right(int(x[0]))
m = ROTATE_LEFT.match(instr)
if m:
x = m.groups()
self.rotate_left(int(x[0]))
m = ROTATE_LETTER.match(instr)
if m:
a = m.groups()
self.rotate_letter(str(a[0]))
m = REVERSE.match(instr)
if m:
x, y = m.groups()
self.reverse_positions(int(x), int(y))
m = MOVE.match(instr)
if m:
x, y = m.groups()
self.move_position(int(x), int(y))
In [27]:
def scramble(myinput, w):
password = Password(w)
with open(myinput, 'rt') as f:
for line in f:
password.use(line.rstrip())
return password.get()
In [28]:
w = Password('abcde')
w.swap_position(4,0)
w.swap_letter('b','d')
w.reverse_positions(0,4)
w.rotate_left(1)
w.move_position(1,4)
w.move_position(3,0)
w.rotate_letter('b')
w.rotate_letter('d')
w.get()
Out[28]:
In [29]:
word = 'abcde'
testinput = '/home/fmuinos/projects/adventofcode/2016/ferran/inputs/input21-test.txt'
scramble(testinput, word)
Out[29]:
In [30]:
word = 'abcdefgh'
myinput = '/home/fmuinos/projects/adventofcode/2016/ferran/inputs/input21.txt'
scramble(myinput, word)
Out[30]:
In [36]:
word = 'fbgdceah'
myinput = '/home/fmuinos/projects/adventofcode/2016/ferran/inputs/input21.txt'
In [37]:
from itertools import permutations
def unscramble(myinput, word):
for l in permutations(list('abcdefgh')):
if scramble(myinput, ''.join(l)) == unscrambable:
return ''.join(l)
In [38]:
unscramble(myinput, word)
Out[38]: