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

Day 11

2023/day11.livemd

Day 11

Mix.install([
  {:nx, "~> 0.5"},
  {:kino, "~> 0.11.3"}
])

Section

input = Kino.Input.textarea("Input")
input_data = Kino.Input.read(input)

defmodule Sol11 do
  def read(input_data) do
    # Output a map {row, col} -> symbol

    rows =
      input_data
      |> String.split("\n")

    rows_with_index = Enum.zip(1..length(rows), rows)

    points =
      Enum.map(rows_with_index, fn {row_idx, row} ->
        Enum.zip(1..String.length(row), String.to_charlist(row))
        |> Enum.map(fn {col_idx, symbol} -> {row_idx, col_idx, symbol} end)
      end)
      |> Enum.flat_map(& &1)

    Enum.reduce(points, %{}, fn {row_idx, col_idx, symbol}, acc ->
      Map.put(acc, {row_idx, col_idx}, symbol)
    end)
  end

  def find_row_galaxy_sum(data) do
    {row_n, col_n} = Enum.max(Map.keys(data))

    row_counts =
      for row_id <- 1..row_n, reduce: %{} do
        acc ->
          Map.put(
            acc,
            row_id,
            Enum.filter(1..col_n, fn col_id -> data[{row_id, col_id}] == ?# end)
            |> Enum.count()
          )
      end

    col_counts =
      for col_id <- 1..col_n, reduce: %{} do
        acc ->
          Map.put(
            acc,
            col_id,
            Enum.filter(1..row_n, fn row_id -> data[{row_id, col_id}] == ?# end)
            |> Enum.count()
          )
      end

    {row_counts, col_counts}
  end

  def find_all_galaxy(data, expand_rate) do
    {row_counts, col_counts} = Sol11.find_row_galaxy_sum(data)

    expand_rows =
      MapSet.new(
        for row <- Map.keys(row_counts), row_counts[row] == 0 do
          row
        end
      )

    expand_cols =
      MapSet.new(
        for col <- Map.keys(col_counts), col_counts[col] == 0 do
          col
        end
      )

    galaxies = Enum.filter(Map.keys(data), &amp;(data[&amp;1] == ?#))

    for {r1, c1} <- galaxies, {r2, c2} <- galaxies, {r1, c1} < {r2, c2} do
      abs(r2 - r1) + abs(c2 - c1) +
        expand_rate * MapSet.size(MapSet.intersection(MapSet.new(r1..r2), expand_rows)) +
        expand_rate * MapSet.size(MapSet.intersection(MapSet.new(c1..c2), expand_cols))
    end
    |> Enum.sum()
  end
end

data = Sol11.read(input_data)
Sol11.find_all_galaxy(data, 1_000_000 - 1)
0..2