Skip to content

Commit ab0201f

Browse files
committed
Day 9, 2017 - Parts I & II
1 parent 6fbdcfb commit ab0201f

File tree

2 files changed

+130
-0
lines changed

2 files changed

+130
-0
lines changed

2017/day09.py

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# --- Day 9: Stream Processing ---
2+
#
3+
# A large stream blocks your path. According to the locals, it's not safe to
4+
# cross the stream at the moment because it's full of garbage. You look down at
5+
# the stream; rather than water, you discover that it's a stream of characters.
6+
#
7+
# You sit for a while and record part of the stream (your puzzle input).
8+
# The characters represent groups - sequences that begin with { and end with }.
9+
# Within a group, there are zero or more other things, separated by commas:
10+
# either another group or garbage. Since groups can contain other groups,
11+
# a } only closes the most-recently-opened unclosed group - that is,
12+
# they are nestable. Your puzzle input represents a single, large group which
13+
# itself contains many smaller ones.
14+
#
15+
# Sometimes, instead of a group, you will find garbage.
16+
# Garbage begins with < and ends with >.
17+
# Between those angle brackets, almost any character can appear,
18+
# including { and }. Within garbage, < has no special meaning.
19+
#
20+
# In a futile attempt to clean up the garbage, some program has canceled some
21+
# of the characters within it using !: inside garbage, any character that
22+
# comes after ! should be ignored, including <, >, and even another !.
23+
#
24+
# You don't see any characters that deviate from these rules.
25+
# Outside garbage, you only find well-formed groups, and garbage always
26+
# terminates according to the rules above.
27+
#
28+
# Here are some self-contained pieces of garbage:
29+
#
30+
# <>, empty garbage.
31+
# <random characters>, garbage containing random characters.
32+
# <<<<>, because the extra < are ignored.
33+
# <{!>}>, because the first > is canceled.
34+
# <!!>, because the second ! is canceled, allowing the > to terminate the garbage.
35+
# <!!!>>, because the second ! and the first > are canceled.
36+
# <{o"i!a,<{i<a>, which ends at the first >.
37+
# Here are some examples of whole streams and the number of groups they contain:
38+
#
39+
# {}, 1 group.
40+
# {{{}}}, 3 groups.
41+
# {{},{}}, also 3 groups.
42+
# {{{},{},{{}}}}, 6 groups.
43+
# {<{},{},{{}}>}, 1 group (which itself contains garbage).
44+
# {<a>,<a>,<a>,<a>}, 1 group.
45+
# {{<a>},{<a>},{<a>},{<a>}}, 5 groups.
46+
# {{<!>},{<!>},{<!>},{<a>}}, 2 groups (since all but the last > are canceled).
47+
#
48+
# Your goal is to find the total score for all groups in your input.
49+
# Each group is assigned a score which is one more than the score of the group
50+
# that immediately contains it. (The outermost group gets a score of 1.)
51+
#
52+
# {}, score of 1.
53+
# {{{}}}, score of 1 + 2 + 3 = 6.
54+
# {{},{}}, score of 1 + 2 + 2 = 5.
55+
# {{{},{},{{}}}}, score of 1 + 2 + 3 + 3 + 3 + 4 = 16.
56+
# {<a>,<a>,<a>,<a>}, score of 1.
57+
# {{<ab>},{<ab>},{<ab>},{<ab>}}, score of 1 + 2 + 2 + 2 + 2 = 9.
58+
# {{<!!>},{<!!>},{<!!>},{<!!>}}, score of 1 + 2 + 2 + 2 + 2 = 9.
59+
# {{<a!>},{<a!>},{<a!>},{<ab>}}, score of 1 + 2 = 3.
60+
#
61+
# What is the total score for all groups in your input?
62+
#
63+
# ------------------------------------------------------------------------------
64+
65+
import re
66+
import sys
67+
import os
68+
69+
sys.setrecursionlimit(17000)
70+
71+
def solve1(chars, ignore = False, garbage = False, open_groups = 0):
72+
if(len(chars) == 0):
73+
return 0
74+
char = chars[0]
75+
if ignore:
76+
return solve1(chars[1:], False, garbage, open_groups)
77+
if char == '!':
78+
return solve1(chars[1:], True, garbage, open_groups)
79+
if garbage:
80+
if char == '>':
81+
return solve1(chars[1:], ignore, False, open_groups)
82+
else:
83+
return solve1(chars[1:], ignore, garbage, open_groups)
84+
if char == '{':
85+
return solve1(chars[1:], ignore, garbage, open_groups + 1)
86+
elif char == '}':
87+
if open_groups > 0:
88+
return open_groups + solve1(chars[1:], ignore, garbage, open_groups - 1)
89+
else:
90+
return solve1(chars[1:], ignore, garbage, open_groups)
91+
elif char == '<':
92+
return solve1(chars[1:], ignore, True, open_groups)
93+
else:
94+
return solve1(chars[1:], ignore, garbage, open_groups)
95+
96+
def solve2(chars, ignore = False, garbage = False, open_groups = 0):
97+
if(len(chars) == 0):
98+
return 0
99+
char = chars[0]
100+
if ignore:
101+
return solve2(chars[1:], False, garbage, open_groups)
102+
if char == '!':
103+
return solve2(chars[1:], True, garbage, open_groups)
104+
if garbage:
105+
if char == '>':
106+
return solve2(chars[1:], ignore, False, open_groups)
107+
else:
108+
return 1 + solve2(chars[1:], ignore, garbage, open_groups)
109+
if char == '{':
110+
return solve2(chars[1:], ignore, garbage, open_groups + 1)
111+
elif char == '}':
112+
if open_groups > 0:
113+
return solve2(chars[1:], ignore, garbage, open_groups - 1)
114+
else:
115+
return solve2(chars[1:], ignore, garbage, open_groups)
116+
elif char == '<':
117+
return solve2(chars[1:], ignore, True, open_groups)
118+
else:
119+
return solve2(chars[1:], ignore, garbage, open_groups)
120+
121+
if __name__ == '__main__':
122+
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "inputs/day09.txt")
123+
if len(sys.argv) == 2:
124+
data = sys.argv[1]
125+
else:
126+
f = open(file_path)
127+
data = f.read()
128+
print(solve1(data))
129+
print(solve2(data))

0 commit comments

Comments
 (0)