-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstream_processing.py
More file actions
58 lines (36 loc) · 1.91 KB
/
Copy pathstream_processing.py
File metadata and controls
58 lines (36 loc) · 1.91 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
# Almost complete solution to Advent of Code 2017 Problem 9.
from mini_parse import exact, Grammar, string_grammar, one_char, none_char, always, foldl
parser = Grammar(string_grammar)
parser.main = parser.garbage | exact('{').and_second(
parser.main.join(parser.comma).optional([])).and_first(exact('}'))
parser.comma = exact(',')
parser.garbage = exact('<').and_second(parser.char.times().concat_all()).and_first(exact('>'))
parser.char = none_char('!>') | ((exact('!') + one_char()) >> always(''))
# Now let's do parts 1 and 2 with a parser for fun. We can reuse stuff from
# our old parser, of course.
# Part 1 is tricky. Ultimately it's probably just simpler to recurse
# through a list, but if you don't want to do that, you can go into
# a mess of lambdas and >>.
parser_1 = Grammar(string_grammar)
parser_1.main = (parser.garbage >> always(always(0))) | (exact('{').and_second(
parser_1.main.join(parser.comma).optional([])).and_first(exact('}'))) >> \
(lambda l: lambda d: d + sum(i(d + 1) for i in l))
# With Part 2, on the other hand, it makes sense to use a parser.
parser_2 = Grammar(string_grammar)
parser_2.main = parser_2.garbage | (exact('{').and_second(
parser_2.main.join(parser.comma).optional([])).and_first(exact('}')) >> sum)
parser_2.garbage = parser.garbage >> len
# Alternatively...
def part_1(p, x):
return x + sum(part_1(i, x + 1) for i in p if type(i) == list)
def part_2(x):
return len(p) if type(p) == str else sum(g_score(i) for i in p)
# Or alternatively, if you are against recursion...
parser_3 = Grammar(string_grammar)
depth = {'{': 1, '}': -1, ',': 0}
update = {'{': True, '}': False, ',': False}
fold_f = lambda c, new: (c[0], c[1], c[2] + new) if type(new) == int else \
(c[0] + depth[new], c[1] + c[0] * update[new], c[2])
parser_3.main = \
((parser.garbage >> len) | exact('{') | exact('}') | exact(',')).times() >> \
(lambda x: foldl(fold_f, (1, 0, 0), x)[1:])