-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy path__init__.py
More file actions
104 lines (83 loc) · 2.4 KB
/
__init__.py
File metadata and controls
104 lines (83 loc) · 2.4 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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import itertools
from typing import List
from aocpy import BaseChallenge
from dataclasses import dataclass
DIGITS = [
"abcefg",
"cf",
"acdeg",
"acdfg",
"bcdf",
"abdfg",
"abdefg",
"acf",
"abcdefg",
"abcdfg",
]
POSSIBLE_WIRINGS = list(itertools.permutations("abcdefg", 7))
@dataclass
class Display:
samples: List[str]
outputs: List[str]
def parse(instr: str) -> List[Display]:
def sort_string(s: str) -> str:
return "".join(sorted(s))
o = []
for line in instr.strip().splitlines():
samples, output = line.split(" | ")
o.append(
Display(
[sort_string(x) for x in samples.split(" ")],
[sort_string(x) for x in output.split(" ")],
)
)
return o
def is_digit_valid(digit: str) -> bool:
return digit in DIGITS
def translate_digit(mapping: str, input_digit: str) -> str:
o = ""
for char in input_digit:
n = ord(char) - ord("a")
o += mapping[n]
return "".join(sorted(o))
def is_wiring_valid(samples: List[str], wiring: str) -> bool:
for sample in samples:
if not is_digit_valid(translate_digit(wiring, sample)):
return False
return True
def find_valid_wiring_from_samples(samples: List[str]) -> str:
for wiring in POSSIBLE_WIRINGS:
if is_wiring_valid(samples, wiring):
return wiring
raise ValueError("no valid wiring")
def get_display_output(display: Display) -> int:
valid_wiring = find_valid_wiring_from_samples(display.samples)
o = 0
for digit in display.outputs:
o *= 10
translated = translate_digit(valid_wiring, digit)
o += DIGITS.index(translated)
return o
class Challenge(BaseChallenge):
@staticmethod
def one(instr: str) -> int:
displays = parse(instr)
sigma = 0
for display in displays:
for digit in display.outputs:
ld = len(digit)
if (
ld == len(DIGITS[1])
or ld == len(DIGITS[4])
or ld == len(DIGITS[7])
or ld == len(DIGITS[8])
):
sigma += 1
return sigma
@staticmethod
def two(instr: str) -> int:
displays = parse(instr)
sigma = 0
for display in displays:
sigma += get_display_output(display)
return sigma