From 07125c75ce4dd2086747d98907c317fa96b50b94 Mon Sep 17 00:00:00 2001 From: Caleb Webber Date: Wed, 6 Dec 2023 00:58:36 -0500 Subject: [PATCH] 2023 day 6 --- lib/2023_day6.ex | 74 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 lib/2023_day6.ex diff --git a/lib/2023_day6.ex b/lib/2023_day6.ex new file mode 100644 index 0000000..423e6ff --- /dev/null +++ b/lib/2023_day6.ex @@ -0,0 +1,74 @@ +defmodule Mix.Tasks.Day6 do + use Mix.Task + + def parse(input, :part1) do + input + |> Enum.map(fn s -> + String.split(s, " ") + |> Enum.reject(fn s -> s === "" or s === "Time:" or s === "Distance:" end) + end) + |> Enum.map(fn i -> + i + |> Enum.map(fn s -> + s |> String.trim() |> String.to_integer() + end) + end) + end + + def parse(input, :part2) do + input + |> Enum.map(fn s -> + String.split(s, " ") + |> Enum.reject(fn s -> s === "" or s === "Time:" or s === "Distance:" end) + end) + |> Enum.map(fn u -> + u + |> Enum.join("") + |> String.trim() + |> String.to_integer() + end) + end + + def distance_traveled_in_n_seconds(seconds, duration) do + seconds * (duration - seconds) + end + + def polynomial_roots(a, b, c) do + [ + (-b + :math.sqrt(b ** 2 - 4 * a * c)) / (2 * a), + (-b - :math.sqrt(b ** 2 - 4 * a * c)) / (2 * a) + ] + end + + def solve([time, distance], p) when p === :part2 do + # number of negative integer solutions to the polynomial + # x^2 - tx + d < 0 + # where x is time spent holding button, t is the duration of the race (seconds), and d is the distance to beat + roots = polynomial_roots(1, -time, distance) + max = roots |> Enum.max() + min = roots |> Enum.min() + floor(max) - floor(min) + end + + def solve([times, distances], p) when p === :part1 do + for {time, index} <- times |> Enum.with_index(), + seconds <- 1..(time - 1), + distance_traveled_in_n_seconds(seconds, time) > distances |> Enum.at(index), + reduce: %{} do + acc -> + acc |> Map.update(time, [seconds], fn u -> [seconds | u] end) + end + |> Map.values() + |> Enum.reduce( + 1, + fn a, acc -> + acc * (a |> Enum.count()) + end + ) + end + + def run(args) do + part = if args |> Enum.at(0) == "1", do: :part1, else: :part2 + IO.stream() |> parse(part) |> solve(part) |> IO.puts() + end +end