— Day 2: Red-Nosed Reports —
Mix.install([{:kino_aoc, "~> 0.1"}])
Section
{:ok, puzzle_input} =
  KinoAOC.download_puzzle("2024", "2", System.fetch_env!("LB_AOC_SESSION_COOKIE"))
defmodule RedNosedReports do
  def parse(input) do
    input
    |> String.split("\n")
    |> Enum.map(fn report ->
      for level <- String.split(report) do
        String.to_integer(level)
      end
    end)
  end
  def ordered?(report) do
    asc? = report == Enum.sort(report)
    desc? = report == Enum.sort(report, :desc)
    asc? || desc?
  end
  def gradual?([first | rest]) do
    result =
      Enum.reduce_while(rest, first, fn
        next_level, prev_level ->
          if abs(prev_level - next_level) in 1..3 do
            {:cont, next_level}
          else
            {:halt, :unsafe}
          end
      end)
    result != :unsafe
  end
  def safe?(report), do: ordered?(report) && gradual?(report)
  def dampener(report) do
    if safe?(report) do
      true
    else
      Enum.reduce_while(report, false, fn level, _acc ->
        if safe?(report -- [level]) || safe?(Enum.reverse(report) -- [level]) do
          {:halt, true}
        else
          {:cont, false}
        end
      end)
    end
  end
end
import RedNosedReports
puzzle_input
|> parse()
|> Enum.map(&safe?/1)
|> Enum.count(& &1)
import RedNosedReports
puzzle_input
|> parse()
|> Enum.map(&dampener/1)
|> Enum.count(& &1)