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