From 028dc17a3cd90bdf5ae57c7f2dba23454348d056 Mon Sep 17 00:00:00 2001 From: Maciej Jur Date: Sat, 11 Dec 2021 17:59:17 +0100 Subject: [PATCH] [2021] day 8 python --- .gitignore | 160 +++++++++++++++++++++++++++++++++++++++++++ 2021/Python/day01.py | 1 - 2021/Python/day03.py | 1 - 2021/Python/day04.py | 2 +- 2021/Python/day08.py | 101 ++++++++++++++++++++++++++- 5 files changed, 259 insertions(+), 6 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..af3f361 --- /dev/null +++ b/.gitignore @@ -0,0 +1,160 @@ +### VirtualEnv template +# Virtualenv +# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ +.Python +[Bb]in +[Ii]nclude +[Ll]ib +[Ll]ib64 +[Ll]ocal +[Ss]cripts +pyvenv.cfg +.venv +pip-selfcheck.json + +### Example user template template +### Example user template + +# IntelliJ project files +.idea +*.iml +out +gen +### Python template +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + diff --git a/2021/Python/day01.py b/2021/Python/day01.py index c0433f5..6187eb1 100644 --- a/2021/Python/day01.py +++ b/2021/Python/day01.py @@ -15,7 +15,6 @@ def solve2() -> int: )) - if __name__ == '__main__': print(solve1()) # 1766 print(solve2()) # 1797 diff --git a/2021/Python/day03.py b/2021/Python/day03.py index 7333645..b9fca15 100644 --- a/2021/Python/day03.py +++ b/2021/Python/day03.py @@ -67,7 +67,6 @@ def solve1_np() -> int: return sum(binary * decimalize) * sum(invert * decimalize) - if __name__ == "__main__": print(solve1()) # 4001724 print(solve2()) # 587895 diff --git a/2021/Python/day04.py b/2021/Python/day04.py index f394051..0a2793a 100644 --- a/2021/Python/day04.py +++ b/2021/Python/day04.py @@ -1,7 +1,7 @@ import numpy as np -def loader_np() -> np.ndarray: +def loader_np(): with open('../.input/day04', 'r') as f: data = f.read().splitlines() diff --git a/2021/Python/day08.py b/2021/Python/day08.py index df6b888..8fe42b1 100644 --- a/2021/Python/day08.py +++ b/2021/Python/day08.py @@ -1,7 +1,7 @@ -from typing import Tuple +from functools import reduce -def load() -> list[Tuple[list[str], list[str]]]: +def load() -> list[tuple[list[str], ...]]: with open('../.input/day08', 'r') as f: return [tuple(map(str.split, line.split('|'))) for line in f.read().splitlines()] @@ -13,5 +13,100 @@ def solve1() -> int: ) +A = 0b0000001 +B = 0b0000010 +C = 0b0000100 +D = 0b0001000 +E = 0b0010000 +F = 0b0100000 +G = 0b1000000 + +n_to_s = { + 0: A | B | C | E | F | G, + 1: C | F, + 2: A | C | D | E | G, + 3: A | C | D | F | G, + 4: B | C | D | F, + 5: A | B | D | F | G, + 6: A | B | D | E | F | G, + 7: A | C | F, + 8: A | B | C | D | E | F | G, + 9: A | B | C | D | F | G, +} + +s_to_n = { + A | B | C | E | F | G: 0, + C | F: 1, + A | C | D | E | G: 2, + A | C | D | F | G: 3, + B | C | D | F: 4, + A | B | D | F | G: 5, + A | B | D | E | F | G: 6, + A | C | F: 7, + A | B | C | D | E | F | G: 8, + A | B | C | D | F | G: 9, +} + +possible = { + 2: n_to_s[1], + 3: n_to_s[7], + 4: n_to_s[4], +} + + +def negate(string: str): + return list(filter(lambda x: x not in string, "abcdefg")) + + +def check_pattern(pattern: list[str], mapping: dict[str, int]): + def check_legal(_str: str): + return reduce(lambda a, c: a | mapping[c], _str, 0) in s_to_n + return all(map(check_legal, pattern)) + + +def find_mapping(pattern: list[str]): + domains = { + char: 0b1111111 + for char in 'abcdefg' + } + + # remove obvious impossible choices + for activation in pattern: + length = len(activation) + if length in possible: + for char in activation: + domains[char] &= possible[length] + for char in negate(activation): + domains[char] &= ~possible[length] + + # bruteforce search + search: list[dict[str, int]] = [{}] + for char, domain in domains.items(): + deeper = [] + for i in range(7): + if domain & (1 << i): + for s in search: + new = s.copy() + new[char] = (1 << i) + deeper.append(new) + search = deeper + + for mapping in search: + if check_pattern(pattern, mapping): + return mapping + + +def string_to_int(string: str, mapping: dict) -> int: + return s_to_n[reduce(lambda a, c: a | mapping[c], string, 0)] + + +def solve2() -> int: + return sum( + reduce(lambda a, c: a * 10 + string_to_int(c, find_mapping(pattern)), output, 0) + for pattern, output in load() + ) + + if __name__ == '__main__': - print(solve1()) # + print(solve1()) # 301 + print(solve2()) # 908067