igorb

igorb

Advent of Code 2023 - Day 16

For Part 1, I was lazy and didn’t want to maintain variables and pass them down to each function (which would also involve merging two different histories after each split), so I used the process dictionary trick I learned about in earlier days from @Aetherus to represent state and have the functions produce side effects (which I thought was ugly). For Part 2, though, I was quite happy with this approach because then I just wrapped this code in Task.async_stream/2 and found the max :slight_smile:

Most Liked

woojiahao

woojiahao

I believe it’s possible to memoize the paths given (row, column, direction). Since you’re just choosing a different starting position, but if the beam traveling left reaches \, it should still be the same path throughout. Though, I did not try this out so it could be false

rugyoga

rugyoga

Pretty straightforward.
A MapSet to prevent loops and brute force.

import AOC

aoc 2023, 16 do
  def p1(input) do
    input
    |> Grid.parse()
    |> then(fn {max, grid} -> {max, Map.new(grid)} end)
    |> compute({{0, 0}, :east})
  end

  def compute(grid, start) do
    grid
    |> recurse([start], MapSet.new(), MapSet.new())
    |> Enum.count()
  end

  def p2(input) do
    {{rows, cols}, points} = input |> Grid.parse()
    grid = {{rows, cols}, Map.new(points)}

    (for row <- 0..(rows-1), do: [{{row, 0}, :east}, {{row, cols-1}, :west}] ++
    for col <- 0..(cols-1), do: [{{0, col}, :south}, {{rows-1, col}, :north}])
    |> List.flatten()
    |> Enum.map(&compute(grid, &1))
    |> Enum.max()
  end

  def recurse(_, [], energized, _), do: energized
  def recurse({_, map} = grid, [active | actives], energized, seen) do
    {active_pos, active_dir} = active
    if not MapSet.member?(seen, active) and Grid.in?(grid, active_pos) do
      energized_new = MapSet.put(energized, active_pos)
      seen_new = MapSet.put(seen, active)
      f = fn candidates -> candidates |> Kernel.++(actives) |> then(&recurse(grid, &1, energized_new, seen_new)) end
      item = map[active_pos]
      cond do
        item == "." or
        (item == "|" and active_dir in [:north, :south]) or
        (item == "-" and active_dir in [:east, :west]) -> f.([next(active)])
        item == "|" -> f.([next({active_pos, :north}), next({active_pos, :south})])
        item == "-" -> f.([next({active_pos, :west}), next({active_pos, :east})])
        item == "/" -> f.([next({active_pos, flip_sw(active_dir)})])
        item == "\\" -> f.([next({active_pos, flip_se(active_dir)})])
      end
    else
      recurse(grid, actives, energized, seen)
    end
  end

  def flip_sw(dir), do: %{north: :east, south: :west, west: :south, east: :north}[dir]
  def flip_se(dir), do: %{north: :west, south: :east, west: :north, east: :south}[dir]
  def next({{row, col}, :west}), do: {{row, col-1}, :west}
  def next({{row, col}, :east}), do: {{row, col+1}, :east}
  def next({{row, col}, :north}), do: {{row-1, col}, :north}
  def next({{row, col}, :south}), do: {{row+1, col}, :south}
end
woojiahao

woojiahao

TIL of ~w()a to generate a list of atoms instead of words, pretty cool!

lud

lud

Hello,

I was afraid that the second part would ask to rotate mirrors to create the maximum energy but thanks it was much easier.

I have no idea how to optimize that so I just simulate all the beams for part 2, and it takes more than one second. Any idea?

lud

lud

Ah yes I generally do not use task async stream because I like to debug the outputs but now that it works, i’ll try it :smiley:

Edit: yeah, 500ms, good enough, thanks!

Also ordered: false comes in handy :smiley:

Where Next?

Popular in Challenges Top

ehayun
I have 2 arrays: a1 can be any combination of value or nil like that a1 = [1,nil,3] and array 2 the same a2 = [4,2, nil] How do I com...
New
JEG2
Note: This topic is to talk about Day 9 of the Advent of Code. For general discussion about the Advent of Code 2018 and links to topics ...
New
Aetherus
This topic is about Day 5 of the Advent of Code 2020 . Thanks to @egze, we have a private leaderboard: https://adventofcode.com/2020/le...
New
igorb
I found today a bit tedious: advent-of-code-2024/lib/advent_of_code2024/day15.ex at main · ibarakaiev/advent-of-code-2024 · GitHub.
New
sukhmeetsd
All in all, from what I understand, it is better not to use GenServer.cast when we want some concurrent operations to happen for sure, be...
New
bjorng
Note: This topic is to talk about Day 3 of the Advent of Code 2019 . There is a private leaderboard for elixirforum members. You can jo...
New
bjorng
My solution finishes both parts in 5 seconds on my computer. That time should be possible to reduce by optimizing my rather naive tilt/2 ...
New
lud
Gosh this one took me sooo much time. At first I was trying to iterate each digit independently on the input A number to make digits cha...
New
bjorng
Note: This topic is to talk about Day 6 of the Advent of Code 2019. There is a private leaderboard for elixirforum members. You can join...
New
igorb
Today is a brute-force day: advent-of-code-2024/lib/advent_of_code2024/day6.ex at main · ibarakaiev/advent-of-code-2024 · GitHub Takes a...
New

Other popular topics Top

dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 45766 226
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 49522 488
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New

We're in Beta

About us Mission Statement