Aetherus

Aetherus

This topic is about Day 4 of the Advent of Code 2020 .

Thanks to @egze, we have a private leaderboard:
https://adventofcode.com/2020/leaderboard/private/view/39276

The join code is:
39276-eeb74f9a

Showing Posts 1 to 10

Aetherus

Aetherus OP

A straightforward solution for Part 2:

#!/usr/bin/env elixir

defmodule Validator do

  def valid?({"byr", value}) do
    value
    |> String.to_integer()
    |> Kernel.in(1920..2002)
  end

  def valid?({"iyr", value}) do
    value
    |> String.to_integer()
    |> Kernel.in(2010..2020)
  end

  def valid?({"eyr", value}) do
    value
    |> String.to_integer()
    |> Kernel.in(2020..2030)
  end

  def valid?({"hgt", value}) do
    case String.split(value, ~r/(?<=\d)(?=[a-z])/) do
      [num, unit] ->
        valid_height?(String.to_integer(num), unit)
      _ -> false
    end
  end

  def valid?({"hcl", value}) do
    value =~ ~r/^\#[0-9a-f]{6}$/
  end

  def valid?({"ecl", value}) do
    value in ~w[amb blu brn gry grn hzl oth]
  end

  def valid?({"pid", value}) do
    value =~ ~r/^\d{9}$/
  end

  def valid?({_key, _value}) do
    true
  end

  defp valid_height?(num, "cm"), do: num in (150..193)
  defp valid_height?(num, "in"), do: num in (59..76)
  defp valid_height?(_, _), do: false
end

required_fields = ~w[
  byr
  iyr
  eyr
  hgt
  hcl
  ecl
  pid
]

to_passport = fn(fields)->
  fields
  |> Stream.map(&String.split(&1, ":"))
  |> Stream.map(&List.to_tuple/1)
  |> Map.new()
end

valid? = fn(passport)->
  has_all_required_keys? = Enum.all?(required_fields, &Map.has_key?(passport, &1))
  all_values_are_valid? = Enum.all?(passport, &Validator.valid?/1)
  has_all_required_keys? and all_values_are_valid?
end

"day4.txt"
|> File.read!()
|> String.split("\n\n")
|> Stream.map(&String.split/1)
|> Enum.map(to_passport)
|> Enum.count(valid?)
|> IO.puts()
aaronnamba

aaronnamba

I see some pattern matching in there, but you could do a lot more of it. Also, Integer.parse is your friend on the height field.

aaronnamba

aaronnamba

Observations:

  • Woof, data validation… kinda tedious. A lot like work, and I do AoC to take a break from work…
  • I anticipated having to look up things, so I parsed into a map, but that ended up being entirely unnecessary.
  • Thank goodness for pattern matching.

Excerpt:

  def all_fields_valid?(record) do
    Enum.all?(record, fn {field, value} -> valid?(field, value) end)
  end

  def valid?(field, year) when field in ["byr", "eyr", "iyr"] and is_binary(year),
    do: valid?(field, String.to_integer(year))

  def valid?("byr", year) when year in 1920..2002, do: true
  def valid?("iyr", year) when year in 2010..2020, do: true
  def valid?("eyr", year) when year in 2020..2030, do: true
  def valid?("hgt", {cm, "cm"}) when cm in 150..193, do: true
  def valid?("hgt", {inch, "in"}) when inch in 59..76, do: true
  def valid?("hgt", {_, _}), do: false
  def valid?("hgt", height), do: valid?("hgt", Integer.parse(height))

  def valid?("hcl", color), do: Regex.match?(~r/^#[0-9a-f]{6}$/, color)

  def valid?("ecl", color) when color in ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"],
    do: true

  def valid?("pid", pid), do: Regex.match?(~r/^[0-9]{9}$/, pid)
  def valid?("cid", _), do: true
  def valid?(_, _), do: false
Aetherus

Aetherus OP

Yea, pattern matching provides great help in validation. That’s one of the reasons why FP languages rock.

Damirados

Damirados

As this is typical day to day work I just imported Ecto in my solution

Aetherus

Aetherus OP

As this is typical day to day work …

True. This year’s quizzes are not so interesting.

Damirados

Damirados

At least properly collecting passports via Stream.transform was fun learning experience. I’m using AoC to properly dig into that module.

Aetherus

Aetherus OP

Seems like you are seeking fun in a quite boring quiz. I did so too, in Day 1. See my last post in Day 1’s thread.

adamu

adamu

Nothing much to add.

I missed a trick not overloading the validator function for each case, so that you can just validate the map with Enum.all - that’s pretty nice.

I forgot about the =~ operator, and I used to work with Perl!

Aetherus

Aetherus OP

I’m not familiar with Perl, but I coded and am still coding a lot in Ruby. Is the =~ operator an Perl invention?

Where Next? Top

Trending in Challenges Top

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
juhalehtonen
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews