summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--2015/day15.exs95
1 files changed, 95 insertions, 0 deletions
diff --git a/2015/day15.exs b/2015/day15.exs
new file mode 100644
index 0000000..8f93a1b
--- /dev/null
+++ b/2015/day15.exs
@@ -0,0 +1,95 @@
+ingredients =
+ File.stream!("inputs/day15.txt")
+ |> Enum.filter(fn line -> String.trim(line) != "" end)
+ |> Enum.map(fn line ->
+ Regex.run(
+ ~r/\w+: capacity ([+-]?\d+), durability ([+-]?\d+), flavor ([+-]?\d+), texture ([+-]?\d+), calories ([+-]?\d+)/,
+ line
+ )
+ |> Stream.drop(1)
+ |> Stream.map(&Integer.parse/1)
+ |> Enum.map(fn {i, _} -> i end)
+ end)
+
+ingredientsWithoutCalories =
+ Enum.map(ingredients, fn line ->
+ {_calories, withoutCalories} = List.pop_at(line, -1)
+ withoutCalories
+ end)
+
+ingredientsWithCalories =
+ Enum.map(ingredients, fn line ->
+ List.pop_at(line, -1)
+ end)
+
+defmodule RecipeFinder do
+ def findTastiestRecipe([lastIngredient], remainingSpoons, currentMixture) do
+ Enum.zip(lastIngredient, currentMixture)
+ |> Enum.map(fn {next, current} -> next * remainingSpoons + current end)
+ |> Enum.map(&max(&1, 0))
+ |> Enum.product()
+ end
+
+ def findTastiestRecipe([nextIngredient | remainingIngredients], remainingSpoons, currentMixture) do
+ Enum.map(0..remainingSpoons, fn nextSpoons ->
+ findTastiestRecipe(
+ remainingIngredients,
+ remainingSpoons - nextSpoons,
+ Enum.zip(nextIngredient, currentMixture)
+ |> Enum.map(fn {next, current} -> next * nextSpoons + current end)
+ )
+ end)
+ |> Enum.max()
+ end
+
+ def findTastiestRecipeWithExactCalories(
+ [{lastIngredientCalories, _}],
+ remainingSpoons,
+ remainingCalories,
+ _
+ )
+ when lastIngredientCalories * remainingSpoons != remainingCalories do
+ nil
+ end
+
+ def findTastiestRecipeWithExactCalories(
+ [{_, lastIngredient}],
+ remainingSpoons,
+ _,
+ currentMixture
+ ) do
+ Enum.zip(lastIngredient, currentMixture)
+ |> Enum.map(fn {next, current} -> next * remainingSpoons + current end)
+ |> Enum.map(&max(&1, 0))
+ |> Enum.product()
+ end
+
+ def findTastiestRecipeWithExactCalories(
+ [{nextIngredientCalories, nextIngredient} | remainingIngredients],
+ remainingSpoons,
+ remainingCalories,
+ currentMixture
+ ) do
+ maxSpoons = min(remainingSpoons, div(remainingCalories, nextIngredientCalories))
+
+ Enum.map(0..maxSpoons, fn nextSpoons ->
+ findTastiestRecipeWithExactCalories(
+ remainingIngredients,
+ remainingSpoons - nextSpoons,
+ remainingCalories - nextIngredientCalories * nextSpoons,
+ Enum.zip(nextIngredient, currentMixture)
+ |> Enum.map(fn {next, current} -> next * nextSpoons + current end)
+ )
+ end)
+ |> Enum.filter(&(!is_nil(&1)))
+ |> Enum.max(&>=/2, fn -> nil end)
+ end
+end
+
+tastiest = RecipeFinder.findTastiestRecipe(ingredientsWithoutCalories, 100, [0, 0, 0, 0])
+IO.puts("Tastiest: #{tastiest}")
+
+healthiest =
+ RecipeFinder.findTastiestRecipeWithExactCalories(ingredientsWithCalories, 100, 500, [0, 0, 0, 0])
+
+IO.puts("Healthiest: #{healthiest}")