Advent of Code 2019 - Day 2

Note: This topic is to talk about Day 2 of the Advent of Code 2019 .

There is a private leaderboard for elixirforum members. You can join it by following this link and entering the following code:

39276-eeb74f9a

4 Likes

Here is my solution.

3 Likes

This is my take. It’s not super fast (takes about 2 sec on my machine for part 2), but does the job.

The most interesting part to me is instruction execution. I define the instruction mapping, and then have a generic exec function which interprets the instruction, fetching the correct amount of arguments based on the arity.

2 Likes

Nice solution based on Stream, and Function.info/1 I’ve never thought about before :slight_smile:

Here’s my version.
I did the input parsing in compile time so it was a bit faster. I found that in later puzzles the input might take more time to parse (it happened before).

1 Like

I’m learning Elixir, and didn’t know about Enum.find; I couldn’t figure out how to do an early return from inside for noun <- 0..100, verb <- 0..100, do: ..., so I picked a terrible way to do handle it: spawn 10k processes! (I finished reading the Concurrent Programming section of Programming Elixir last night.)

What’s interesting is that I read sasajuric’s solution, adapted it, and it seems to run slower (!) than what I have: 175769 microseconds for my part2, 682567 for theirs. Maybe it’s because of all the destructuring? Both solutions in one file.

1 Like

Here is mine: https://github.com/egze/aoc/blob/master/lib/aoc/y2019/d2.ex

Thanks @NobbZ for the boilerplate.

1 Like

I’m learning Elixir currently, and here is my mine: https://gitlab.com/KonradBorowski/advent_of_code_2019/blob/master/lib/day2.ex

I’m pretty sure it can be improved, but I quite like what I have here.

2 Likes

Finaly I found some time to do it. And a small typo took me half an hour to figure out the problem… I did for noun <- 0..99, verb <- 0..9 do … end

1 Like

That’s cool. Didn’t know about :array from Erlang.

2 Likes

My first guess would be that your solution is faster b/c you’re using spawn, which means you’re leveraging multiple cores. The Enum.find version is sequential.

How about we get a little private leaderboard for elixirforum going? :slight_smile: Because the public leader board is insane, people solve the challenges in minutes. wtf

2 Likes

Here’s mine solution: https://github.com/pozhega/AoC/blob/master/lib/aoc/Y2019/d2.ex

Mine: https://github.com/keathley/advent_of_code_2019/blob/master/day2.exs.

I did something similar to @sasajuric on part 2 using the pattern of generating all possible VMs as a stream and then using Enum.find to get the one that you want: https://github.com/keathley/advent_of_code_2019/blob/master/day2.exs#L66-L74.

That’s one of my favorite patterns in elixir.

2 Likes

Nice idea!

Feel free to join!

39276-eeb74f9a

2 Likes

Cool. Let’s make this the official one? :slight_smile:

@bjorng Could you include it in your posts please? Here is the link to join a private leaderboard: https://adventofcode.com/2019/leaderboard/private

2 Likes

Just had time to finish mine: aoc2019/lib/aoc2019/day2.ex at master · alvises/aoc2019 · GitHub

I had refactored it a bit after seeing @sasajuric solution, liked the comprehension + Enum.find. In my first version I did it with an excessively complicated Stream.iteration + Enum.reduce_while.

Guys, weren’t the first two days of the aoc2018 much easier? The first day was just a sum of nums if I remember correctly… I’m curious to see what they come out increasing the difficulty :exploding_head::scream::joy:

What the score is based on? (just joined, I hope is fine :slight_smile: )

It’s not all that difficult to also generate permutations lazily:

0..99
|> Stream.flat_map(fn noun -> Stream.map(0..99, &{noun, &1}) end)

My first version used this approach, but then I decided to switch to for b/c I think it communicates the intention a bit better.

4 Likes

We have n users in the group, so a star is up to n points worth.

The mth person that gets a star will receive n-m+1 points, as there are 2 stars per day, max score per day is 2 * n.

So full score for the first person, one point less for the second, etc.

2 Likes

Yeah for sure. I didn’t spend much time optimizing since its still a pretty low set of inputs and the algorithm is O(n).

My solution:

defmodule GravAssist do
  def calc([op, _, _ | rest], a \\ 12, b \\ 2) do
    hd(execute([op, a, b | rest]))
  end

  def execute(bytecode) when is_list(bytecode), do: execute(:array.from_list(bytecode))
  def execute(bytecode), do: eval(bytecode, 0)

  defp eval(bytecode, ic) do
    case :array.get(ic, bytecode) do
      99 -> :array.to_list(bytecode)
      op when op in 1..2 ->
        pos_a = :array.get(ic + 1, bytecode)
        pos_b = :array.get(ic + 2, bytecode)
        pos_r = :array.get(ic + 3, bytecode)

        result = compute(op, :array.get(pos_a, bytecode), :array.get(pos_b, bytecode))

        new_bc = :array.set(pos_r, result, bytecode)

        eval(new_bc, ic + 4)
      _ -> :error
    end
  end

  defp compute(1, a, b), do: a + b
  defp compute(2, a, b), do: a * b
end

data =
  IO.read(:line)
  |> String.split(",")
  |> Enum.map(&String.to_integer(String.trim(&1)))

IO.inspect(GravAssist.calc(data), label: :sol1)

for(a <- 0..99,
    b <- 0..99,
    19690720 == GravAssist.calc(data, a, b),
  do: {a, b})
|> IO.inspect(label: :sol2)
3 Likes