stevensonmt

stevensonmt

Advent Of Code 2022 - Day 13

Anyone else think the prompt for this challenge is contradictory?
The rules for comparing packets include

  • If both values are lists, compare the first value of each list, then the second value, and so on. If the left list runs out of items first, the inputs are in the right order. If the right list runs out of items first, the inputs are not in the right order. If the lists are the same length and no comparison makes a decision about the order, continue checking the next part of the input.
  • If exactly one value is an integer, convert the integer to a list which contains that integer as its only value, then retry the comparison. For example, if comparing [0,0,0] and 2, convert the right value to [2] (a list containing 2); the result is then found by instead comparing [0,0,0] and [2].

But if you compare lists according to the rules, [0,0,0] vs [2] should be incorrect order since the right side runs out of items first. But the sample data evaluation we’re told

Compare [2,3,4] vs 4
- Mixed types; convert right to [4] and retry comparison
- Compare [2,3,4] vs [4]
- Compare 2 vs 4
- Left side is smaller, so inputs are in the right order

So the rule for “list vs wrapped integer” is not the same as the rule for “list vs list”. Am I crazy?

Most Liked

lud

lud

I have the same kind of solution, but my compare/2 function returns :lt | :gt | :eq which means that I can call Enum.sort(packets, __MODULE__)

defmodule Aoe.Y22.Day13 do
  alias Aoe.Input

  def read_file!(file, _part) do
    Input.read!(file)
  end

  def parse_input!(input, _part) do
    input
    |> String.trim()
    |> String.split("\n")
    |> Enum.flat_map(&parse_line/1)
  end

  defp parse_line("") do
    []
  end

  defp parse_line(text) do
    [Jason.decode!(text)]
  end

  def part_one(packets) do
    packets
    |> Enum.chunk_every(2)
    |> Enum.map(&compare/1)
    |> Enum.with_index(1)
    |> Enum.filter(fn {order, _} -> order == :lt end)
    |> Enum.reduce(0, fn {_, index}, acc -> acc + index end)
  end

  def part_two(packets) do
    [[[2]], [[6]] | packets]
    |> Enum.sort(__MODULE__)
    |> Enum.with_index(1)
    |> Enum.filter(fn {p, _} -> p == [[6]] or p == [[2]] end)
    |> case(do: ([{_, a}, {_, b}] -> a * b))
  end

  def compare([left, right]) do
    compare(left, right)
  end

  def compare([a | as], [b | bs]) do
    case compare(a, b) do
      :eq -> compare(as, bs)
      other -> other
    end
  end

  def compare([], []) do
    :eq
  end

  def compare([], [_ | _]) do
    :lt
  end

  def compare([_ | _], []) do
    :gt
  end

  def compare(a, b) when is_integer(a) and is_integer(b) do
    cond do
      a < b -> :lt
      a > b -> :gt
      a == b -> :eq
    end
  end

  def compare(a, b) when is_list(a) and is_integer(b) do
    compare(a, [b])
  end

  def compare(a, b) when is_integer(a) and is_list(b) do
    compare([a], b)
  end
end

Every year I start doing AoC in Rust now, but after a week I have no time for it since I have to work, so I fallback on Elixir and then it feels like cheating :smiley:

reobin

reobin

Using &Enum.sort/2 in part 2 with absolutely no modifications to the comparator was something else

kwando

kwando

Turned out okay, I don’t dare to clean this up more now that it works :sweat_smile:
Code.eval_string saved me from some parsing fun.

kwando

kwando

Nice, looks very clean :slight_smile:

mruoss

mruoss

I was having a hard time understanding the rules, too. The thing is, when you traverse two lists, you stop as soon as the result is either right or wrong. Only if it stays undecided until one of the lists are out of items, then that rule decides.

Today it felt like an Elixir puzzle again…

Parsing:

parsed =
  input_field
  |> Kino.Input.read()
  |> String.split("\n", trim: true)
  |> Enum.map(&Code.eval_string/1)
  |> Enum.map(&elem(&1, 0))
  |> Enum.chunk_every(2)

Decoder:

defmodule Decoder do
  def compare([], []), do: :none
  def compare([_ | _], []), do: false
  def compare([], [_ | _]), do: true

  def compare([a | resta], [b | restb]) do
    case compare(a, b) do
      :none -> compare(resta, restb)
      other -> other
    end
  end

  def compare(a, b) when is_integer(a) and is_integer(b) do
    cond do
      a < b -> true
      a > b -> false
      true -> :none
    end
  end

  def compare(a, b), do: compare(List.wrap(a), List.wrap(b))
end

Part 1:

parsed
|> Enum.map(fn [a, b] -> Decoder.compare(a, b) end)
|> Enum.with_index(1)
|> Enum.filter(&(elem(&1, 0) == true))
|> Enum.map(&elem(&1, 1))
|> Enum.sum()

Part 2:

sorted =
  [[[[2]], [[6]]] | parsed]
  |> Enum.flat_map(&Function.identity/1)
  |> Enum.sort(&Decoder.compare/2)

divider_packet_1 = Enum.find_index(sorted, &(&1 == [[2]])) + 1
divider_packet_2 = Enum.find_index(sorted, &(&1 == [[6]])) + 1
divider_packet_1 * divider_packet_2

Where Next?

Popular in Challenges Top

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
bjorng
Note: This topic is to talk about Day 25 of the Advent of Code 2019. There is a private leaderboard for elixirforum members. You can joi...
New
Aetherus
This topic is about Day 7 of the Advent of Code 2020 . Thanks to @egze, we have a private leaderboard: https://adventofcode.com/2020/le...
New
shritesh
This was way too easy after the last few days. Simple map, filter and count.
New
Aetherus
Don’t know why the regex ~r/[\W && [^\.]]/x does not work in Elixir. It works pretty well in Ruby. Anyway, here is my solution:
New
New
bjorng
This topic is about Day 5 of the Advent of Code 2021. We have a private leaderboard (shared with users of Erlang Forums ): https://adve...
New
bjorng
Note: This topic is to talk about Day 5 of the Advent of Code 2019. There is a private leaderboard for elixirforum members. You can join...
New
groovyda
Today’s challenge for me was about using reduce: defmodule Prob5 do def move([[h1 | rest] = _list1, list2]) do [rest, [h1 | list2]...
New
bjorng
This topic is about Day 9 of the Advent of Code 2021 . We have a private leaderboard (shared with users of Erlang Forums): https://adve...
New

Other popular topics Top

Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
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
Jim
As a follow up to my earlier question: I have the code compiling and running but not getting a successful login from the rest server. ...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
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
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
AstonJ
by Lance Halvorsen Elixir and Phoenix are generating tremendous excitement as an unbeatable platform for building modern web application...
460 27162 124
New

We're in Beta

About us Mission Statement