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
I also found today’s puzzle much easier than yesterday’s.
https://github.com/bjorng/advent-of-code-2023/blob/main/day04/lib/day04.ex
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. ![]()
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
You don’t have to convert those numeric strings to integers.
Here’s my code:
https://github.com/Aetherus/advent-of-code/blob/master/2023/day-04.livemd
Popular in Challenges
Other popular topics
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









