]> git.njae.me.uk Git - advent-of-code-24-elixir.git/commitdiff
Done day 1 in Elixir main
authorNeil Smith <NeilNjae@users.noreply.github.com>
Fri, 24 Jan 2025 15:21:16 +0000 (15:21 +0000)
committerNeil Smith <NeilNjae@users.noreply.github.com>
Fri, 24 Jan 2025 15:21:16 +0000 (15:21 +0000)
lib/advent_of_code/day_01.ex
lib/advent_of_code/input.ex
mix.exs
mix.lock
test/advent_of_code/day_01_test.exs

index 8e532a57ccd679a2ea628ed4b0946782828471dc..c4933c2b6dc7d41157b94c6a7c478769472c01a7 100644 (file)
@@ -1,7 +1,60 @@
+
 defmodule AdventOfCode.Day01 do
-  def part1(_args) do
+  require Logger
+  use Flow
+
+  def part1(input \\ nil) do
+    input = if is_nil(input), do: AdventOfCode.Input.get!(1), else: input
+    {lefts, rights} = parse_input(input)
+    s_lefts = Enum.sort(lefts)
+    s_rights = Enum.sort(rights)
+
+    Enum.zip(s_lefts, s_rights)
+    |> Enum.map(fn {l, r} -> abs(l - r) end)
+    |> Enum.sum()
+  end
+
+  def part2(input \\ nil) do
+    input = if is_nil(input), do: AdventOfCode.Input.get!(1), else: input
+    {lefts, rights} = parse_input(input)
+
+    right_counts = rights
+    |> Flow.from_enumerable()
+    |> Flow.partition(key: fn x -> rem(x, 100) end)
+    |> Flow.reduce(fn -> %{} end, fn item, acc ->
+          Map.update(acc, item, 1, &(&1 + 1))
+          end)
+    |> Enum.reduce(%{}, fn {n, c}, acc -> Map.merge(%{n => c}, acc) end)
+
+    # right_counts = Enum.frequencies(rights)
+
+    similarity =
+      lefts
+      |> Enum.map(fn x -> x * Map.get(right_counts, x, 0) end)
+      |> Enum.sum()
+
+    similarity
+  end
+
+  defp parse_input(input) do
+    input
+    |> String.split("\n")
+    |> Task.async_stream(&parse_line/1, ordered: false)
+    |> Enum.map(fn r -> elem(r, 1) end)
+    |> Enum.unzip()
+
+    # |> String.split("\n")
+    # |> Enum.map(&String.split/1)
+    # # |> Enum.map(fn xs -> xs |> Enum.map(&String.to_integer/1) end)
+    # |> Enum.map(fn xs -> Enum.map(xs, &String.to_integer/1) end)
+    # |> Enum.map(fn xs -> {Enum.at(xs, 0), Enum.at(xs, 1)} end)
+    # |> Enum.unzip()
   end
 
-  def part2(_args) do
+  defp parse_line(inline) do
+    lp = inline
+          |> String.split()
+          |> Enum.map(&String.to_integer/1)
+    {Enum.at(lp, 0), Enum.at(lp, 1)}
   end
 end
