···11+import fileinput
22+from collections import deque
33+44+from utils import parse_line
55+66+77+def scramble(data, operations, unscramble=False):
88+ data = deque(data)
99+1010+ if unscramble:
1111+ operations.reverse()
1212+1313+ for line in operations:
1414+ if line.startswith('swap position'):
1515+ x, y = parse_line(r'swap position (\d+) with position (\d+)', line)
1616+ data[x], data[y] = data[y], data[x]
1717+1818+ elif line.startswith('swap letter'):
1919+ x, y = parse_line(r'swap letter (\w+) with letter (\w+)', line)
2020+ data = deque(''.join(data).replace(x, '_').replace(y, x).replace('_', y))
2121+2222+ elif line.startswith('rotate based'):
2323+ x = line.split()[-1]
2424+ tmp = ''.join(data)
2525+2626+ if not unscramble:
2727+ i = tmp.index(x)
2828+ data.rotate(i + (2 if i >= 4 else 1))
2929+3030+ else:
3131+ # Keep trying rotation candidates until one is valid
3232+ curr = deque(data)
3333+3434+ while True:
3535+ curr.rotate(1)
3636+ post = ''.join(curr)
3737+ idx = post.index(x)
3838+3939+ tmp = deque(data)
4040+ tmp.rotate(-(idx + (2 if idx >= 4 else 1)))
4141+ pre = ''.join(tmp)
4242+4343+ if pre == post:
4444+ data = deque(pre)
4545+ break
4646+4747+4848+ elif line.startswith('rotate'):
4949+ lr, x = parse_line(r'rotate (\w+) (\d+) step', line)
5050+5151+ if (unscramble and lr == 'right') or (not unscramble and lr == 'left'):
5252+ x = -x
5353+5454+ data.rotate(x)
5555+5656+ elif line.startswith('reverse'):
5757+ x, y = parse_line(r'reverse positions (\d+) through (\d+)', line)
5858+5959+ tmp = ''.join(data)
6060+ tmp = tmp[:x] + ''.join(reversed(tmp[x:y+1])) + tmp[y+1:]
6161+ data = deque(tmp)
6262+6363+ elif line.startswith('move'):
6464+ x, y = parse_line(r'move position (\d+) to position (\d+)', line)
6565+6666+ if unscramble:
6767+ x, y = y, x
6868+6969+ tmp = ''.join(data)
7070+7171+ # Extract the character
7272+ c = tmp[x]
7373+ tmp = tmp[:x] + tmp[x+1:]
7474+7575+ # Reinsert it
7676+ tmp = tmp[:y] + c + tmp[y:]
7777+7878+ data = deque(tmp)
7979+8080+8181+ return ''.join(data)
8282+8383+8484+if __name__ == '__main__':
8585+ operations = [line.strip() for line in fileinput.input()]
8686+ print 'Result of scrambling abcdefgh:', scramble('abcdefgh', operations, False)
8787+ print 'Unscrambled version of fbgdceah:', scramble('fbgdceah', operations, unscramble=True)
+100
2016/inputs/21.txt
···11+move position 2 to position 6
22+move position 0 to position 5
33+move position 6 to position 4
44+reverse positions 3 through 7
55+move position 1 to position 7
66+swap position 6 with position 3
77+swap letter g with letter b
88+swap position 2 with position 3
99+move position 4 to position 3
1010+move position 6 to position 3
1111+swap position 4 with position 1
1212+swap letter b with letter f
1313+reverse positions 3 through 4
1414+swap letter f with letter e
1515+reverse positions 2 through 7
1616+rotate based on position of letter h
1717+rotate based on position of letter a
1818+rotate based on position of letter e
1919+rotate based on position of letter h
2020+rotate based on position of letter c
2121+move position 5 to position 7
2222+swap letter a with letter d
2323+move position 5 to position 6
2424+swap position 4 with position 0
2525+swap position 4 with position 6
2626+rotate left 6 steps
2727+rotate right 4 steps
2828+rotate right 5 steps
2929+swap letter f with letter e
3030+swap position 2 with position 7
3131+rotate based on position of letter e
3232+move position 4 to position 5
3333+swap position 4 with position 2
3434+rotate right 1 step
3535+swap letter b with letter f
3636+rotate based on position of letter b
3737+reverse positions 3 through 5
3838+move position 3 to position 1
3939+rotate based on position of letter g
4040+swap letter c with letter e
4141+swap position 7 with position 3
4242+move position 0 to position 3
4343+rotate right 6 steps
4444+reverse positions 1 through 3
4545+swap letter d with letter e
4646+reverse positions 3 through 5
4747+move position 0 to position 3
4848+swap letter c with letter e
4949+move position 2 to position 7
5050+swap letter g with letter b
5151+rotate right 0 steps
5252+reverse positions 1 through 3
5353+swap letter h with letter d
5454+move position 4 to position 0
5555+move position 6 to position 3
5656+swap letter a with letter c
5757+reverse positions 3 through 6
5858+swap letter h with letter g
5959+move position 7 to position 2
6060+rotate based on position of letter h
6161+swap letter b with letter h
6262+reverse positions 2 through 6
6363+move position 6 to position 7
6464+rotate based on position of letter a
6565+rotate right 7 steps
6666+reverse positions 1 through 6
6767+move position 1 to position 6
6868+rotate based on position of letter g
6969+rotate based on position of letter d
7070+move position 0 to position 4
7171+rotate based on position of letter e
7272+rotate based on position of letter d
7373+rotate based on position of letter a
7474+rotate based on position of letter a
7575+rotate right 4 steps
7676+rotate based on position of letter b
7777+reverse positions 0 through 4
7878+move position 1 to position 7
7979+rotate based on position of letter e
8080+move position 1 to position 7
8181+swap letter f with letter h
8282+move position 5 to position 1
8383+rotate based on position of letter f
8484+reverse positions 0 through 1
8585+move position 2 to position 4
8686+rotate based on position of letter a
8787+swap letter b with letter d
8888+move position 6 to position 0
8989+swap letter e with letter b
9090+rotate right 7 steps
9191+move position 2 to position 7
9292+rotate left 4 steps
9393+swap position 6 with position 1
9494+move position 3 to position 5
9595+rotate right 7 steps
9696+reverse positions 0 through 6
9797+swap position 2 with position 1
9898+reverse positions 4 through 6
9999+rotate based on position of letter g
100100+move position 6 to position 4