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

Advent of Code 2015 Day 18 Part 2

2015_day18_part2.livemd

Advent of Code 2015 Day 18 Part 2

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

Get Inputs

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

My answer

lights =
  puzzle_input
  |> String.split("\n")
  |> Enum.map(fn row ->
    row
    |> String.codepoints()
    |> Enum.map(fn light -> if light == "#", do: 1, else: 0 end)
  end)
  |> Nx.tensor()
tb_lights =
  1..100
  |> Enum.map(fn index -> if index == 1 or index == 100, do: 1, else: 0 end)
  |> Nx.tensor()
  |> Nx.new_axis(1)
inner_lights = Nx.broadcast(0, {100, 98})
corner_lights =
  Nx.concatenate(
    [tb_lights, inner_lights, tb_lights],
    axis: 1
  )
lights = Nx.logical_or(lights, corner_lights)
1..100
|> Enum.reduce(lights, fn _, acc_lights ->
  around_on =
    acc_lights
    |> Nx.pad(0, [{1, 1, 0}, {1, 1, 0}])
    |> Nx.window_sum({3, 3})
    |> Nx.subtract(acc_lights)

  current_on_next_on =
    Nx.multiply(
      acc_lights,
      Nx.multiply(Nx.greater_equal(around_on, 2), Nx.less_equal(around_on, 3))
    )

  current_off_next_on =
    Nx.multiply(
      Nx.equal(acc_lights, 0),
      Nx.equal(around_on, 3)
    )

  Nx.add(current_on_next_on, current_off_next_on)
  |> Nx.logical_or(corner_lights)
end)
|> Nx.sum()