Day 20
Mix.install([{:kino, "~>0.8.0"}, {:aja, "~> 0.6.1"}])
Section
file_input = Kino.Input.textarea("file input")
Part 1
alias Aja.Vector
defmodule Day20 do
def mix(input, n, repeat) do
1..repeat
|> Enum.reduce(input, fn _, repeated_acc ->
0..n
|> Enum.reduce(repeated_acc, fn i, acc1 ->
j =
Enum.reduce_while(0..n, acc1, fn j, acc2 ->
{_, idx} = acc1[j]
case idx do
^i -> {:halt, j}
_ -> {:cont, acc2}
end
end)
{val, _} = acc1[j]
{_, popped} = Vector.pop_at(acc1, j)
ins = (j + val) |> Integer.mod(n)
insert_at(popped, ins, {val, i})
end)
end)
end
def index_of(sequence, n, idx) do
Enum.reduce_while(0..(n - 1), nil, fn i, acc ->
case sequence[i] do
{^idx, _} ->
{:halt, i}
_ ->
{:cont, acc}
end
end)
end
def grove_sum(sequence, n, zero_idx) do
[1000, 2000, 3000]
|> Enum.reduce(0, fn pos, acc ->
{val, _} = sequence[rem(zero_idx + pos, n + 1)]
acc + val
end)
end
# Private methods
defp insert_at(vector, idx, value) do
{left, right} = Vector.split(vector, idx)
left |> Vector.concat([value]) |> Vector.concat(right)
end
end
input =
file_input
|> Kino.Input.read()
|> String.split("\n", trim: true)
|> Enum.map(&String.to_integer/1)
|> Enum.with_index()
|> Vector.new()
n = Vector.size(input) - 1
sequence = Day20.mix(input, n, 1)
zero_idx = Day20.index_of(sequence, n, 0)
Day20.grove_sum(sequence, n, zero_idx)
Part 2
alias Aja.Vector
input =
file_input
|> Kino.Input.read()
|> String.split("\n", trim: true)
|> Enum.map(&String.to_integer/1)
|> Enum.with_index()
|> Vector.new()
|> Vector.map(fn {v, i} -> {v * 811_589_153, i} end)
n = Vector.size(input) - 1
sequence = Day20.mix(input, n, 10)
zero_idx = Day20.index_of(sequence, n, 0)
Day20.grove_sum(sequence, n, zero_idx)