From cbd541911a318fcd892856b06bddff0fa9cd95e7 Mon Sep 17 00:00:00 2001 From: Caleb Webber Date: Tue, 3 Dec 2024 10:03:23 -0500 Subject: [PATCH] make mix tasks work again - fix comp errors with day11 2022 --- elixir/lib/Y2022/day11.ex | 173 ++++++++++++++++-------- elixir/lib/aoc.ex | 23 ++-- elixir/lib/{ => mix/tasks}/get_input.ex | 2 + elixir/lib/mix/tasks/get_report_card.ex | 9 ++ 4 files changed, 137 insertions(+), 70 deletions(-) rename elixir/lib/{ => mix/tasks}/get_input.ex (82%) create mode 100644 elixir/lib/mix/tasks/get_report_card.ex diff --git a/elixir/lib/Y2022/day11.ex b/elixir/lib/Y2022/day11.ex index 10fe4d1..9696bb0 100644 --- a/elixir/lib/Y2022/day11.ex +++ b/elixir/lib/Y2022/day11.ex @@ -1,26 +1,46 @@ defmodule MonkeyUtil do def parse_op(z, s) do - "Operation: new = " <> z, s -> parse_op(z, s) - "old " <> z, s -> parse_op(z, [:old | s]) - "old" <> z, s -> parse_op(z, [:old | s]) - "+ " <> z, s -> parse_op(z, [:plus | s]) - "- " <> z, s -> parse_op(z, [:minus | s]) - "* " <> z, s -> parse_op(z, [:mul | s]) - "/ " <> z, s -> parse_op(z, [:div | s]) - "", _, s -> s |> Enum.reverse() - n, s -> - [a | b] = String.split( n, " ") - a = String.trim(a) |> String.to_integer() - parse_op(b |> Enum.join(" "), [a | s]) + (fn + "Operation: new = " <> z, s -> + parse_op(z, s) + + "old " <> z, s -> + parse_op(z, [:old | s]) + + "old" <> z, s -> + parse_op(z, [:old | s]) + + "+ " <> z, s -> + parse_op(z, [:plus | s]) + + "- " <> z, s -> + parse_op(z, [:minus | s]) + + "* " <> z, s -> + parse_op(z, [:mul | s]) + + "/ " <> z, s -> + parse_op(z, [:div | s]) + + "", s -> + s |> Enum.reverse() + + n, s -> + [a | b] = String.split(n, " ") + a = String.trim(a) |> String.to_integer() + parse_op(b |> Enum.join(" "), [a | s]) + end).(z, s) end - def subs(b, a), do: if b == :old, do: a, else: b + def subs(b, a), do: if(b == :old, do: a, else: b) + def resolve_stack(x, y) do (fn - old, [a, :plus, b] -> subs(a, old) + subs(b, old) - old, [a, :minus, b] -> subs(a, old) - subs(b, old) - old, [a, :mul, b] -> subs(a, old) * subs(b, old) - old, [a, :div, b] -> subs(a, old) / subs(b, old) end).(x, y) + old, [a, :plus, b] -> subs(a, old) + subs(b, old) + old, [a, :minus, b] -> subs(a, old) - subs(b, old) + old, [a, :mul, b] -> subs(a, old) * subs(b, old) + old, [a, :div, b] -> subs(a, old) / subs(b, old) + end).(x, y) end end @@ -30,16 +50,23 @@ end defmodule MonkeyMachine do def load(instructions) do - {barrel, _} = for instruction <- instructions, reduce: {%{}, nil} do - {barrel, monkey} -> - (fn - {:break} -> - {barrel |> Map.put(monkey.id, monkey), nil} - {:add_monkey, id} -> {barrel, %Monkey{id: id}} - {:starting_items, i} -> {barrel, %{monkey | items: i }} - {a, o} -> {barrel, %{monkey | a => o }} - end).(instruction) - end + {barrel, _} = + for instruction <- instructions, reduce: {%{}, nil} do + {barrel, monkey} -> + (fn + {:break} -> + {barrel |> Map.put(monkey.id, monkey), nil} + + {:add_monkey, id} -> + {barrel, %Monkey{id: id}} + + {:starting_items, i} -> + {barrel, %{monkey | items: i}} + + {a, o} -> + {barrel, %{monkey | a => o}} + end).(instruction) + end barrel end @@ -49,38 +76,51 @@ defmodule MonkeyMachine do end def run(barrel, :part2) do - run(barrel, 0, (Map.keys(barrel) |> Enum.count()) - 1, Map.values(barrel) |> Stream.map(&(&1.mod)) |> Enum.product()) + run( + barrel, + 0, + (Map.keys(barrel) |> Enum.count()) - 1, + Map.values(barrel) |> Stream.map(& &1.mod) |> Enum.product() + ) end defp run(barrel, i, n) when i > n, do: barrel + defp run(barrel, id, n) do monkey = Map.get(barrel, id) - barrel = for item <- monkey.items, reduce: barrel do - b -> - item = div(monkey.op.(item), 3) - dest = if rem(item, monkey.mod) == 0, do: monkey.if_true, else: monkey.if_false - b + barrel = + for item <- monkey.items, reduce: barrel do + b -> + item = div(monkey.op.(item), 3) + dest = if rem(item, monkey.mod) == 0, do: monkey.if_true, else: monkey.if_false + + b |> Map.update!(dest, fn d -> %{d | items: [item | d.items]} end) |> Map.update!(id, fn m -> Map.update!(m, :inspections, &(&1 + 1)) end) - end |> Map.update!(id, fn m -> %{m | items: []} end) + end + |> Map.update!(id, fn m -> %{m | items: []} end) run(barrel, id + 1, n) end defp run(barrel, i, n, _) when i > n, do: barrel + defp run(barrel, id, n, m) do monkey = Map.get(barrel, id) - barrel = for item <- monkey.items, reduce: barrel do - b -> - r = rem(monkey.op.(item), m) - item = if r == 0, do: m, else: r - dest = if rem(r, monkey.mod) == 0, do: monkey.if_true, else: monkey.if_false - b + barrel = + for item <- monkey.items, reduce: barrel do + b -> + r = rem(monkey.op.(item), m) + item = if r == 0, do: m, else: r + dest = if rem(r, monkey.mod) == 0, do: monkey.if_true, else: monkey.if_false + + b |> Map.update!(dest, fn d -> %{d | items: [item | d.items]} end) |> Map.update!(id, fn m -> Map.update!(m, :inspections, &(&1 + 1)) end) - end |> Map.update!(id, fn m -> %{m | items: []} end) + end + |> Map.update!(id, fn m -> %{m | items: []} end) run(barrel, id + 1, n, m) end @@ -89,30 +129,45 @@ end defmodule MonkeySolver do # part := :part1 || :part2 def solve(input, part) do - barrel = input - |> String.split("\n") - |> Stream.map(&String.trim/1) - |> Enum.map( - fn - "Monkey " <> z -> {:add_monkey, z |> String.split(":") |> Enum.at(0) |> String.to_integer()} - "Starting items: " <> i -> {:starting_items, i |> String.split(",", trim: true) |> Enum.map(&String.to_integer(String.trim(&1)))} - "Operation: " <> _ = u -> {:op, fn o -> MonkeyUtil.resolve_stack(o, MonkeyUtil.parse_op(u, [])) end} - "Test: divisible by " <> n -> {:mod, String.to_integer(n)} - "If true: throw to monkey " <> n -> {:if_true, String.to_integer(n)} - "If false: throw to monkey " <> n -> {:if_false, String.to_integer(n)} - "" -> {:break} - u -> u - end - ) - |> MonkeyMachine.load() + barrel = + input + |> String.split("\n") + |> Stream.map(&String.trim/1) + |> Enum.map(fn + "Monkey " <> z -> + {:add_monkey, z |> String.split(":") |> Enum.at(0) |> String.to_integer()} - iterations = if part == :part1, do: 20, else: 10_000 end + "Starting items: " <> i -> + {:starting_items, + i |> String.split(",", trim: true) |> Enum.map(&String.to_integer(String.trim(&1)))} + + "Operation: " <> _ = u -> + {:op, fn o -> MonkeyUtil.resolve_stack(o, MonkeyUtil.parse_op(u, [])) end} + + "Test: divisible by " <> n -> + {:mod, String.to_integer(n)} + + "If true: throw to monkey " <> n -> + {:if_true, String.to_integer(n)} + + "If false: throw to monkey " <> n -> + {:if_false, String.to_integer(n)} + + "" -> + {:break} + + u -> + u + end) + |> MonkeyMachine.load() + + iterations = if part == :part1, do: 20, else: 10_000 for _ <- 1..iterations, reduce: barrel do b -> MonkeyMachine.run(b, part) end |> Map.values() - |> Stream.map(&(&1.inspections)) + |> Stream.map(& &1.inspections) |> Enum.sort(:desc) |> Enum.take(2) |> Enum.product() diff --git a/elixir/lib/aoc.ex b/elixir/lib/aoc.ex index 4efa2d5..c7f6b9a 100644 --- a/elixir/lib/aoc.ex +++ b/elixir/lib/aoc.ex @@ -3,8 +3,6 @@ defmodule AoC do defp get_request_headers!(), do: [Cookie: "session=#{get_session!()}"] def fetch_input!(year, day) do - Application.ensure_all_started(:req) - Req.get!( "https://adventofcode.com/#{year}/day/#{day}/input", headers: get_request_headers!() @@ -17,7 +15,9 @@ defmodule AoC do import String, only: [split: 2, trim: 1, contains?: 2, to_integer: 1] day_class = fn classes -> classes |> split(" ") |> at(0) |> split("-") |> at(1) |> trim() end - days_complete = fn classes -> cond do + + days_complete = fn classes -> + cond do contains?(classes, "verycomplete") -> 2 contains?(classes, "complete") -> 1 true -> 0 @@ -25,14 +25,15 @@ defmodule AoC do end session = get_session!() + Req.get!("https://adventofcode.com/#{year}", headers: [cookie: "session=#{session}"]).body - |> Floki.parse_document!(html_parser: Floki.HTMLParser.Html5ever) - |> Floki.find("pre.calendar > a") - |> Stream.map(fn e -> - "#{Floki.attribute(e, "class")}\n" - end) - |> Stream.map(fn classes -> { day_class.(classes), days_complete.(classes) } end) - |> Stream.map(fn {day, c} -> {day |> split("day") |> at(1) |> to_integer(), c} end) - |> sort_by(&(elem(&1, 0))) + |> Floki.parse_document!(html_parser: Floki.HTMLParser.Html5ever) + |> Floki.find("pre.calendar > a") + |> Stream.map(fn e -> + "#{Floki.attribute(e, "class")}\n" + end) + |> Stream.map(fn classes -> {day_class.(classes), days_complete.(classes)} end) + |> Stream.map(fn {day, c} -> {day |> split("day") |> at(1) |> to_integer(), c} end) + |> sort_by(&elem(&1, 0)) end end diff --git a/elixir/lib/get_input.ex b/elixir/lib/mix/tasks/get_input.ex similarity index 82% rename from elixir/lib/get_input.ex rename to elixir/lib/mix/tasks/get_input.ex index 7f65b3d..5976ac6 100644 --- a/elixir/lib/get_input.ex +++ b/elixir/lib/mix/tasks/get_input.ex @@ -1,5 +1,7 @@ defmodule Mix.Tasks.GetInput do def run(args) do + Application.ensure_all_started(:req) + [year, day] = args write_file = &File.write("./input/#{year}_#{day}.txt", &1) diff --git a/elixir/lib/mix/tasks/get_report_card.ex b/elixir/lib/mix/tasks/get_report_card.ex new file mode 100644 index 0000000..4f0a475 --- /dev/null +++ b/elixir/lib/mix/tasks/get_report_card.ex @@ -0,0 +1,9 @@ +defmodule Mix.Tasks.GetReportCard do + def run([year | _]) do + Application.ensure_all_started(:req) + + AoC.fetch_reportcard!(year) + |> inspect() + |> IO.puts() + end +end