Day 3: Binary Diagnostic
Setup
Mix.install([
{:kino, "~> 0.4.1"}
])
:ok
Input
input = Kino.Input.textarea("Input")
Part 1
defmodule M do
def calc(freq, func) do
freq
|> Enum.map(&func.(&1, fn r -> elem(r, 1) end))
|> Enum.map(&elem(&1, 0))
|> List.to_string()
|> String.to_integer(2)
end
end
Kino.Input.read(input)
|> String.split()
|> Enum.map(&String.to_charlist/1)
|> Enum.zip()
|> Enum.map(&Tuple.to_list/1)
|> Enum.map(&Enum.frequencies/1)
|> then(fn freq ->
M.calc(freq, &Enum.max_by/2) * M.calc(freq, &Enum.min_by/2)
end)
1997414
Part 2
defmodule M do
defp freq_bit(li, max_fn) do
li
|> Enum.frequencies()
|> max_fn.()
|> then(fn r -> elem(r, 0) end)
end
def filter(li, position, max_fn) do
if length(li) == 1 do
li
else
filter(do_filter(li, position, max_fn), position + 1, max_fn)
end
end
defp do_filter(li, position, max_fn) do
li
|> Enum.zip()
|> Enum.at(position)
|> Tuple.to_list()
|> freq_bit(max_fn)
|> then(fn bit ->
Enum.filter(li, fn l -> Enum.at(l, position) == bit end)
end)
end
defp max(li) do
Enum.max_by(
li,
fn r -> elem(r, 1) end,
fn x, y -> x > y end
)
end
defp min(li) do
Enum.min_by(
li,
fn r -> elem(r, 1) end,
fn x, y -> x <= y end
)
end
def oxygen(li) do
li
|> filter(0, &max/1)
|> Enum.at(0)
|> List.to_string()
|> String.to_integer(2)
end
def co2(li) do
li
|> filter(0, &min/1)
|> Enum.at(0)
|> List.to_string()
|> String.to_integer(2)
end
end
Kino.Input.read(input)
|> String.split()
|> Enum.map(&String.to_charlist/1)
|> then(&(M.oxygen(&1) * M.co2(&1)))
1032597