index 38a8fc8f7190518125542da99cf33af0930745f3..df956cc0dec40aebc3f8ba463f9b39088a999322 100644 (file)
@@ -13,79 +13,70 @@ defmodule AdventOfCode.Input do
   cache, it will be retrieved from the server if `allow_network?: true` is
   configured and your cookie is setup.
   """
-  def get!(day, year \\ nil)
-  def get!(day, nil), do: get!(day, default_year())
 
-  def get!(day, year) do
-    cond do
-      in_cache?(day, year) ->
-        from_cache!(day, year)
-
-      allow_network?() ->
-        download!(day, year)
-
-      true ->
-        raise "Cache miss for day #{day} of year #{year} and `:allow_network?` is not `true`"
-    end
-  end
-
-  @doc """
-  If, somehow, your input is invalid or mangled and you want to delete it from
-  your cache so you can re-fetch it, this will save your bacon.
-  Please don't use this to retrieve the input from the server repeatedly!
-  """
-  def delete!(day, year \\ nil)
-  def delete!(day, nil), do: delete!(day, default_year())
-  def delete!(day, year), do: File.rm!(cache_path(day, year))
-
-  defp cache_path(day, year), do: Path.join(cache_dir(), "/#{year}/#{day}.aocinput")
-  defp in_cache?(day, year), do: File.exists?(cache_path(day, year))
-
-  defp store_in_cache!(day, year, input) do
-    path = cache_path(day, year)
-    :ok = path |> Path.dirname() |> File.mkdir_p()
-    :ok = File.write(path, input)
-  end
-
-  defp from_cache!(day, year), do: File.read!(cache_path(day, year))
-
-  defp download!(day, year) do
-    {:ok, {{~c"HTTP/1.1", 200, ~c"OK"}, _, input}} =
-      :httpc.request(
-        :get,
-        {~c"https://adventofcode.com/#{year}/day/#{day}/input", headers()},
-        [],
-        []
-      )
-
-    store_in_cache!(day, year, input)
-
-    to_string(input)
+  def get!(day, suffix \\ "") do
+    day_string = Integer.to_string(day) |> String.pad_leading(2, "0")
+    filename = "../data/advent#{day_string}#{suffix}.txt"
+    File.read!(filename)
   end
 
-  defp cache_dir do
-    config()
-    |> Keyword.get(
-      :cache_dir,
-      Path.join([System.get_env("XDG_CACHE_HOME", "~/.cache"), "/advent_of_code_inputs"])
-    )
-    |> Path.expand()
-  end
-
-  defp default_year do
-    case :calendar.local_time() do
-      {{y, 12, _}, _} -> y
-      {{y, _, _}, _} -> y - 1
-    end
-  end
-
-  defp config, do: Application.get_env(:advent_of_code, __MODULE__)
-  defp allow_network?, do: Keyword.get(config(), :allow_network?, false)
-
-  defp headers,
-    do: [
-      {~c"user-agent",
-       ~c"github.com/mhanberg/advent-of-code-elixir-starter by aoc@mitchellhanberg.com"},
-      {~c"cookie", String.to_charlist("session=" <> Keyword.get(config(), :session_cookie))}
-    ]
+  # @doc """
+  # If, somehow, your input is invalid or mangled and you want to delete it from
+  # your cache so you can re-fetch it, this will save your bacon.
+  # Please don't use this to retrieve the input from the server repeatedly!
+  # """
+  # def delete!(day, year \\ nil)
+  # def delete!(day, nil), do: delete!(day, default_year())
+  # def delete!(day, year), do: File.rm!(cache_path(day, year))
+
+  # defp cache_path(day, year), do: Path.join(cache_dir(), "/#{year}/#{day}.aocinput")
+  # defp in_cache?(day, year), do: File.exists?(cache_path(day, year))
+
+  # defp store_in_cache!(day, year, input) do
+  #   path = cache_path(day, year)
+  #   :ok = path |> Path.dirname() |> File.mkdir_p()
+  #   :ok = File.write(path, input)
+  # end
+
+  # defp from_cache!(day, year), do: File.read!(cache_path(day, year))
+
+  # defp download!(day, year) do
+  #   {:ok, {{~c"HTTP/1.1", 200, ~c"OK"}, _, input}} =
+  #     :httpc.request(
+  #       :get,
+  #       {~c"https://adventofcode.com/#{year}/day/#{day}/input", headers()},
+  #       [],
+  #       []
+  #     )
+
+  #   store_in_cache!(day, year, input)
+
+  #   to_string(input)
+  # end
+
+  # defp cache_dir do
+  #   config()
+  #   |> Keyword.get(
+  #     :cache_dir,
+  #     Path.join([System.get_env("XDG_CACHE_HOME", "~/.cache"), "/advent_of_code_inputs"])
+  #   )
+  #   |> Path.expand()
+  # end
+
+  # defp default_year do
+  #   case :calendar.local_time() do
+  #     {{y, 12, _}, _} -> y
+  #     {{y, _, _}, _} -> y - 1
+  #   end
+  # end
+
+  # defp config, do: Application.get_env(:advent_of_code, __MODULE__)
+  # defp allow_network?, do: Keyword.get(config(), :allow_network?, false)
+
+  # defp headers,
+  #   do: [
+  #     {~c"user-agent",
+  #      ~c"github.com/mhanberg/advent-of-code-elixir-starter by aoc@mitchellhanberg.com"},
+  #     {~c"cookie", String.to_charlist("session=" <> Keyword.get(config(), :session_cookie))}
+  #   ]
 end
diff --git a/mix.exs b/mix.exs
index 017ffd19ca76b8e4766aa1c096b8f359c05d9e44..dd68e9a512789328765a07d667d91e021b9a85cb 100644 (file)
--- a/mix.exs
+++ b/mix.exs
@@ -14,7 +14,7 @@ defmodule AdventOfCode.MixProject do
   # Run "mix help compile.app" to learn about applications.
   def application do
     [
-      extra_applications: [:logger, :inets, :public_key, :ssl]
+      extra_applications: [:logger]
     ]
   end
 
@@ -22,7 +22,9 @@ defmodule AdventOfCode.MixProject do
   defp deps do
     [
       {:benchee, "~> 1.0"},
-      {:ssl_verify_fun, "~> 1.1.7", manager: :rebar3, override: true}
+      {:gen_stage, "~> 1.0"},
+      {:flow, "~> 1.0"}
+      # {:ssl_verify_fun, "~> 1.1.7", manager: :rebar3, override: true}
     ]
   end
 end
index 207c2e15623be367ded056f6ce0b60963179abaa..5ca195e4058c2a3de208670e2a74b2d720d99ee3 100644 (file)
--- a/mix.lock
+++ b/mix.lock
@@ -1,6 +1,8 @@
 %{
   "benchee": {:hex, :benchee, "1.1.0", "f3a43817209a92a1fade36ef36b86e1052627fd8934a8b937ac9ab3a76c43062", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}, {:statistex, "~> 1.0", [hex: :statistex, repo: "hexpm", optional: false]}], "hexpm", "7da57d545003165a012b587077f6ba90b89210fd88074ce3c60ce239eb5e6d93"},
   "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"},
+  "flow": {:hex, :flow, "1.2.4", "1dd58918287eb286656008777cb32714b5123d3855956f29aa141ebae456922d", [:mix], [{:gen_stage, "~> 1.0", [hex: :gen_stage, repo: "hexpm", optional: false]}], "hexpm", "874adde96368e71870f3510b91e35bc31652291858c86c0e75359cbdd35eb211"},
+  "gen_stage": {:hex, :gen_stage, "1.2.1", "19d8b5e9a5996d813b8245338a28246307fd8b9c99d1237de199d21efc4c76a1", [:mix], [], "hexpm", "83e8be657fa05b992ffa6ac1e3af6d57aa50aace8f691fcf696ff02f8335b001"},
   "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
   "statistex": {:hex, :statistex, "1.0.0", "f3dc93f3c0c6c92e5f291704cf62b99b553253d7969e9a5fa713e5481cd858a5", [:mix], [], "hexpm", "ff9d8bee7035028ab4742ff52fc80a2aa35cece833cf5319009b52f1b5a86c27"},
 }
index d264e46efab80ae2ab54104cc64f75c33b898784..ffc96d08bd8669a650d832ef7f2a8264716ee840 100644 (file)
@@ -3,19 +3,19 @@ defmodule AdventOfCode.Day01Test do
 
   import AdventOfCode.Day01
 
-  @tag :skip
+  @tag :skip
   test "part1" do
-    input = nil
+    input = AdventOfCode.Input.get!(1, "a")
     result = part1(input)
 
-    assert result
+    assert result == 11
   end
 
-  @tag :skip
+  @tag :skip
   test "part2" do
-    input = nil
+    input = AdventOfCode.Input.get!(1, "a")
     result = part2(input)
 
-    assert result
+    assert result == 31
   end
 end