Tasks 18.1 and 18.2

This commit is contained in:
2022-01-12 10:28:52 +03:00
parent c384d9b144
commit e01d0d233d
2 changed files with 345 additions and 0 deletions
+245
View File
@@ -0,0 +1,245 @@
from functools import reduce as freduce
from itertools import permutations
class Regular:
__slots__ = ['data']
def __init__(self, x):
self.data = x
def __str__(self):
return f'r{self.data}'
__repr__ = __str__
def __eq__(self, other):
if isinstance(other, Regular):
return self.data == other.data
if isinstance(other, int):
return self.data == other
return False
def load_file(filename='input'):
with open(filename) as f:
for line in f:
yield line.strip()
def add(x, y):
return reduce(add_numbers(x, y))
def reduce(x):
while True:
if can_explode(x):
x = explode(x)
continue
if can_split(x):
x = split(x)
continue
break
return x
def can_split(x):
try:
return next(filter(lambda k: k.data>=10, numbers(x)))
except StopIteration:
return False
def is_int(x):
return isinstance(x, int)
def is_regular(x):
return isinstance(x, Regular)
def is_pair(x):
return isinstance(x, list)
def magnitude(x):
if is_regular(x):
return x.data
return 3*magnitude(first(x)) + 2*magnitude(second(x))
def numbers(x):
if is_regular(x):
yield x
elif is_pair(x):
yield from numbers(first(x))
yield from numbers(second(x))
def height(x, h=0):
if is_regular(first(x)) and is_regular(second(x)):
yield h, x
if is_pair(first(x)):
yield from height(first(x), h+1)
if is_pair(second(x)):
yield from height(second(x), h+1)
def can_explode(x):
try:
return next(filter(lambda k: k[0]==4, height(x)))
except StopIteration:
return None
def explode(where):
what = can_explode(where)[1]
replace_once(where, what, Regular(-1))
k = list(numbers(where))
i = k.index(Regular(-1))
if i-1>=0:
k[i-1].data += what[0].data
if i+1<len(k):
k[i+1].data += what[1].data
k[i].data = 0
update(where, iter(k))
return where
def update(where, k):
if where == -1:
return
if is_regular(first(where)):
where[0] = next(k)
if is_pair(first(where)):
update(first(where), k)
if is_pair(second(where)):
update(second(where), k)
if is_regular(second(where)):
where[1] = next(k)
def replace_once(where, what, with_):
def replace(where, what, with_):
nonlocal found
if is_pair(where):
if first(where) is what and not found:
where[0] = with_
found = True
elif second(where) is what and not found:
where[1] = with_
found = True
if not found and is_pair(first(where)):
replace(first(where), what, with_)
if not found and is_pair(second(where)):
replace(second(where), what, with_)
found = False
replace(where, what, with_)
def split(where):
what = can_split(where)
with_ = [Regular(what.data//2), Regular((what.data+1)//2)]
replace_once(where, what, with_)
return where
def first(x):
return x[0]
def second(x):
return x[1]
def add_numbers(x, y):
return [x,y]
def from_string(s):
return regularize(eval(s))
def regularize(x):
def rec(x):
if is_pair(x):
if is_int(first(x)):
x[0] = Regular(x[0])
else:
regularize(first(x))
if is_int(second(x)):
x[1] = Regular(x[1])
else:
regularize(second(x))
rec(x)
return x
def calculate(xs):
return freduce(add, map(from_string, xs))
def test_magnitude():
assert magnitude(regularize([9,1]))==29
assert magnitude(regularize([1,9]))==21
assert 143==magnitude(regularize([[1,2],[[3,4],5]]))
assert 1384==magnitude(regularize([[[[0,7],4],[[7,8],[6,0]]],[8,1]]))
assert 445==magnitude(regularize([[[[1,1],[2,2]],[3,3]],[4,4]]))
assert 791==magnitude(regularize([[[[3,0],[5,3]],[4,4]],[5,5]]))
assert 1137==magnitude(regularize([[[[5,0],[7,4]],[5,5]],[6,6]]))
assert 3488==magnitude(regularize([[[[8,7],[7,7]],[[8,6],[7,7]]],[[[0,7],[6,6]],[8,7]]]))
def test_can_explode():
assert can_explode(regularize([[[[[4,3],4],4],[7,[[8,4],9]]],[1,1]]))
assert can_explode(regularize([[[[0,7],4],[7,[[8,4],9]]],[1,1]]))
assert can_explode(regularize([[[[0,7],4],[[7,8],[0,[6,7]]]],[1,1]]))
def test_can_split():
assert can_split(regularize([[[[0,7],4],[15,[0,13]]],[1,1]]))
assert can_split(regularize([[[[0,7],4],[[7,8],[0,13]]],[1,1]]))
def test_split():
assert split(regularize([[[[0,7],4],[15,[0,13]]],[1,1]]))==[[[[0,7],4],[[7,8],[0,13]]],[1,1]]
assert split(regularize([[[[0,7],4],[[7,8],[0,13]]],[1,1]]))==[[[[0,7],4],[[7,8],[0,[6,7]]]],[1,1]]
def test_explode():
assert explode(regularize([[[[[4,3],4],4],[7,[[8,4],9]]],[1,1]]))==[[[[0,7],4],[7,[[8,4],9]]],[1,1]]
assert explode(regularize([[[[0,7],4],[7,[[8,4],9]]],[1,1]]))==[[[[0,7],4],[15,[0,13]]],[1,1]]
assert explode(regularize([[[[0,7],4],[[7,8],[0,[6,7]]]],[1,1]]))==[[[[0,7],4],[[7,8],[6,0]]],[8,1]]
def test_add_simple():
t1 = """
[1,1]
[2,2]
[3,3]
[4,4]
""".strip().split('\n')
assert calculate(t1)==[[[[1,1],[2,2]],[3,3]],[4,4]]
t2 = """
[1,1]
[2,2]
[3,3]
[4,4]
[5,5]
""".strip().split('\n')
assert calculate(t2)==[[[[3,0],[5,3]],[4,4]],[5,5]]
t3 = """
[1,1]
[2,2]
[3,3]
[4,4]
[5,5]
[6,6]
""".strip().split('\n')
assert calculate(t3)==[[[[5,0],[7,4]],[5,5]],[6,6]]
def test_add_example():
t = '''
[[[[4,3],4],4],[7,[[8,4],9]]]
[1,1]
'''.strip().split('\n')
assert calculate(t)==[[[[0,7],4],[[7,8],[6,0]]],[8,1]]
def test_add_complex():
t4 = """
[[[0,[4,5]],[0,0]],[[[4,5],[2,6]],[9,5]]]
[7,[[[3,7],[4,3]],[[6,3],[8,8]]]]
[[2,[[0,8],[3,4]]],[[[6,7],1],[7,[1,6]]]]
[[[[2,4],7],[6,[0,5]]],[[[6,8],[2,8]],[[2,1],[4,5]]]]
[7,[5,[[3,8],[1,4]]]]
[[2,[2,2]],[8,[8,1]]]
[2,9]
[1,[[[9,3],9],[[9,0],[0,7]]]]
[[[5,[7,4]],7],1]
[[[[4,2],2],6],[8,7]]
""".strip().split('\n')
assert calculate(t4[:2])==[[[[4,0],[5,4]],[[7,7],[6,0]]],[[8,[7,7]],[[7,9],[5,0]]]]
assert calculate(t4[:3])==[[[[6,7],[6,7]],[[7,7],[0,7]]],[[[8,7],[7,7]],[[8,8],[8,0]]]], 'похоже, при одинаковых заменах происходит пиздец'
assert calculate(t4[:4])==[[[[7,0],[7,7]],[[7,7],[7,8]]],[[[7,7],[8,8]],[[7,7],[8,7]]]]
assert calculate(t4[:5])==[[[[7,7],[7,8]],[[9,5],[8,7]]],[[[6,8],[0,8]],[[9,9],[9,0]]]]
assert calculate(t4[:6])==[[[[6,6],[6,6]],[[6,0],[6,7]]],[[[7,7],[8,9]],[8,[8,1]]]]
assert calculate(t4[:7])==[[[[6,6],[7,7]],[[0,7],[7,7]]],[[[5,5],[5,6]],9]]
assert calculate(t4[:8])==[[[[7,8],[6,7]],[[6,8],[0,8]]],[[[7,7],[5,0]],[[5,5],[5,6]]]]
assert calculate(t4[:9])==[[[[7,7],[7,7]],[[8,7],[8,7]]],[[[7,0],[7,7]],9]]
assert calculate(t4)==[[[[8,7],[7,7]],[[8,6],[7,7]]],[[[0,7],[6,6]],[8,7]]]
if __name__ == '__main__':
print(magnitude(calculate(load_file())))
print(max(magnitude(calculate(x)) for x in permutations(load_file(), 2)))
+100
View File
@@ -0,0 +1,100 @@
[[[6,[0,5]],2],3]
[[3,9],[[4,[5,5]],[9,4]]]
[[3,[2,[0,7]]],[[1,[0,1]],[8,[2,4]]]]
[[[[3,0],[8,1]],[[5,6],[3,5]]],[5,[[7,9],[5,1]]]]
[[[9,5],1],[[2,6],[4,[4,6]]]]
[2,[5,[3,0]]]
[[[[3,8],9],[[9,2],[7,7]]],5]
[[[[8,5],3],[0,[0,8]]],[9,[6,[8,1]]]]
[[[[9,6],[9,1]],[[3,4],3]],[2,2]]
[[3,[[7,7],2]],[[[9,9],[8,6]],2]]
[[[[3,5],8],[4,[9,4]]],7]
[[1,[6,[2,6]]],[[7,0],[[3,1],9]]]
[[[[0,5],0],[0,[2,4]]],[7,[6,[1,6]]]]
[0,[6,[3,1]]]
[4,[[[1,2],0],[[6,3],6]]]
[[[[4,3],[8,5]],[9,[0,5]]],[[[8,1],3],[8,8]]]
[[3,[6,7]],[[[1,4],[2,1]],[9,[2,8]]]]
[[[[3,0],[4,5]],4],[[3,[5,7]],6]]
[[8,[5,[3,9]]],[[[1,9],[8,7]],7]]
[[[0,[3,4]],[[0,1],6]],[1,5]]
[6,[[9,4],[9,0]]]
[[4,9],[[[0,9],9],8]]
[5,[0,[3,6]]]
[[[[3,9],[1,1]],[4,0]],[4,[[5,7],6]]]
[[[6,[2,1]],[4,[3,3]]],[[6,[5,6]],[7,[5,0]]]]
[[[8,4],[[1,2],[2,0]]],[[6,[5,6]],[6,4]]]
[[[5,9],7],[[[3,4],[2,1]],2]]
[[[8,8],5],[6,[[9,1],1]]]
[[[[3,4],1],[1,[4,2]]],[[[9,1],[2,0]],3]]
[[[5,[1,7]],[3,[9,7]]],[[2,0],[[7,7],5]]]
[[[6,9],6],[6,[[4,2],[5,3]]]]
[[[[6,5],[5,0]],[[6,9],7]],6]
[[[[2,8],[3,2]],[8,8]],[[[4,6],7],[2,[2,3]]]]
[[[3,4],1],5]
[[6,[[7,4],8]],[[6,[9,2]],9]]
[[[[0,4],0],[[3,1],[3,6]]],[0,[[2,8],[5,5]]]]
[[5,[[1,2],6]],[[[1,9],[2,2]],[9,[1,0]]]]
[[[[7,7],5],[[0,0],[0,5]]],[[5,4],[5,[8,1]]]]
[[[[8,7],6],[0,[0,3]]],[2,[[9,8],0]]]
[6,7]
[[[[5,2],[2,2]],[[8,1],[2,7]]],2]
[[[1,0],[[9,8],[2,1]]],4]
[[[[5,2],[2,0]],7],[[2,[4,4]],[3,3]]]
[[8,3],[[7,2],[[1,5],9]]]
[[[[9,4],[7,5]],[[4,9],1]],[[[0,6],[1,6]],[[4,2],3]]]
[4,[5,[5,3]]]
[[1,[[0,1],6]],[[[8,8],6],0]]
[[[0,3],[1,2]],[[6,8],[7,[4,7]]]]
[3,[[[5,8],[6,9]],[8,[5,4]]]]
[[1,1],[[8,[7,0]],9]]
[2,2]
[[3,[[0,4],1]],[[7,[2,3]],[8,4]]]
[[[0,2],[5,[5,6]]],[[[8,1],[5,2]],8]]
[[[[9,5],6],[[7,2],[2,1]]],[[[0,0],0],[[7,9],[9,1]]]]
[[1,7],[1,[[6,3],8]]]
[4,[[[7,4],1],[[1,9],6]]]
[[[[7,8],9],3],[[[5,0],9],8]]
[[[1,3],[[8,3],[1,9]]],[[[6,2],5],5]]
[[8,[[6,6],[1,4]]],[[2,[9,0]],[9,[2,2]]]]
[[0,[[1,6],8]],[[[3,7],[9,2]],[3,[3,6]]]]
[[0,[5,6]],[[[6,5],1],8]]
[[[[9,0],[1,1]],[[1,0],1]],[[[2,5],7],[5,[0,3]]]]
[2,[2,[[3,8],[5,5]]]]
[[[[4,0],2],[4,2]],[[5,[8,1]],[[2,7],6]]]
[[[1,[3,5]],6],0]
[[[3,3],[1,[2,1]]],[[3,[1,1]],[7,0]]]
[[[[8,5],3],[2,[3,0]]],[[[4,8],[8,8]],[9,[2,0]]]]
[[[[8,3],[9,8]],[[8,3],2]],[5,[5,8]]]
[[[1,9],8],[[[0,3],[9,1]],[[9,1],[4,2]]]]
[[[4,1],6],[[5,2],[4,2]]]
[[7,[5,[3,0]]],[[0,[0,1]],[1,[9,6]]]]
[[[[0,3],[8,9]],1],[6,2]]
[[5,[7,8]],[[5,3],[[9,8],[6,2]]]]
[[[[3,6],8],9],[[3,[6,2]],[0,1]]]
[[[5,3],[6,[0,3]]],6]
[[[2,9],7],[[[4,2],9],8]]
[[[7,[3,5]],[6,[5,9]]],[[[3,2],[5,6]],1]]
[[0,[[9,1],6]],8]
[[[[3,5],[2,2]],[[9,8],9]],[8,8]]
[[[[6,9],[2,0]],[6,1]],[1,5]]
[[[0,[9,9]],[[3,1],9]],[[[4,8],2],[3,[4,8]]]]
[[[5,3],[6,3]],[6,[[2,7],[3,2]]]]
[[[5,[7,3]],8],[[2,[0,0]],[9,5]]]
[[[7,[4,3]],[[9,6],[5,7]]],[[[1,8],[3,0]],[[2,4],[7,3]]]]
[[[3,[2,1]],[1,2]],[7,[[5,4],8]]]
[[4,[[2,6],[7,9]]],[[[1,8],3],[[0,1],[5,4]]]]
[[[4,0],4],[3,7]]
[[[4,[7,7]],5],[2,3]]
[[[[7,7],[9,3]],8],[[[3,8],6],[[1,2],[9,6]]]]
[[7,[[7,5],[7,8]]],[2,[[4,3],[6,3]]]]
[[[7,3],[[8,2],[6,5]]],1]
[[8,[7,[9,6]]],[5,[[2,2],2]]]
[[[3,[8,9]],[[3,8],[3,3]]],[4,[7,[5,0]]]]
[[[[2,0],[1,0]],3],[6,[[1,3],[5,4]]]]
[[1,8],[8,[[6,7],3]]]
[4,[[[3,4],[7,8]],[7,[7,1]]]]
[[[4,8],[9,[7,4]]],6]
[[[7,3],[[2,9],7]],[[[2,5],8],[2,5]]]
[7,[[[8,7],0],[[3,1],6]]]
[[6,[2,[3,2]]],[[[5,4],2],[[2,6],[8,4]]]]