seeplusplus

seeplusplus

Advent of Code 2023 - Day 4

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 before work!)

My set-up:

defmodule Card do
  defp to_list_numbers(str) do
    str 
    |> String.split(" ")
    |> Enum.filter(fn s -> String.length(s) !== 0 end)
    |> Enum.map(fn u ->
      {i, _} = Integer.parse(u)
      i
    end)
  end
  def parse("Card " <> rest) do
    [_, numbers] = rest |> String.split(":")
    [winning, player] = numbers |> String.split("|")
    [winning |> String.trim() |> to_list_numbers(), player |> String.trim() |> to_list_numbers()]
  end
end

cards = for card <- input |> String.split("\n"),
[winning_numbers, our_numbers] = Card.parse(card) do
  [winning_numbers, our_numbers]
end

Then part 1 was really simple (10 minutes from start for me to get here):


for [winning_numbers, our_numbers] <- cards
do
  case count_winning_cards.(our_numbers, winning_numbers) do
    n when n > 0 -> 2**(n-1)
    0 -> 0
  end
end |> Enum.sum()

Part 2 slightly less so (40 minutes from start to get here):


cards 
  |> Enum.with_index()
  |> Enum.reduce(
    List.duplicate(1, cards |> Enum.count()),
    fn {[winning, player], idx}, copies ->
      self_copies = Enum.at(copies, idx)
      won = count_winning_cards.(player, winning)
      slice = if won > 0, do: (idx+1)..(idx+won), else: ..
      copies |> Enum.with_index() |> Enum.map(
        fn {count, idx} ->
          if idx in slice, do: count + self_copies, else: count
        end
      )
    end
  ) |> Enum.sum()

The biggest time sink for me was remembering that 1..1 is a non-empty range in Elixir, so I needed to write the slice to be:

      slice = if won > 0, do: (idx+1)..(idx+won), else: ..

Most Liked

bjorng

bjorng

Erlang Core Team

I also found today’s puzzle much easier than yesterday’s.

nico.t

nico.t

It seems many people don’t know that we can pass a list of characters as 2nd argument of String.split/2.
It is pretty useful when parsing your input.
Think about it in the coming days. :wink:

iex(1)> line = "Card 1: 41 48 83 86 17 | 83 86  6 31 17  9 48 53"
"Card 1: 41 48 83 86 17 | 83 86  6 31 17  9 48 53"
iex(2)> ["Card " <> id, winning, mine] = String.split(line, [":", "|"])
["Card 1", " 41 48 83 86 17 ", " 83 86  6 31 17  9 48 53"]
iex(3)> winning = String.split(winning)
["41", "48", "83", "86", "17"]
iex(4)> mine = String.split(mine)
["83", "86", "6", "31", "17", "9", "48", "53"]
iex(5)> id
"1"
Aetherus

Aetherus

You don’t have to convert those numeric strings to integers.

Here’s my code:

Aetherus

Aetherus

I heard that when running a -- b, the Erlang runtime will first convert b to a red-black tree if b is long enough (maybe when length(b) > 32). If that’s the case, then a -- a -- b can be as performant as MapSet.intersection(set1, set2).

Aetherus

Aetherus

Learned Map.get_and_update.

Where Next?

Popular in Challenges Top

dominicletz
This topic is about Day 8 of the Advent of Code 2020 . Thanks to @egze, we have a private leaderboard: https://adventofcode.com/2020/le...
New
LostKobrakai
This one has been quite the ride. Struggled at first to find a good data format to suite the problem. I really like how that turned out b...
New
bjorng
Note: This topic is to talk about Day 9 of the Advent of Code 2019. There is a private leaderboard for elixirforum members. You can join...
New
christhekeele
Setting this down for the night, as after a quick naive solve for quick part 1 I realize that part 2 is by design computationally expensi...
New
bjorng
This topic is about Day 15 of the Advent of Code 2021. We have a private leaderboard (shared with users of Erlang Forums): https://adve...
New
bjorng
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
adamu
Probably not the most efficient implementation, because part 1 took &gt;1 ms and part 2 &gt;4ms, but the code was simple enough. def p...
New
connorlay
Note by the Moderators: This topic is for general discussion about the Advent of Code 2018. To prevent people from being spoiled about s...
New
bjorng
Note: This topic is to talk about Day 4 of the Advent of Code 2019. There is a private leaderboard for elixirforum members. You can join...
New
christhekeele
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 Top

shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list....
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New
beno
I will often find my self writing things similar to: case some_value do nil -&gt; something() "" -&gt; something() _ -&gt; someth...
New

We're in Beta

About us Mission Statement