Day 1
Setup
input = Aoc.get_input(1)
textarea = Kino.Input.textarea("Puzzle Input", default: input)
lines =
Kino.Input.read(textarea)
|> String.split("\n", trim: true)
Part 1
lines
|> Enum.map(&String.to_integer(&1))
|> Enum.reduce({nil, 0}, fn
n, {prev, total} when is_integer(prev) and n > prev -> {n, total + 1}
n, {_prev, total} -> {n, total}
end)
|> elem(1)
Part 2
lines
|> Enum.map(&String.to_integer(&1))
|> Enum.reduce({nil, nil, []}, fn
n, {a, nil, xs} -> {n, a, xs}
n, {a, b, xs} -> {n, a, [n + a + b | xs]}
end)
|> elem(2)
|> Enum.reverse()
|> Enum.reduce({nil, 0}, fn
n, {prev, total} when is_integer(prev) and n > prev -> {n, total + 1}
n, {_prev, total} -> {n, total}
end)
|> elem(1)
Part 2 revisited
Improvement over the previous solution by performing a single pass over the list.
lines
|> Enum.map(&String.to_integer(&1))
# {count, n-1, n-2, prev_sum}
|> Enum.reduce({0, nil, nil, nil}, fn
n, {c, a, nil, prev} ->
{c, n, a, prev}
n, {c, a, b, nil} ->
{c, n, a, a + b + n}
n, {c, a, b, prev} ->
next = a + b + n
if next > prev do
{c + 1, n, a, next}
else
{c, n, a, next}
end
end)
|> elem(0)
Nicer to read solution.
lines
|> Enum.map(&String.to_integer/1)
|> Enum.chunk_every(3, 1, :discard)
|> Enum.map(&Enum.sum/1)
|> Enum.chunk_every(2, 1, :discard)
|> Enum.count(fn [a, b] -> a < b end)
When looking at the inputs and comparing the numbers, we have:
$a + b + c < b + c + d$
Which can be simplified to:
$a < d$
lines
|> Enum.map(&String.to_integer/1)
|> Enum.chunk_every(4, 1, :discard)
|> Enum.count(fn [a, _, _, d] -> a < d end)
Using streams, which would not need to make multiple passes.
lines
|> Stream.map(&String.to_integer/1)
|> Stream.chunk_every(4, 1, :discard)
|> Enum.count(fn [a, _, _, d] -> a < d end)