Anyone planning on solving Advent of Code 2020?

It was quite easy as I knew instantly how I wantet to solve it, and of course I’m getting more used to Erlang, so I don’t have to look up everything. I really like Erlang so far :slight_smile: I’m not experienced with Elixir, I just did some small hobby projects with Phoenix, and already it’s easier for me to read/write Erlang, just because of the time i spent with it.

I solved todays one by changing one instruction, test the code, then changing next instruction and test again, so quite brute force. No idea for some other solution.
Code’ll follow, wanna do some clean up first :slight_smile:

1 Like

Today was fun :slight_smile:


Day 9

Two brute forces in a row! Also, the first part was reminiscent of Day 1 :wink:

defmodule AdventOfCode.Y2020.Day9 do
  @moduledoc """
  Problem Link:
  use AdventOfCode.Helpers.InputReader, year: 2020, day: 9

  def run_1, do: input!() |> process() |> find_invalid()
  def run_2, do: input!() |> process() |> contiguous_list()

  def process(input), do:, "\n"), &String.to_integer/1)

  defp find_invalid(data) do
    {frame, [v | _] = next} = Enum.split(data, 25)
    (invalid?(v, && v) || find_invalid(tl(frame) ++ next)

  def invalid?(value, frame), do: Enum.empty?(Enum.filter(frame, &((value - &1) in frame)))

  defp contiguous_list(data), do: contiguous_list(find_invalid(data), data)

  defp contiguous_list(value, [h | rest]) do
    case contiguous_list(List.wrap(h), rest, value) do
      :bigger -> contiguous_list(value, rest)
      lst -> Enum.max(lst) + Enum.min(lst)

  def contiguous_list(data, [h | rest], value) do
    lst = [h | data]

    case Enum.sum(lst) do
      ^value -> lst
      n when n > value -> :bigger
      _ -> contiguous_list(lst, rest, value)


Rank 6931 for me today, but started 10 minutes late :smiley:


    Input = load_file("day9input.txt"),
    InvalidNumber = part1(Input),
    {InvalidNumber, part2(Input, InvalidNumber)}.

    find_invalid_number(Input, 1).

find_invalid_number(Input, Offset)->
    Preamble = lists:sublist(Input, Offset, 25),
    NumberToCheck = lists:nth(Offset + 25, Input),
    case is_valid(Preamble, NumberToCheck) of
        true -> find_invalid_number(Input, Offset + 1);
        false -> NumberToCheck

is_valid(Preamble, Number)->
    Sums = [X + Y || X <- Preamble, Y <- Preamble, X=/=Y],
    lists:member(Number, Sums).

part2(Input, InvalidNumber)->
    find_weakness(Input, 1, 1, InvalidNumber).

find_weakness(Input, Offset, Length, InvalidNumber)->
    Sublist = lists:sublist(Input, Offset, Length),
    SublistSum = lists:sum(Sublist),
    case SublistSum =:= InvalidNumber of
        true -> lists:nth(1, Sublist) + lists:last(Sublist);
        false -> 
            case (SublistSum > InvalidNumber) or (Offset + Length =:= length(Input)) of
                true -> find_weakness(Input, Offset + 1, 1, InvalidNumber);
                false -> find_weakness(Input, Offset, Length+1, InvalidNumber)

    {ok, Binary} = file:read_file(Filename),
    StringContent = unicode:characters_to_list(Binary),
    [ element(1, string:to_integer(Line)) || Line <- string:split(StringContent, "\n", all)].

Today’s one was a bit taxing for my to understand, just did number 1, I’ll do the next one tomorrow. (I do smell brute force there)

defmodule AdventOfCode.Y2020.Day10 do
  use AdventOfCode.Helpers.InputReader, year: 2020, day: 10

  def run_1, do: input!() |> process() |> rates() |> multiply_1_3()
  def run_2, do: {:not_implemented, 2}
  def run, do: {run_1(), run_2()}

  def process(input),
    do: input |> String.split("\n") |> |>

  defp rates(data) do
    my_rate = Enum.max(data) + 3

    Stream.unfold(0, fn
      n when n > my_rate ->

      n ->
        range = + 1)..(n + 3))
        jolt = MapSet.intersection(data, range) |> Enum.to_list()
        if Enum.empty?(jolt), do: diffs(my_rate, n), else: diffs(Enum.min(jolt), n)

  defp diffs(a, b) when a - b == 1, do: {{1, 0}, a}
  defp diffs(a, b) when a - b == 2, do: {{0, 0}, a}
  defp diffs(a, b) when a - b == 3, do: {{0, 1}, a}
  defp diffs(_, _), do: nil

  defp multiply_1_3(r),
    do: apply(&Kernel.*/2, Enum.reduce(r, [0, 0], fn {a, b}, [x, y] -> [x + a, y + b] end))


Good to here I wasn’t the only one with a problem today :smiley:
Part 1 was quite easy, after I noticed I still loaded last days input :roll_eyes:
For part 2 I thought bruteforce isn’t a good implementation here, but I didn’t come up with a solution until I had to start work, so I’ll try it later too.


    Input = lists:sort(load_file("day10input.txt")),
    {part1(Input), part2(Input)}.

    calc([0|Input], 0, 0).

calc([X,Y|T], Ones, Threes) ->
    case Y - X of
        1 -> calc([Y|T], Ones + 1, Threes);
        3 -> calc([Y|T], Ones, Threes + 1);
        _ -> calc([Y|T], Ones, Threes)
calc(_, Ones, Threes)->
    Ones * (Threes + 1).

part2(_)-> notimplemented.

    {ok, Binary} = file:read_file(Filename),
    StringContent = unicode:characters_to_list(Binary),
    [ element(1, string:to_integer(Line)) || Line <- string:split(StringContent, "\n", all)].
1 Like

You can’t brute force Part 2 for Day 10. There’s simply too many possibilities. Maybe try looking at a dynamic programming approach :wink:


Yes memoization what I ended up doing. Relevant parts are:

  defp count(data), do: count(data, %{(hd(data) + 3) => 1})
  defp count([], m), do: m[0]

  defp count([h | rst], m),
    do: count(rst, Map.put(m, h, Enum.sum(, &Map.get(m, h + &1, 0)))))

Where data is the parsed input date sorted in descending order. :slight_smile:

I don’t “get” Dynamic Programming. It’s been demonstrated in college, job interviews and puzzles, I struggle to intuitively understand it.

1 Like

Today’s one was nothing fancy, plain old pattern matching worked… at least for the first one, let’s see how the second one is like. Here’s my first solution:

1 Like

Day 13

I cheated on this one a little, I did not have the energy to implement Chinese Remainder Theorem in Elixir and since there wasn’t a good solution of it found in the Net (!), I translated an Erlang code into Elixir. And it’s fairly performant. The code is here…

1 Like

Just converted input data to Regex.

1 Like

I did the same. Ended up with a 27,000 char long regex :sweat_smile:


A snapshot of my regex…


Day 22 was super fun! I was thinking of waiting for the morning but the puzzle was begging me to do a quick mix solve 2020 22 and go for it!

defmodule AdventOfCode.Y2020.Day22 do
  use AdventOfCode.Helpers.InputReader, year: 2020, day: 22

  def run_1, do: input!() |> process() |> play() |> score()
  def run_2, do: input!() |> process() |> play_rec() |> score()
  def process(deal), do: decks(, "\n\n"), &String.split(&1, ":")))

  defp score(cards) do
    Enum.reduce(Enum.with_index(Enum.reverse(cards), 1), 0, fn {val, idx}, score ->
      score + val * idx

  defp decks([[_, human], [_, crab]]), do: {deck(human), deck(crab)}
  defp deck(p), do:, "\n", trim: true), &String.to_integer/1)

  defp play({[], crab}), do: crab
  defp play({human, []}), do: human
  defp play({[h | human], [c | crab]}) when h > c, do: play({human ++ [h, c], crab})
  defp play({[h | human], [c | crab]}), do: play({human, crab ++ [c, h]})

  defp play_rec(decks), do: elem(play_rec(decks, {[], []}), 1)
  defp play_rec({[], crab}, _), do: {2, crab}
  defp play_rec({human, []}, _), do: {1, human}

  defp play_rec({[h | hs] = human, [c | cs] = crab}, {humans, crabs}) do
    if human in humans || crab in crabs do
      {1, human}
      memo = {[human | humans], [crab | crabs]}

      if h <= length(hs) && c <= length(cs) do
        case play_rec({Enum.take(hs, h), Enum.take(cs, c)}, {[], []}) do
          {1, _} -> play_rec({hs ++ [h, c], cs}, memo)
          {2, _} -> play_rec({hs, cs ++ [c, h]}, memo)
        (h > c && play_rec({hs ++ [h, c], cs}, memo)) || play_rec({hs, cs ++ [c, h]}, memo)
1 Like

It took me a couple of reads to actually get all the rules of day 22. :sweat_smile:

Like, I didn’t get that you should only take the top N cards from each deck for each sub-game.

1 Like

Just realized, this thread has become pretty big lol

1 Like

It’s a great thread! Well done to all of you who participated :nerd_face:

And the AoC saga ends! This is the first time I scored all 50 stars and the experience has been great. I probably would’ve gotten bored and left like all other years had it not been all these discussions with you folks here. Thank you for this <3

See you in 2021 friends! Have an excellent time with family and friends y’all

1 Like

Oh, and here is my solution to Day 25, and it fits a Tweet.

1 Like

I golfed Day 9 in Ruby:

# Input is given with:
# cat day9.input | ruby 9.rb
(f=$< &:to_i).each_cons(26){|*n,b|n.combination(2).any?{|c|c.sum==b}||2.upto(f.size){|i|f.each_cons(i){|n|p b,n.minmax.sum if n.sum==b}}}
1 Like