Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Advent 2021 - Day 8

day8.livemd

Advent 2021 - Day 8

Setup

Mix.install([
  {:kino, github: "livebook-dev/kino"}
])
input = Kino.Input.textarea("Please paste your input file:")
parsed =
  input
  |> Kino.Input.read()
  |> String.trim()
  |> String.split("\n")
  |> Enum.map(fn line ->
    line |> String.split(" | ") |> Enum.map(&String.split(&1, " "))
  end)

Utils

defmodule Utils do
  def string_to_mapset(string) do
    string
    |> String.graphemes()
    |> MapSet.new()
  end
end

Part 1

parsed
|> Enum.map(fn [_ | output] -> output end)
|> List.flatten()
|> Enum.count(fn string ->
  len = String.length(string)

  len == 2 or len == 4 or len == 3 or len == 7
end)

Part 2

This part 2 had me pretty stumped…

Used some pointers from https://github.com/nint8835/AdventOfCode2021/blob/main/Day8/Day8.fsx in the production of this solution, thanks Riley!

all_outputs =
  for [input, output] <- parsed do
    everything = [input | output] |> List.flatten()

    known_digits = %{
      1 => everything |> Enum.find(&amp;(String.length(&amp;1) == 2)) |> Utils.string_to_mapset(),
      4 => everything |> Enum.find(&amp;(String.length(&amp;1) == 4)) |> Utils.string_to_mapset(),
      7 => everything |> Enum.find(&amp;(String.length(&amp;1) == 3)) |> Utils.string_to_mapset(),
      8 => everything |> Enum.find(&amp;(String.length(&amp;1) == 7)) |> Utils.string_to_mapset()
    }

    intersection_check = [known_digits[1], known_digits[4], known_digits[7], known_digits[8]]

    scrambled_to_value =
      everything
      |> Enum.map(fn value ->
        set = Utils.string_to_mapset(value)

        intersections =
          Enum.map(intersection_check, fn check ->
            MapSet.intersection(check, set) |> Enum.count()
          end)
          |> List.to_tuple()

        case intersections do
          {2, 2, 2, 2} -> {set, 1}
          {1, 2, 2, 5} -> {set, 2}
          {2, 3, 3, 5} -> {set, 3}
          {2, 4, 2, 4} -> {set, 4}
          {1, 3, 2, 5} -> {set, 5}
          {1, 3, 2, 6} -> {set, 6}
          {2, 2, 3, 3} -> {set, 7}
          {2, 4, 3, 7} -> {set, 8}
          {2, 4, 3, 6} -> {set, 9}
          {2, 3, 3, 6} -> {set, 0}
          _ -> nil
        end
      end)
      |> Map.new()

    output
    |> Enum.map(fn value ->
      Map.get(scrambled_to_value, Utils.string_to_mapset(value))
      |> Integer.to_string()
    end)
    |> Enum.join("")
    |> String.to_integer()
  end

Enum.sum(all_outputs)