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

Advent of Code 2023 Day 13 Part 1

2023_day13_part1.livemd

Advent of Code 2023 Day 13 Part 1

Mix.install([
  {:kino_aoc, "~> 0.1"},
  {:nx, "~> 0.9.2"}
])

Get Inputs

{:ok, puzzle_input} =
  KinoAOC.download_puzzle("2023", "13", System.fetch_env!("LB_SESSION"))

My answer

block =
  Nx.tensor([
    [1, 0, 0, 0, 0, 1, 0],
    [1, 0, 0, 0, 0, 1, 1],
    [0, 1, 1, 1, 1, 0, 0],
    [0, 1, 1, 1, 1, 0, 0],
    [1, 0, 0, 0, 0, 1, 1],
    [1, 0, 1, 1, 0, 1, 0],
    [0, 1, 1, 1, 1, 0, 1]
  ])
{num_rows, num_cols} = Nx.shape(block)
0..(num_rows - 2)
|> Enum.map(fn row_index ->
  range = min(row_index + 1, num_rows - row_index - 1)

  {
    Nx.slice_along_axis(block, row_index - range + 1, range, axis: 0),
    Nx.slice_along_axis(block, row_index + 1, range, axis: 0) |> Nx.reverse(axes: [0])
  }
end)
0..(num_rows - 2)
|> Enum.find(fn row_index ->
  range = min(row_index + 1, num_rows - row_index - 1)

  Nx.equal(
    Nx.slice_along_axis(block, row_index - range + 1, range, axis: 0),
    Nx.slice_along_axis(block, row_index + 1, range, axis: 0) |> Nx.reverse(axes: [0])
  )
  |> Nx.all()
  |> Nx.to_number()
  |> Kernel.==(1)
end)
0..(num_cols - 2)
|> Enum.find(fn col_index ->
  range = min(col_index + 1, num_cols - col_index - 1)

  Nx.equal(
    Nx.slice_along_axis(block, col_index - range + 1, range, axis: 1),
    Nx.slice_along_axis(block, col_index + 1, range, axis: 1) |> Nx.reverse(axes: [1])
  )
  |> Nx.all()
  |> Nx.to_number()
  |> Kernel.==(1)
end)
0..1
|> Enum.map(fn axis ->
  num = Nx.shape(block) |> elem(axis)

  0..(num - 2)
  |> Enum.find(fn index ->
    range = min(index + 1, num - index - 1)

    Nx.equal(
      Nx.slice_along_axis(block, index - range + 1, range, axis: axis),
      Nx.slice_along_axis(block, index + 1, range, axis: axis) |> Nx.reverse(axes: [axis])
    )
    |> Nx.all()
    |> Nx.to_number()
    |> Kernel.==(1)
  end)
end)
blocks =
  puzzle_input
  |> String.split("\n\n")
  |> Enum.map(fn block ->
    block
    |> String.split("\n")
    |> Enum.map(fn row ->
      String.codepoints(row)
      |> Enum.map(fn tile -> if tile == "#", do: 1, else: 0 end)
    end)
    |> Nx.tensor()
  end)
blocks
|> Enum.map(fn block ->
  0..1
  |> Enum.map(fn axis ->
    num = Nx.shape(block) |> elem(axis)

    0..(num - 2)
    |> Enum.find(fn index ->
      range = min(index + 1, num - index - 1)

      Nx.equal(
        Nx.slice_along_axis(block, index - range + 1, range, axis: axis),
        Nx.slice_along_axis(block, index + 1, range, axis: axis) |> Nx.reverse(axes: [axis])
      )
      |> Nx.all()
      |> Nx.to_number()
      |> Kernel.==(1)
    end)
    |> then(fn index -> if is_nil(index), do: 0, else: index + 1 end)
    |> then(fn num -> if axis == 0, do: num * 100, else: num end)
  end)
  |> Enum.sum()
end)
|> Enum.sum()