Advent of Code 2020 in Elixir - Day 10

Adapter Array

defmodule Aoc2020.Day10 do
  @moduledoc "Adapter Array"

  def run(), do: part_2()

  def part_1() do
    parse_input()
    |> complete_range()
    |> Enum.chunk_every(2, 1, :discard)
    |> Enum.map(fn [a, b] -> b - a end)
    |> Enum.frequencies()
    |> (fn counts -> Map.fetch!(counts, 1) * Map.fetch!(counts, 3) end).()
  end

  def part_2() do
    parse_input()
    |> complete_range()
    |> calculate_variations()
    |> Map.fetch!(0)
  end

  def parse_input() do
    File.read!("priv/inputs/2020/day10.txt")
    |> String.trim()
    |> String.split("\n")
    |> Enum.map(fn line -> String.to_integer(line) end)
    |> Enum.sort()
  end

  def complete_range(input) do
    [0 | input] ++ [List.last(input) + 3]
  end

  # part 2
  def calculate_variations(adapters) do
    reversed = Enum.reverse(adapters)

    Enum.reduce(tl(reversed), %{}, fn adapter, acc ->
      within_3 = Enum.filter(reversed, fn x -> x > adapter && x <= adapter + 3 end)

      variations_from_here =
        Enum.reduce(within_3, 0, fn next, acc2 ->
          acc2 + Map.get(acc, next, 1)
        end)

      Map.put(acc, adapter, variations_from_here)
    end)
  end
end