Part 1:
all =
puzzle_input
|> String.split("\n", trim: true)
|> Enum.map(fn line ->
line
|> String.split(" ", trim: true)
|> Enum.map(&String.to_integer/1)
end)
safe? = fn levels ->
Enum.reduce_while(levels, {nil, nil}, fn a, acc ->
case acc do
{nil, _} ->
{:cont, {a, nil}}
{b, nil} when abs(a - b) in [1, 2, 3] and a < b ->
{:cont, {a, :decrease}}
{b, nil} when abs(a - b) in [1, 2, 3] and a > b ->
{:cont, {a, :increase}}
{b, :decrease} when abs(a - b) in [1, 2, 3] and a < b ->
{:cont, {a, :decrease}}
{b, :increase} when abs(a - b) in [1, 2, 3] and a > b ->
{:cont, {a, :increase}}
_ ->
{:halt, :invalid}
end
end)
|> case do
:invalid -> false
_ -> true
end
end
for levels <- all do
safe?.(levels)
end
|> Enum.count(& &1)
Part 2:
all =
puzzle_input
|> String.split("\n", trim: true)
|> Enum.map(fn line ->
line
|> String.split(" ", trim: true)
|> Enum.map(&String.to_integer/1)
end)
damp = fn levels ->
levels
|> Enum.with_index()
|> Enum.map(fn {_, i} -> List.delete_at(levels, i) end)
end
safe? = fn levels ->
Enum.reduce_while(levels, {nil, nil}, fn a, acc ->
case acc do
{nil, _} ->
{:cont, {a, nil}}
{b, nil} when abs(a - b) in [1, 2, 3] and a < b ->
{:cont, {a, :decrease}}
{b, nil} when abs(a - b) in [1, 2, 3] and a > b ->
{:cont, {a, :increase}}
{b, :decrease} when abs(a - b) in [1, 2, 3] and a < b ->
{:cont, {a, :decrease}}
{b, :increase} when abs(a - b) in [1, 2, 3] and a > b ->
{:cont, {a, :increase}}
_ ->
{:halt, :invalid}
end
end)
|> case do
:invalid -> false
_ -> true
end
end
for levels <- all do
safe?.(levels) || Enum.any?(damp.(levels), fn level -> safe?.(level) end)
end
|> Enum.count(& &1)






















