summaryrefslogtreecommitdiff
path: root/15
diff options
context:
space:
mode:
authorPrefetch2022-12-31 22:21:39 +0100
committerPrefetch2022-12-31 22:21:39 +0100
commit68615a9ad2c942254135cffb00cf25a84a3b1356 (patch)
tree1ed3131f673207b2ef0bdaee3ee98bb68d6640ca /15
Initial commit
Diffstat (limited to '15')
-rw-r--r--15/input.txt4
-rwxr-xr-x15/main.py78
-rwxr-xr-x15/test.py23
3 files changed, 105 insertions, 0 deletions
diff --git a/15/input.txt b/15/input.txt
new file mode 100644
index 0000000..d1af06e
--- /dev/null
+++ b/15/input.txt
@@ -0,0 +1,4 @@
+Sugar: capacity 3, durability 0, flavor 0, texture -3, calories 2
+Sprinkles: capacity -3, durability 3, flavor 0, texture 0, calories 9
+Candy: capacity -1, durability 0, flavor 4, texture 0, calories 1
+Chocolate: capacity 0, durability 0, flavor -2, texture 2, calories 8
diff --git a/15/main.py b/15/main.py
new file mode 100755
index 0000000..cb2077b
--- /dev/null
+++ b/15/main.py
@@ -0,0 +1,78 @@
+#!/usr/bin/python
+
+
+
+def parse_input(lines):
+ ingredients = []
+
+ for l in lines:
+ words = l.split()
+
+ # Rather than label the properties by name, we number them 0-4
+ props = []
+ for n in range(5):
+ props.append(int(words[2 + 2 * n].rstrip(",")))
+
+ name = words[0].rstrip(":")
+ ingredients.append(props)
+
+ return ingredients
+
+
+
+def all_recipes(ingredients):
+ recipes = {}
+
+ for i1 in range(101):
+ for i2 in range(101 - i1):
+ for i3 in range(101 - i1 - i2):
+ i4 = 100 - i1 - i2 - i3
+ amounts = [i1, i2, i3, i4] # amount of each ingredient
+
+ props = [0, 0, 0, 0] # score for each property
+ for p in range(len(props)):
+ # Accumulate properties of ingredients
+ for i in range(len(amounts)):
+ prop = amounts[i] * ingredients[i][p]
+ props[p] += prop
+ # Clamp negative totals to zero
+ if props[p] < 0:
+ props[p] = 0
+
+ # `recipes' is a dictionary: key is recipe, value is total score
+ recipes[tuple(amounts)] = props[0] * props[1] * props[2] * props[3]
+
+ return recipes
+
+
+
+def solve_partn(partn, lines):
+ ingredients = parse_input(lines)
+ recipes = all_recipes(ingredients)
+
+ if partn == 2:
+ suitable = {}
+ for amounts, score in recipes.items():
+ calories = 0
+ for i in range(len(amounts)):
+ calories += amounts[i] * ingredients[i][4]
+ if calories == 500:
+ suitable[amounts] = score
+ recipes = suitable
+
+ return max(recipes.values())
+
+
+
+def main():
+ # Read ingredient information from input text file
+ with open("input.txt", "r") as f:
+ lines = f.read().splitlines()
+
+ print("Part 1 solution:", solve_partn(1, lines)) # 222870 for me
+ print("Part 2 solution:", solve_partn(2, lines)) # 117936 for me
+
+
+
+if __name__ == "__main__":
+ main()
diff --git a/15/test.py b/15/test.py
new file mode 100755
index 0000000..fb71ad8
--- /dev/null
+++ b/15/test.py
@@ -0,0 +1,23 @@
+#!/usr/bin/python
+
+import unittest
+
+import main
+
+
+
+class Examples(unittest.TestCase):
+ def test_example1(self):
+ lines = [
+ "Butterscotch: capacity -1, durability -2, flavor 6, texture 3, calories 8",
+ "Cinnamon: capacity 2, durability 3, flavor -2, texture -1, calories 3",
+ "Dummy: capacity 0, durability 0, flavor 0, texture 0, calories 0",
+ "Dummy: capacity 0, durability 0, flavor 0, texture 0, calories 0"
+ ]
+ self.assertEqual(main.solve_partn(1, lines), 62842880)
+ self.assertEqual(main.solve_partn(2, lines), 57600000)
+
+
+
+if __name__ == "__main__":
+ unittest.main()