Advent of Code 2019 - Day 4

Note: This topic is to talk about Day 4 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

2 Likes

Here is my solution.

1 Like

Very unhygienic code, especially for part 2.

Part 1

359999..799999
|> Stream.map(&Integer.to_string/1)
|> Stream.map(&String.graphemes/1)
|> Stream.reject(fn graphemes -> graphemes |> Stream.chunk_every(2, 1, :discard) |> Enum.any?(fn [a, b] -> a > b end) end)
|> Stream.reject(fn graphemes -> graphemes |> Stream.chunk_every(2, 1, :discard) |> Enum.all?(fn [a, b] -> a != b end) end)
|> Enum.count()
|> IO.inspect()

Part 2

359999..799999
|> Stream.map(&Integer.to_string/1)
|> Stream.map(&String.graphemes/1)
|> Stream.reject(fn graphemes -> graphemes |> Stream.chunk_every(2, 1, :discard) |> Enum.any?(fn [a, b] -> a > b end) end)
|> Stream.map(fn graphemes -> [:x] ++ graphemes ++ [:x] end)  # tricky padding
|> Stream.filter(fn graphemes -> graphemes |> Stream.chunk_every(4, 1, :discard) |> Enum.any?(fn
     [a, b, b, c] when a != b and b != c -> true
     _ -> false
   end) end)
|> Enum.count()
|> IO.inspect()
4 Likes

For AoC, I pick a language I want to get to know better. This year it’s Elixir. I came from the Ruby world (by way of a short detour through Crystal-land). I have already launched a Phoenix-based CMS (closed source for now, unfortunately), but I am still far from fluent.

So I’m sure my solutions won’t be ideal, but I thought I’d post them anyway, since i have enjoyed reading through the various solutions posted here for the first 3 days.

Day 4 Solution

As I was writing this, Aetherus’s post appeared and I realized I forgot about the :discard option on chunk_every… oh well.

6 Likes

Glad to have helped :slightly_smiling_face:

1 Like

Here is my solution. I feel it can still be improved.

Edit:
I simplified it after reading @yuchunc 's nice solution. This is always the most enjoyable part during the AOC sessions, because I can learn so much from others here. Thank you guys!

3 Likes

I used quite a few pattern matchiing clauses for the strict double checking

3 Likes

One of the first languages I ever learned was Perl (now called Raku?!?), so I tend to reach for regexes a lot, perhaps more than I should. Maybe regexes are a no-no in Elixir world, I don’t know.

This regex needed backreferences, so I was afraid it might turn out super slow, but in this case, the strings involved are so short that it didn’t matter.

  @doc """
      iex> Day4.PasswordFinder2.remove_long_repeats("112233")
      "112233"
      iex> Day4.PasswordFinder2.remove_long_repeats("123444")
      "123"
      iex> Day4.PasswordFinder2.remove_long_repeats("111122")
      "22"
  """
  def remove_long_repeats(str) do
    String.replace(str, ~r/(\d)\1{2,}/, "")
  end
2 Likes

My Day4 Solution

Any feedbacks are welcome! :slight_smile:

4 Likes

How to prevent someone cheating by using other languages? I personally used Ruby in Day 2.

Your part 2 check is really nice, I wish I’d thought of that.

One small thing I noticed, things like:

  defp increment?([d1 | [d2 | _]]) when d1 > d2, do: false

can be:

  defp increment?([d1, d2 | _]) when d1 > d2, do: false
1 Like

Regexes are totally fine in Elixir IMHO. I’ve been using Ruby a lot so I’m totally biased though :nerd_face:

Day 2 definitely makes more sense with variable mutation.
I wouldn’t call it cheating, just using right tools for the job. :hammer_and_wrench:

My solution.

2 Likes

This works. Somehow. The [c] != d is weird, but it works, so whatever.

1 Like

Yeah, the Raku thing is confusing. There used to be two programming languages.

  • One called Perl. The more popular one. This one is still called Perl.
  • One called Perl 6. This one changed its name to Raku, as calling it Perl was confusing - it was a completely different language.

My solution is here.
I decided I don’t want to brute-force this, so I made a function which computes the next valid password, on top of which I can build a stream of valid passwords.

5 Likes

Today’s was a lot simpler than yesterday’s. I know my haspairs does more work than necessary, but I’m out of time to clean it up.

Interestingly enough, using my to_pairs function is a lot faster than using Enum.chunk_every(digits, 2, 1, :discard) – 172ms for part 1 instead of 639ms.

1 Like

Here is my solution : https://github.com/cblavier/advent/tree/master/lib/2019/day4 :slight_smile:

I only half brute forced the problem by generating a stream of semi-valid numbers (with only increasing digits) and filtered them afterward

I am just starting my elixir jouney, here is my ugly implementation:

Day 4

2 Likes