summaryrefslogtreecommitdiffstats
path: root/src/day05.exs
diff options
context:
space:
mode:
authorAlexandre Jesus <adbjesus@gmail.com>2024-12-05 19:38:04 +0000
committerAlexandre Jesus <adbjesus@gmail.com>2024-12-05 19:38:04 +0000
commit368feac2eb23657ae2de72b8ed6a2366fd1cbe3e (patch)
tree9cd25fcaf210fa367b28679e3b5e9a8f8609b013 /src/day05.exs
parent0ab3136b95feddb47be5b14b4c741182fc7dd4d2 (diff)
downloadaoc2024-368feac2eb23657ae2de72b8ed6a2366fd1cbe3e.tar.gz
aoc2024-368feac2eb23657ae2de72b8ed6a2366fd1cbe3e.zip
Day 5
Diffstat (limited to 'src/day05.exs')
-rw-r--r--src/day05.exs80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/day05.exs b/src/day05.exs
new file mode 100644
index 0000000..e950b06
--- /dev/null
+++ b/src/day05.exs
@@ -0,0 +1,80 @@
+defmodule Day05 do
+ def parse_integer_list(list, split) do
+ list
+ |> String.split(split, trim: true)
+ |> Enum.map(&String.to_integer/1)
+ end
+
+ def parse_data(data) do
+ [rules, jobs] = data
+ |> String.split("\n\n", trim: true)
+
+ rules = rules
+ |> String.split("\n", trim: true)
+ |> Enum.map(&parse_integer_list(&1, "|"))
+ |> Enum.group_by(&hd/1, &hd(tl(&1)))
+ |> Enum.into(%{}, fn {k, v} -> {k, MapSet.new(v)} end)
+
+ jobs = jobs
+ |> String.split("\n", trim: true)
+ |> Enum.map(&parse_integer_list(&1, ","))
+
+ {rules, jobs}
+ end
+
+ def part1({rules, jobs}) do
+ jobs
+ |> Enum.filter(&job_okay?(&1, rules))
+ |> Enum.map(&middle_page/1)
+ |> Enum.sum()
+ end
+
+ def job_okay?(job, rules) do
+ case job do
+ [] ->
+ true
+ [page | rest] ->
+ page_okay?(page, rest, rules) and
+ job_okay?(rest, rules)
+ end
+ end
+
+ def page_okay?(page, rest, rules) do
+ rest
+ |> Enum.all?(&Map.get(rules, &1, %MapSet{}) |> MapSet.member?(page) == false)
+ end
+
+ def middle_page(job) do
+ job |> Enum.at(job |> length() |> div(2))
+ end
+
+ def part2({rules, jobs}) do
+ jobs
+ |> Enum.reject(&job_okay?(&1, rules))
+ |> Enum.map(&fix_job(&1, rules))
+ |> Enum.map(&middle_page/1)
+ |> Enum.sum()
+ end
+
+ def fix_job(job, rules, acc \\ []) do
+ case job do
+ [] ->
+ Enum.reverse(acc)
+ job ->
+ {l, r} = Enum.split_with(job, &page_okay?(&1, job, rules) == false)
+ [next, rest] = [hd(r), l ++ tl(r)]
+ fix_job(rest, rules, [next | acc])
+ end
+ end
+end
+
+data = IO.read(:stdio, :eof) |> Day05.parse_data()
+
+{time1 , ans1} = :timer.tc(fn -> Day05.part1(data) end)
+IO.puts("Time : #{time1 / 1000000}")
+IO.puts("Answer: #{ans1}")
+
+{time2 , ans2} = :timer.tc(fn -> Day05.part2(data) end)
+IO.puts("Time : #{time2 / 1000000}")
+IO.puts("Answer: #{ans2}")
+