Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
461 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
from aoc import * | ||
|
||
inp = read(sep=" \\| ") | ||
|
||
entries = [(entry[0].split(' '), entry[1].split(' ')) for entry in inp] | ||
ans = sum(sum(1 for p in entry[1] if len(p) in [2, 3, 4, 7]) for entry in entries) | ||
|
||
print("Part One", ans) | ||
|
||
digits = { | ||
'abcefg': 0, | ||
'cf': 1, | ||
'acdeg': 2, | ||
'acdfg': 3, | ||
'bcdf': 4, | ||
'abdfg': 5, | ||
'abdefg': 6, | ||
'acf': 7, | ||
'abcdefg': 8, | ||
'abcdfg': 9 | ||
} | ||
|
||
|
||
def solve(): | ||
ans2 = 0 | ||
for signals, displays in entries: | ||
def find_signal(segments_count, other_digit='', intersection_size=0): | ||
candidates = [ | ||
s for s in signals | ||
if len(s) == segments_count | ||
and len(set(other_digit) & set(s)) == intersection_size] | ||
assert len(candidates) == 1 | ||
return ''.join(sorted(candidates[0])) | ||
|
||
d1 = find_signal(2) | ||
d4 = find_signal(4) | ||
d7 = find_signal(3) | ||
d8 = find_signal(7) | ||
d3 = find_signal(5, d1, 2) | ||
d2 = find_signal(5, d4, 2) | ||
d5 = find_signal(5, d2, 3) | ||
d6 = find_signal(6, d1, 1) | ||
d9 = find_signal(6, d3, 5) | ||
d0 = find_signal(6, d5, 4) | ||
mapping = dict([(d1, 1), (d2, 2), (d3, 3), (d4, 4), (d5, 5), (d6, 6), (d7, 7), (d8, 8), (d9, 9), (d0, 0)]) | ||
|
||
n = 0 | ||
for display in displays: | ||
n = n*10 + mapping[''.join(sorted(display))] | ||
ans2 += n | ||
return ans2 | ||
|
||
|
||
def solve_sets(): | ||
ans2 = 0 | ||
for signals, displays in entries: | ||
|
||
def contains_all_segments(signal, required_segments): | ||
return len(required_segments - set(signal)) == 0 | ||
|
||
def find_signal_with(segments_count, required_segments=set()): | ||
signal = next( | ||
s for s in signals if len(s) == segments_count and contains_all_segments(s, required_segments)) | ||
return set(signal) | ||
|
||
d1 = find_signal_with(2) | ||
d4 = find_signal_with(4) | ||
d8 = find_signal_with(7) | ||
d7 = find_signal_with(3) | ||
fc = d1 | ||
a = d7 - d1 | ||
d3 = find_signal_with(5, a | fc) | ||
dg = d3 - fc - a | ||
d9 = find_signal_with(6, dg | fc) | ||
b = d9 - dg - fc - a | ||
d = d4 - fc - b | ||
g = dg - d | ||
e = d8 - d9 | ||
d6 = find_signal_with(6, a | dg | e) | ||
c = d8 - d6 | ||
f = fc - c | ||
|
||
letters = [list(x)[0] for x in [a, b, c, d, e, f, g]] | ||
mapping = {} | ||
for i in range(7): | ||
mapping[letters[i]] = 'abcdefg'[i] | ||
n = 0 | ||
|
||
for d in displays: | ||
d2 = ''.join(sorted(map(lambda ch: mapping[ch], d))) | ||
digit = digits[d2] | ||
n = n * 10 + digit | ||
ans2 += n | ||
return ans2 | ||
|
||
|
||
print("Part Two", solve_sets()) | ||
print("Part Two", solve()) |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
# Ищем интересное в AoC 2021 | ||
|
||
## Day 8. 7-segment displays | ||
|
||
### itertools.permutations | ||
|
||
![permutations](day8.jpg) | ||
|
||
```python | ||
from itertools import permutations | ||
|
||
*good, = map(set, ['abcefg','cf', # Correct segments for each digit. | ||
'acdeg','acdfg','bcdf','abdfg', # Segments for 0 are at position 0, etc. | ||
'abdefg','acf','abcdefg','abcdfg']) | ||
|
||
s = 0 | ||
for x,y in [x.split("|") for x in open(0)]: | ||
for p in permutations('abcdefg'): # For each possible wiring permutation, | ||
wires = dict(zip('abcdefg', p)) # create a dictionary to translate them. | ||
|
||
def trans(displays): | ||
out = 0 | ||
for d in displays.split(): # For each of the segment displays: | ||
t = [wires[s] for s in d] # 1. translate each segment using dict, | ||
digit = good.index(set(t)) # 2. look up to which digit they belong, | ||
out = 10*out + digit # 3. add this digit to the output value. | ||
return out | ||
|
||
try: # Try translating using this dictionary. | ||
_ = trans(x) # If we can trans. all signal patterns, | ||
s += trans(y) # it must be correct, so we add output. | ||
except ValueError: # If we hit a translation error, we try | ||
pass # the next wiring permutation. | ||
print(s) | ||
``` | ||
|
||
## Размер пересечения с известными цифрами | ||
|
||
Цифры 1 4 7 8 — определяются по количеству сегментов. | ||
2 3 5 можно отличить друг от друга по количеству пересечений сегментов с уже известными цифрами. | ||
6 9 0 — аналогично. | ||
|
||
Например так: | ||
|
||
```python | ||
def solve(): | ||
ans2 = 0 | ||
for signals, displays in entries: | ||
def find_signal(segments_count, other_digit='', intersection_size=0): | ||
candidates = [ | ||
s for s in signals | ||
if len(s) == segments_count | ||
and len(set(other_digit) & set(s)) == intersection_size] | ||
assert len(candidates) == 1 | ||
return ''.join(sorted(candidates[0])) | ||
|
||
d1 = find_signal(2) | ||
d4 = find_signal(4) | ||
d7 = find_signal(3) | ||
d8 = find_signal(7) | ||
d3 = find_signal(5, d1, 2) | ||
d2 = find_signal(5, d4, 2) | ||
d5 = find_signal(5, d2, 3) | ||
d6 = find_signal(6, d1, 1) | ||
d9 = find_signal(6, d3, 5) | ||
d0 = find_signal(6, d5, 4) | ||
mapping = dict([(d1, 1), (d2, 2), (d3, 3), (d4, 4), (d5, 5), (d6, 6), (d7, 7), (d8, 8), (d9, 9), (d0, 0)]) | ||
|
||
n = 0 | ||
for display in displays: | ||
n = n*10 + mapping[''.join(sorted(display))] | ||
ans2 += n | ||
return ans2 | ||
``` | ||
|
||
### Вычитание множеств | ||
|
||
```python | ||
def decode_digits(x): | ||
cc = {x.count(c):c for c in 'abcdefg'} # A | ||
sB = {cc[6]}; sE = {cc[4]}; sF = {cc[9]} # B C | ||
ss = {len(d):set(d) for d in x.split()} # D | ||
d1 = ss[2]; d4 = ss[4]; d7 = ss[3]; d8 = ss[7] # E F | ||
sD = d4-d1-sB; sC = d1-sF # sA=d7-d1; sG=d8-d4-d7 - not needed # G | ||
return d8-sD,d1,d8-sB-sF,d8-sB-sE,d4,d8-sC-sE,d8-sC,d7,d8,d8-sE | ||
``` | ||
|
||
### Ещё короче! | ||
|
||
Если отсортировать сигналы по хитрому критерию, все встанет на свои места! | ||
|
||
```python | ||
ans1 = ans2 = 0 | ||
for line in data.splitlines(): | ||
seqs = [frozenset(seq) for seq in re.findall(r'\w+', line)] | ||
_1,_7,_4, *pending,_8 = sorted(set(seqs), key=len) | ||
sorter = lambda x: [len(x &_8), len(x &_4), len(x &_1)] | ||
_2,_5,_3,_6,_0,_9 = sorted(pending, key=sorter) | ||
ns = [_0,_1,_2,_3,_4,_5,_6,_7,_8,_9] | ||
ans1 += sum(x in {_1, _7, _4, _8} for x in seqs[-4:]) | ||
ans2 += int(''.join(str(ns.index(x)) for x in seqs[-4:])) | ||
``` | ||
|
||
--- | ||
|
||
Автор большинства сниппетов выше не я — они взяты [из реддита](https://www.reddit.com/r/adventofcode/) твиттера или нашего [телеграм чата](https://t.me/konturAoC2021_chat). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
def run(program, inp): | ||
program = program.copy() | ||
ip = 0 | ||
inp_index = 0 | ||
output = '' | ||
|
||
def param(i): | ||
mode = modes // int(10 ** (i - 1)) % 10 | ||
if mode == 0: | ||
return program[program[ip + i]] | ||
else: | ||
return program[ip + i] | ||
|
||
while ip < len(program): | ||
modes = program[ip] // 100 | ||
opcode = program[ip] % 100 | ||
if opcode == 99: | ||
break | ||
if opcode == 1: | ||
program[program[ip + 3]] = param(1) + param(2) | ||
ip += 4 | ||
elif opcode == 2: | ||
program[program[ip + 3]] = param(1) * param(2) | ||
ip += 4 | ||
elif opcode == 3: | ||
program[program[ip + 1]] = inp[inp_index] | ||
inp_index += 1 | ||
ip += 2 | ||
elif opcode == 4: | ||
v = param(1) | ||
output = output + chr(v) | ||
ip += 2 | ||
elif opcode == 5: # jump-if-true | ||
if param(1) != 0: | ||
ip = param(2) | ||
else: | ||
ip += 3 | ||
elif opcode == 6: # jump-if-false | ||
if param(1) == 0: | ||
ip = param(2) | ||
else: | ||
ip += 3 | ||
elif opcode == 7: # less-than | ||
program[program[ip + 3]] = 1 if param(1) < param(2) else 0 | ||
ip += 4 | ||
elif opcode == 8: # equals | ||
program[program[ip + 3]] = 1 if param(1) == param(2) else 0 | ||
ip += 4 | ||
else: | ||
print("Unknown opcode: ", opcode) | ||
return | ||
return program, output |