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

bjorng
This topic is about Day 17 of the Advent of Code 2020 . Thanks to @egze, we have a private leaderboard: https://adventofcode.com/2020/l...
New
Aetherus
This topic is about Day 3 of the Advent of Code 2020 . Thanks to @egze, we have a private leaderboard: https://adventofcode.com/2020/le...
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
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
rugyoga
Fairly straightforward Dijkstra’s algorithm import AOC aoc 2023, 17 do def compute(input, candidates) do {{max_row, max_col}, ite...
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
Aetherus
Today’s problem is really tense. I don’t think I can do it without libgraph.
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
cblavier
Hi, there :wave: Today, I felt it was way more challenging! I went through part2 thanks to Agent based memoization (without memoization ...
New
coen.bakker
Since I started using Elixir, I have benefited greatly from being able to study various open-source projects. The codebase of LiveBook, i...
New

Other popular topics Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
yurko
Here are few pieces of (common) Linux knowledge that we use for reasonably small one server apps. We use Ubuntu but this should work for ...
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 42633 214
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
magnetic
Hey :wave:t3: Elixir community, I’ve been learning Elixir, and working on some side projects. My editor of choice is VSCode, and althoug...
New

We're in Beta

About us Mission Statement