Просмотр исходного кода

refactor + no precommit

master
Roderic Day 3 лет назад
Родитель
Сommit
e5703e5302
13 измененных файлов: 184 добавлений и 53 удалений
  1. +1
    -0
      .gitignore
  2. +3
    -7
      makefile
  3. +23
    -8
      toolkit.py
  4. +1
    -6
      y2015/p01.py
  5. +1
    -6
      y2015/p02.py
  6. +1
    -6
      y2015/p03.py
  7. +10
    -13
      y2015/p04.py
  8. +1
    -7
      y2015/p05.py
  9. +0
    -0
      y2015/p06.py
  10. +29
    -0
      y2015/p07.py
  11. +49
    -0
      y2016/p24.py
  12. +15
    -0
      y2018/p05.py
  13. +50
    -0
      y2020/p98.py

+ 1
- 0
.gitignore Просмотреть файл

@@ -4,3 +4,4 @@ __pycache__/
.DS_Store
venv/
.env
*.js

+ 3
- 7
makefile Просмотреть файл

@@ -1,23 +1,19 @@
include .env
FILE = $(shell find . -path "./y????/p??.py" -type f | xargs ls -rt | tail -n 1)
DATA = $(shell echo $(FILE) | sed -e s/\.py/\.dat/)
PYTHONPATH = .
export

main: venv/ $(DATA)
@cat $(DATA) | venv/bin/python -u $(FILE)
venv/bin/python -u toolkit.py $(FILE)

flake: venv/
venv/bin/flake8 --exclude=venv/

$(DATA):
@echo $(DATA) | venv/bin/python -c "import toolkit; toolkit.get_dat()" $(DATA)

venv/: requirements.txt
rm -rf venv/
~/.pyenv/versions/3.8.0/bin/python -m venv venv
venv/bin/pip install -r requirements.txt
touch requirements.txt venv/
# install flake8 git hook
echo 'venv/bin/flake8 --exclude=venv/' > .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
# echo 'venv/bin/flake8 --exclude=venv/' > .git/hooks/pre-commit
# chmod +x .git/hooks/pre-commit

+ 23
- 8
toolkit.py Просмотреть файл

@@ -1,9 +1,12 @@
import builtins
import collections
import hashlib
import itertools
import importlib
import math
import os
import re
import string
import sys
from pathlib import Path

@@ -64,14 +67,14 @@ def shortest_path(start, end, move):
return path[::-1]


def get_dat():
path = sys.argv[1]
year, qn = map(int, re.findall(r'\d+', sys.argv[1]))
url = f'https://adventofcode.com/{year}/day/{qn}/input'
cookies = {'session': os.environ['SESSION']}
response = requests.get(url, cookies=cookies)
response.raise_for_status()
Path(path).write_bytes(response.content)
def ensure_data(path):
if not path.exists():
year, qn = map(int, re.findall(r'\d+', sys.argv[1]))
url = f'https://adventofcode.com/{year}/day/{qn}/input'
cookies = {'session': os.environ['SESSION']}
response = requests.get(url, cookies=cookies)
response.raise_for_status()
path.write_bytes(response.content)


def batch(iterable, size):
@@ -97,3 +100,15 @@ def loop_consume(lines, handler):
count += 1
else:
raise RuntimeError('Reached steady state')


if __name__ == '__main__':
data_file = Path(sys.argv[1]).with_suffix('.dat')
ensure_data(data_file)
builtins.data_file = data_file
builtins.string = string
builtins.re = re
rel = re.sub(r'.+(y\d+)/(p\d+).+', r'\1.\2', os.environ['FILE'])
mod = importlib.import_module(rel)
print(getattr(mod, 'ans1', None))
print(getattr(mod, 'ans2', None))

+ 1
- 6
y2015/p01.py Просмотреть файл

@@ -1,11 +1,6 @@
import sys


ans1 = 0
ans2 = None
for i, char in enumerate(sys.stdin.read(), 1):
for i, char in enumerate(data_file.read_text(), 1):
ans1 += {'(': 1, ')': -1}[char]
if ans1 == -1 and ans2 is None:
ans2 = i
print(ans1)
print(ans2)

+ 1
- 6
y2015/p02.py Просмотреть файл

@@ -1,11 +1,6 @@
import sys


ans1 = 0
ans2 = 0
for line in sys.stdin.readlines():
for line in data_file.read_text().splitlines():
a, b, c = sorted(map(int, line.split('x')))
ans1 += 2 * (a * b + b * c + a * c) + a * b
ans2 += a * b * c + 2 * (a + b)
print(ans1)
print(ans2)

+ 1
- 6
y2015/p03.py Просмотреть файл

@@ -1,12 +1,7 @@
import sys
from itertools import accumulate as acc


text = sys.stdin.read()
text = data_file.read_text()
dirs = dict(zip('<>^v', [-1, 1, -1j, 1j]))

ans1 = len({*acc(map(dirs.get, text))})
print(ans1)

ans2 = len({*acc(map(dirs.get, text[::2])), *acc(map(dirs.get, text[1::2]))})
print(ans2)

+ 10
- 13
y2015/p04.py Просмотреть файл

@@ -1,4 +1,3 @@
import sys
from hashlib import md5
from multiprocessing import Pool

@@ -9,15 +8,13 @@ def mine(code, i):
return i, hasher.hexdigest()


