diff options
author | Justin Wernick <justin@worthe-it.co.za> | 2024-10-02 13:54:05 +0200 |
---|---|---|
committer | Justin Wernick <justin@worthe-it.co.za> | 2024-10-02 13:54:05 +0200 |
commit | 4f68a95fcd21022f141c4c8e410217858b8c3951 (patch) | |
tree | ee097deaa59b3aa57db3752d11529a86a743c72c | |
parent | 6997fbea377ca44c445e112d594eb077dcc8a76a (diff) |
Day 15
-rw-r--r-- | 2015/day15.exs | 95 |
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}") |