-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday16.py
More file actions
76 lines (62 loc) · 2.22 KB
/
day16.py
File metadata and controls
76 lines (62 loc) · 2.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import re
import string
from day import Day
class Programs:
SPIN = r's(\d+)'
EXCHANGE = r'x(\d+)/(\d+)'
PARTNER = r'p(\w)/(\w)'
def __init__(self, size, moves):
self.size = size
self.moves = moves
def dance(self, programs=None):
# Initial standing of the programs
if programs is None:
programs = string.ascii_lowercase[:self.size]
# Work with list as str is immutable
programs = list(programs)
for move in self.moves:
spin = re.match(Programs.SPIN, move)
exchange = re.match(Programs.EXCHANGE, move)
partner = re.match(Programs.PARTNER, move)
if spin:
n = int(spin.group(1))
programs = Programs.spin(n, programs)
if exchange:
i = int(exchange.group(1))
j = int(exchange.group(2))
programs = Programs.exchange(i, j, programs)
if partner:
a = partner.group(1)
b = partner.group(2)
programs = Programs.partner(a, b, programs)
return ''.join(programs)
# Find a cycle and then compute the standing of the programs
def n_dance(self, n):
dances = []
programs = self.dance()
# Dance until we encounter a repeated standing
while programs not in dances:
dances.append(programs)
programs = self.dance(programs)
# The first element of dances is the standing after 1st dance
return dances[(n-1) % len(dances)]
@staticmethod
def spin(n, programs):
return programs[-n:] + programs[:-n]
@staticmethod
def exchange(i, j, programs):
programs[i], programs[j] = programs[j], programs[i]
return programs
@staticmethod
def partner(a, b, programs):
i = programs.index(a)
j = programs.index(b)
return Programs.exchange(i, j, programs)
class Day16(Day):
def __init__(self, moves, size=16):
self.moves = moves.split(',')
self.size = size
def solve_part_one(self):
return Programs(self.size, self.moves).dance()
def solve_part_two(self):
return Programs(self.size, self.moves).n_dance(10**9)