woojiahao
Advent of Code 2023 - Day 13
Fun day today! Quite straightforward but the key observations are:
Spoilers
- Finding the column-wise reflection line is the same as transposing the pattern and finding the row-wise reflection line so we just need to develop 1 search algorithm
- Smudges correspond to the differences between rows, so if the total differences is exactly 1, then a smudge can exist
- We only need to compare between the minimum between the (top, bottom) from the reflection line, this saves a teeny bit of time
https://github.com/woojiahao/aoc/blob/main/lib/aoc/2023/day_13.ex
Most Liked
bjorng
Erlang Core Team
The approach I took for solving part 1 was not useful for part 1, so I had to rewrite my solver so that it was able to handle part 2.
My solution:
https://github.com/bjorng/advent-of-code-2023/blob/main/day13/lib/day13.ex
3
midouest
Went with Nx again for today’s problem.
Part 1
defmodule Part1 do
def parse(input) do
for pattern <- String.split(input, "\n\n") do
for line <- String.split(pattern, "\n", trim: true) do
String.graphemes(line)
|> Enum.map(fn c -> if c == "#", do: 1, else: 0 end)
end
|> Nx.tensor(type: :u8, names: [:y, :x])
end
end
def summarize(patterns) do
for pattern <- patterns do
{axis, {index, _}} =
reflect(pattern)
left = index + 1
if axis == :x, do: left, else: 100 * left
end
|> Enum.sum()
end
def reflect(pattern) do
[:x, :y]
|> Enum.map(fn axis -> {axis, reflect_along(pattern, axis)} end)
|> Enum.max_by(fn {_, {_, size}} -> size end)
end
def reflect_along(pattern, axis) do
0..Nx.axis_size(pattern, axis)
|> Enum.reduce({-1, -1}, fn index, {_, prev_size} = prev ->
{_, next_size} = next = reflect_at(pattern, axis, index)
if next_size > prev_size, do: next, else: prev
end)
end
def reflect_at(pattern, axis, index), do: reflect_at(pattern, axis, index, index + 1)
def reflect_at(pattern, axis, left, right) do
if left < 0 or right >= Nx.axis_size(pattern, axis) do
reflection(left + 1, right - 1)
else
left_tensor = pattern[Keyword.new([{axis, left}])]
right_tensor = pattern[Keyword.new([{axis, right}])]
if left_tensor != right_tensor do
{-1, -1}
else
reflect_at(pattern, axis, left - 1, right + 1)
end
end
end
def reflection(left, right) when left > right, do: {-1, -1}
def reflection(left, right) do
size = div(right - left, 2)
{left + size, size}
end
end
input
|> Part1.parse()
|> Part1.summarize()
Part 2
defmodule Part2 do
def summarize(patterns) do
for pattern <- patterns do
{axis, {index, _}} =
reflect(pattern)
left = index + 1
if axis == :x, do: left, else: 100 * left
end
|> Enum.sum()
end
def reflect(pattern) do
[:x, :y]
|> Enum.map(fn axis -> {axis, reflect_along(pattern, axis)} end)
|> Enum.max_by(fn {_, {_, size}} -> size end)
end
def reflect_along(pattern, axis) do
0..Nx.axis_size(pattern, axis)
|> Enum.reduce({-1, -1}, fn index, prev ->
{start, size, smudge} = reflect_at(pattern, axis, index)
if smudge, do: {start, size}, else: prev
end)
end
def reflect_at(pattern, axis, index), do: reflect_at(pattern, axis, index, index + 1, false)
def reflect_at(pattern, axis, left, right, smudge) do
if left < 0 or right >= Nx.axis_size(pattern, axis) do
reflection(left + 1, right - 1, smudge)
else
left_tensor = pattern[Keyword.new([{axis, left}])]
right_tensor = pattern[Keyword.new([{axis, right}])]
if left_tensor != right_tensor do
if smudge or
Nx.equal(left_tensor, right_tensor)
|> Nx.logical_not()
|> Nx.sum() != Nx.tensor(1, type: :u64) do
{-1, -1, false}
else
reflect_at(pattern, axis, left - 1, right + 1, true)
end
else
reflect_at(pattern, axis, left - 1, right + 1, smudge)
end
end
end
def reflection(left, right, _) when left > right, do: {-1, -1, false}
def reflection(left, right, smudge) do
size = div(right - left, 2)
{left + size, size, smudge}
end
end
input
|> Part1.parse()
|> Part2.summarize()
3
Aetherus
I’m so not proud of my code. Just a pile of junk. Ctrl+C & Ctrl+V everywhere. Anyway, I post it here.
https://github.com/Aetherus/advent-of-code/blob/master/2023/day-13.livemd
2
Popular in Challenges
So… that’s it? Everyone is stuck on part 2? :slight_smile: I looked at Reddit hints and thought I probably wouldn’t have come up with the...
New
This topic is about Day 10 of the Advent of Code 2021.
We have a private leaderboard (shared with users of Erlang Forums ):
https://adv...
New
Here is my solution:
https://github.com/bjorng/advent-of-code-2021/blob/77bdef7a51b428b58ffb4ab76f540901e636f841/day12/lib/day12.ex
New
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
A frustrating one for me. I spent a long time trying to understand why some combinations resulted in fewer presses and struggled to keep ...
New
This is my second year doing AoC in Elixir and my first year doing it with Livebook.
When I was doing just plain Elixir I usually set up...
New
Hello all, hopefully I post this before someone else does and I don’t dupe.
IMO Day 4 was much easier than Day 3 (yay, I can sleep befor...
New
Anyone else think the prompt for this challenge is contradictory?
The rules for comparing packets include
If both values are lists, c...
New
Anyone have a solution to Part 2 today? Part 1 was straight forward, but I can’t figure out a programatic way to do part 2. I understand ...
New
Thought I’d kick today’s thread off!
Parsing
Enum rocks, so most of my code was actually in parsing input.
▶ Preprocessing input
Part 1...
New
Other popular topics
Hello!
tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability.
After spen...
New
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
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
In templates/appointment/index.html.eex:
<%= for appointment <- @appointments do %>
<tr>
<td><%= appoi...
New
lets say i have a sample like
a = 20; b = 10;
if (a > b) do
{:ok, "a"}
end
if (a < b) do
{:ok, b}
end
if (a == b) do
{:ok, "equa...
New
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this:
...
New
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum.
...
New
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine)
This is a plugin that adds support for Elixir to JetBrains IntelliJ...
New
Hi there,
I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