if __name__ == '__main__':
code = sys.stdin.read().strip()
ans1 = None
ans2 = None
with Pool() as pool:
for i, coin in pool.starmap(mine, [(code, i) for i in range(10**7)]):
if ans1 is None and coin.startswith('00000'):
ans1 = i
if ans2 is None and coin.startswith('000000'):
ans2 = i
print(ans1)
print(ans2)
code = data_file.read_text().strip()
ans1 = None
ans2 = None
for i in range(10**7):
i, coin = mine(code, i)
if ans1 is None and coin.startswith('00000'):
ans1 = i
if ans2 is None and coin.startswith('000000'):
ans2 = i
break

+ 1
- 7
y2015/p05.py Просмотреть файл

@@ -1,7 +1,3 @@
import re
import sys


def checks1(string):
yield len(re.findall(r'([aeiou])', string)) >= 3
yield len(re.findall(r'(.)\1', string))
@@ -15,8 +11,6 @@ def checks2(string):

ans1 = 0
ans2 = 0
for line in sys.stdin.read().splitlines():
for line in data_file.read_text().splitlines():
ans1 += all(checks1(line))
ans2 += all(checks2(line))
print(ans1)
print(ans2)

+ 0
- 0
y2015/p06.py Просмотреть файл


+ 29
- 0
y2015/p07.py Просмотреть файл

@@ -0,0 +1,29 @@
def pythonize(string):
op, out = (
re.sub(r'([a-z]+)', r'\1_', string)
.replace('AND', '&')
.replace('OR', '|')
.replace('NOT ', '~')
.replace('RSHIFT', '>>')
.replace('LSHIFT', '<<')
).split(' -> ')
return f'{out} = {op}'


def process(instructions, registers={}):
while instructions:
curr, *instructions = instructions
out = curr.split()[0]
if out in registers:
continue
try:
exec(curr, None, registers)
except NameError:
instructions.append(curr)
return registers


inp = [pythonize(string) for string in data_file.read_text().splitlines()]
found = process(inp.copy())
ans1 = found['a_']
ans2 = process(inp.copy(), {'b_': ans1})['a_']

+ 49
- 0
y2016/p24.py Просмотреть файл

@@ -0,0 +1,49 @@
import sys
from itertools import permutations


text = sys.stdin.read()


# transform text into data structures
valid = set()
target = {}
for y, line in enumerate(text.splitlines()):
for x, char in enumerate(line):
if char == '#':
continue
valid.add(x + 1j * y)
if char != '.':
target[x + 1j * y] = char


# generate travel map
graph = {}
for A in target:
seen = {A}
boundary = {A}
pending = set(target) - seen
N = 0
while pending:
N += 1
boundary = {pos + step for pos in boundary for step in [1, -1, 1j, -1j]}
boundary &= valid - seen
seen.update(boundary)

for B in boundary & pending:
pending -= {B}
graph[target[A], target[B]] = N


# use map to determine routes
calc = lambda combo: sum(graph[pair] for pair in zip(combo, combo[1:]))

z = '0'
rest = set(target.values()) - {z}
options = [(z,) + combo for combo in permutations(rest)]
ans = min(options, key=calc)
print(calc(ans))

options = [(z,) + combo + (z,) for combo in permutations(rest)]
ans = min(options, key=calc)
print(calc(ans))

+ 15
- 0
y2018/p05.py Просмотреть файл

@@ -0,0 +1,15 @@
inp = data_file.read_text().strip()
out = {}
for a in [''] + list(string.ascii_lowercase):
text = inp.replace(a, '').replace(a.swapcase(), '')
stack1 = list(text)
stack2 = []
while stack1:
x = stack1.pop()
if stack2 and x.swapcase() == stack2[-1]:
y = stack2.pop()
else:
stack2.append(x)
out[a] = len(stack2)
ans1 = out['']
ans2 = min(out.values())

+ 50
- 0
y2020/p98.py Просмотреть файл

@@ -0,0 +1,50 @@
import collections
import itertools
import re
import sys


txt = '''90342 ;2 correct
70794 ;0 correct
39458 ;2 correct
34109 ;1 correct
51545 ;2 correct
12531 ;1 correct
''' # 39542 is unique
txt = sys.stdin.read()


exclusions = collections.defaultdict(set)
clues = []
for string, n in re.findall(r'(\d+) ;(\d)', txt):
choices = set(enumerate(string))
combos = [frozenset(cs) for cs in itertools.combinations(choices, int(n))]
for combo in combos:
exclusions[combo] |= (choices - combo)
if int(n):
clues.append(combos)


for pos in range(len(string)):
choices = {(pos, char) for char in '0123456789'}
for choice in choices:
exclusions[frozenset({choice})] |= (choices - {choice})


def solve(clues_left, known=frozenset()):
if not clues_left:
avail = {a for gr in exclusions for a in gr}
avail -= {v for k, vs in exclusions.items() if k <= known for v in vs}
yield ''.join(c for _, c in sorted(avail))

else:
choices = min(clues_left, key=len)
for choice in choices:
chosen = known | choice
bads = {v for k, vs in exclusions.items() if k <= chosen for v in vs}
mods = [[c for c in cl if not c & bads] for cl in clues_left if cl != choices]
yield from solve(mods, chosen)


solution = next(solve(clues))
print(solution)

Загрузка…
Отмена
Сохранить