Skip to content

Commit c14864c

Browse files
committed
Added day 2020-07
1 parent 9f626b7 commit c14864c

File tree

1 file changed

+157
-0
lines changed

1 file changed

+157
-0
lines changed

2020/07-Handy Haversacks.py

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# -------------------------------- Input data ---------------------------------------- #
2+
import os, grid, graph, dot, assembly, re, itertools
3+
from collections import Counter, deque, defaultdict
4+
5+
from compass import *
6+
7+
8+
# This functions come from https://github.com/mcpower/adventofcode - Thanks!
9+
def lmap(func, *iterables):
10+
return list(map(func, *iterables))
11+
12+
13+
def ints(s: str):
14+
return lmap(int, re.findall(r"-?\d+", s)) # thanks mserrano!
15+
16+
17+
def positive_ints(s: str):
18+
return lmap(int, re.findall(r"\d+", s)) # thanks mserrano!
19+
20+
21+
def floats(s: str):
22+
return lmap(float, re.findall(r"-?\d+(?:\.\d+)?", s))
23+
24+
25+
def positive_floats(s: str):
26+
return lmap(float, re.findall(r"\d+(?:\.\d+)?", s))
27+
28+
29+
def words(s: str):
30+
return re.findall(r"[a-zA-Z]+", s)
31+
32+
33+
test_data = {}
34+
35+
test = 1
36+
test_data[test] = {
37+
"input": """light red bags contain 1 bright white bag, 2 muted yellow bags.
38+
dark orange bags contain 3 bright white bags, 4 muted yellow bags.
39+
bright white bags contain 1 shiny gold bag.
40+
muted yellow bags contain 2 shiny gold bags, 9 faded blue bags.
41+
shiny gold bags contain 1 dark olive bag, 2 vibrant plum bags.
42+
dark olive bags contain 3 faded blue bags, 4 dotted black bags.
43+
vibrant plum bags contain 5 faded blue bags, 6 dotted black bags.
44+
faded blue bags contain no other bags.
45+
dotted black bags contain no other bags.""",
46+
"expected": ["4", "Unknown"],
47+
}
48+
49+
test = 2
50+
test_data[test] = {
51+
"input": """shiny gold bags contain 2 dark red bags.
52+
dark red bags contain 2 dark orange bags.
53+
dark orange bags contain 2 dark yellow bags.
54+
dark yellow bags contain 2 dark green bags.
55+
dark green bags contain 2 dark blue bags.
56+
dark blue bags contain 2 dark violet bags.
57+
dark violet bags contain no other bags.""",
58+
"expected": ["Unknown", "126"],
59+
}
60+
61+
test = "real"
62+
input_file = os.path.join(
63+
os.path.dirname(__file__),
64+
"Inputs",
65+
os.path.basename(__file__).replace(".py", ".txt"),
66+
)
67+
test_data[test] = {
68+
"input": open(input_file, "r+").read(),
69+
"expected": ["300", "8030"],
70+
}
71+
72+
73+
# -------------------------------- Control program execution ------------------------- #
74+
case_to_test = "real"
75+
part_to_test = 2
76+
77+
# -------------------------------- Initialize some variables ------------------------- #
78+
79+
puzzle_input = test_data[case_to_test]["input"]
80+
puzzle_expected_result = test_data[case_to_test]["expected"][part_to_test - 1]
81+
puzzle_actual_result = "Unknown"
82+
83+
84+
# -------------------------------- Actual code execution ----------------------------- #
85+
86+
if part_to_test == 1:
87+
results = []
88+
for string in puzzle_input.split("\n"):
89+
results.append(re.findall("[a-z ]* bags?", string))
90+
91+
combinations = []
92+
for result in results:
93+
if len(result) == 1:
94+
print("No match for", result)
95+
else:
96+
combinations.append(
97+
{
98+
"out": result[0].replace("bags", "bag"),
99+
"in": [x.replace("bags", "bag")[1:] for x in result[1:]],
100+
}
101+
)
102+
103+
contain_gold = set(["shiny gold bag"])
104+
# There is certainly a clever way to reduce how many loops I do, but I don't know it (yet)
105+
for i in range(len(combinations)):
106+
for combination in combinations:
107+
if any(
108+
[gold_container in combination["in"] for gold_container in contain_gold]
109+
):
110+
contain_gold.add(combination["out"])
111+
print(len(contain_gold), i, len(combinations))
112+
113+
puzzle_actual_result = len(contain_gold) - 1
114+
115+
116+
else:
117+
results = []
118+
for string in puzzle_input.split("\n"):
119+
results.append(re.findall("([0-9]* )?([a-z ]*) bags?", string))
120+
121+
combinations = []
122+
for result in results:
123+
if len(result) == 1:
124+
bags = result[0][1].split(" bags contain no ")
125+
combinations.append({"out": bags[0], "in": []})
126+
else:
127+
combinations.append(
128+
{"out": result[0][1], "in": {x[1]: int(x[0]) for x in result[1:]}}
129+
)
130+
131+
gold_contains = defaultdict(int)
132+
gold_contains["shiny gold"] = 1
133+
gold_contains["total"] = -1
134+
135+
while len(gold_contains) > 1:
136+
for combination in combinations:
137+
if combination["out"] in gold_contains:
138+
for containee in combination["in"]:
139+
# Add those bags to the count
140+
gold_contains[containee] += (
141+
combination["in"][containee] * gold_contains[combination["out"]]
142+
)
143+
# Add the "out" bag to the count & remove it from the list
144+
# This ensures we don't loop over the same bag twice
145+
gold_contains["total"] += gold_contains[combination["out"]]
146+
del gold_contains[combination["out"]]
147+
148+
print(sum(gold_contains.values()), gold_contains)
149+
150+
puzzle_actual_result = gold_contains["total"]
151+
152+
153+
# -------------------------------- Outputs / results --------------------------------- #
154+
155+
print("Case :", case_to_test, "- Part", part_to_test)
156+
print("Expected result : " + str(puzzle_expected_result))
157+
print("Actual result : " + str(puzzle_actual_result))

0 commit comments

Comments
 (0)