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

AoC 2022 Day 1 Visualization

2022/day01/viz.livemd

AoC 2022 Day 1 Visualization

Section

Mix.install([
  {:explorer, "~> 0.4.0"},
  {:vega_lite, "~> 0.1.6"},
  {:kino_vega_lite, "~> 0.1.6"}
])
# needed to use Explorer.DataFrame.arrange/2 macro
require Explorer.DataFrame
alias Explorer.DataFrame, as: DF
alias VegaLite, as: Vl
calories_per_elf =
  File.read!("./input.txt")
  |> String.split("\n\n", trim: true)
  |> Stream.with_index()
  |> Enum.group_by(fn {_, i} -> "Elf #{i}" end, fn {s, _} ->
    String.split(s, "\n", trim: true)
    |> Enum.map(&String.to_integer/1)
  end)
  |> Enum.reduce(%{names: [], calories: []}, fn {k, [v]}, %{names: n, calories: c} = acc ->
    %{acc | names: [k | n], calories: [Enum.sum(v) | c]}
  end)
sorted_elves =
  calories_per_elf
  |> DF.new()
  |> DF.arrange(desc: calories)
sorted_elves
|> Kino.DataTable.new()
top_50 =
  sorted_elves
  |> DF.head(50)

Vl.new(title: "Calories Carried by Elf (top 50)", width: 600, height: 400)
|> Vl.data_from_values(top_50)
|> Vl.mark(:bar, corner_radius_end: 50)
|> Vl.encode_field(:x, "names", sort: "-y", type: :nominal)
|> Vl.encode_field(:y, "calories", type: :quantitative)
|> Vl.encode_field(:color, "names", sort: "-y", scale: %{scheme: "tableau20"})