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