AoC20/lib/day4/day4.ex

145 lines
2.9 KiB
Elixir

defmodule Day4 do
@example """
ecl:gry pid:860033327 eyr:2020 hcl:#fffffd
byr:1937 iyr:2017 cid:147 hgt:183cm
iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884
hcl:#cfa07d byr:1929
hcl:#ae17e1 iyr:2013
eyr:2024
ecl:brn pid:760753108 byr:1931
hgt:179cm
hcl:#cfa07d eyr:2025 pid:166559648
iyr:2011 ecl:brn hgt:59in
"""
def part1(example \\ false) do
count_all_valid(example, false)
end
def part2(example \\ false) do
count_all_valid(example, true)
end
def count_all_valid(example, check_values) do
if(example, do: @example, else: File.read!("lib/day4/input.txt"))
|> String.trim()
|> String.split("\n\n")
|> parse_input()
|> count_valid(check_values)
end
def parse_input(inputs) do
Enum.map(inputs, fn input ->
input
|> String.split()
|> Enum.reduce(%{}, fn pair, acc ->
[k, v] = String.split(pair, ":")
Map.put(acc, k, v)
end)
end)
end
@doc """
iex> Day4.validate_byr("2002")
true
iex> Day4.validate_byr("2003")
false
"""
def validate_byr(v) do
Regex.match?(~r/(^19[2-9][0-9]|200[0-2])$/, v)
end
@doc """
iex> Day4.validate_iyr("2010")
true
iex> Day4.validate_iyr("2009")
false
iex> Day4.validate_iyr("2021")
false
"""
def validate_iyr(v) do
Regex.match?(~r/^(201\d|2020)$/, v)
end
@doc """
iex> Day4.validate_eyr("2020")
true
iex> Day4.validate_eyr("2030")
true
iex> Day4.validate_eyr("2019")
false
iex> Day4.validate_eyr("2031")
false
"""
def validate_eyr(v) do
Regex.match?(~r/^(202\d|2030)$/, v)
end
@doc """
iex> Day4.validate_hgt("60in")
true
iex> Day4.validate_hgt("190cm")
true
iex> Day4.validate_hgt("190in")
false
iex> Day4.validate_hgt("190")
false
"""
def validate_hgt(v) do
Regex.match?(~r/^(1[5-8]\dcm|19[0-9]cm|59in|6\din|7[0-6]in)$/, v)
end
@doc """
iex> Day4.validate_hcl("#123abc")
true
iex> Day4.validate_hcl("#123ABC")
true
iex> Day4.validate_hcl("#123abz")
false
iex> Day4.validate_hcl("123abc")
false
"""
def validate_hcl(v) do
Regex.match?(~r/#[0-9a-f]{6}/i, v)
end
@doc """
iex> Day4.validate_ecl("brn")
true
iex> Day4.validate_ecl("wat")
false
"""
def validate_ecl(v) do
Regex.match?(~r/^(amb|b(lu|rn)|gr[yn]|hzl|oth)$/i, v)
end
@doc """
iex> Day4.validate_pid("000000001")
true
iex> Day4.validate_pid("0123456789")
false
"""
def validate_pid(v) do
Regex.match?(~r/^\d{9}$/, v)
end
@required_keys ["byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"]
def count_valid(data, check_values) do
Enum.count(data, fn passport ->
is_valid(passport, check_values)
end)
end
def is_valid(data, check_values) do
Enum.all?(@required_keys, fn k ->
Map.has_key?(data, k) &&
(!check_values ||
apply(Day4, String.to_atom("validate_#{k}"), [Map.fetch!(data, k)]))
end)
end
end