diff options
Diffstat (limited to 'src/day22.exs')
-rw-r--r-- | src/day22.exs | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/day22.exs b/src/day22.exs new file mode 100644 index 0000000..418631f --- /dev/null +++ b/src/day22.exs @@ -0,0 +1,65 @@ +defmodule Day22 do + def part1(data, n \\ 2000) do + data + |> String.split("\n", trim: true) + |> Enum.map(&String.to_integer/1) + |> Enum.map(&(secret_numbers(&1, n))) + |> Enum.map(&hd/1) + |> Enum.sum() + end + + defp secret_numbers(v, n) do + for _ <- 1..n, reduce: [v] do + v -> + [(v |> hd() |> change_value(6) |> change_value(-5) |> change_value(11)) | v] + end + end + + defp change_value(v, shift) do + v + |> Bitwise.bsl(shift) + |> Bitwise.bxor(v) + |> Integer.mod(16777216) + end + + def part2(data, n \\ 2000) do + data + |> String.split("\n", trim: true) + |> Enum.map(&String.to_integer/1) + |> Enum.map(&(secret_numbers(&1, n))) + |> Enum.map(&(sequences(&1, 10))) + |> Enum.reduce(%{}, fn s, acc -> + Map.merge(acc, s, fn _k, v1, v2 -> v1 + v2 end) + end) + |> Map.values() + |> Enum.max() + end + + defp sequences(vs, m) do + vs + |> Enum.map(&Integer.mod(&1, m)) + |> Enum.chunk_every(5, 1, :discard) # performance here could be improved + |> Enum.map(fn chunk -> {diffs(chunk), hd(chunk)} end) + |> Map.new() + end + + defp diffs(vs) do + vs + |> Enum.chunk_every(2, 1, :discard) + |> Enum.map(fn [a, b] -> a - b end) + |> List.to_tuple() + end +end + +data = IO.read(:stdio, :eof) + +{time1, ans1} = :timer.tc(fn -> Day22.part1(data) end) +IO.puts("Time : #{time1 / 1000000}") +IO.puts("Answer: #{ans1}") # 19822877190 + +{time2, ans2} = :timer.tc(fn -> Day22.part2(data) end) +IO.puts("Time : #{time2 / 1000000}") +IO.puts("Answer: #{ans2}") # 2277 + + + |