Day 4 Parts 1 and 2
This commit is contained in:
parent
7483608460
commit
ace4184758
5 changed files with 1163 additions and 1 deletions
|
@ -2,7 +2,7 @@
|
|||
|
||||
My (attempted) solutions to [Advent of Code 2020](https://adventofcode.com/2020) in Elixir.
|
||||
|
||||
<img width="973" alt="image" src="https://user-images.githubusercontent.com/498229/100967992-db331000-3573-11eb-8a48-aa73d01f1a53.png">
|
||||
<img width="970" alt="image" src="https://user-images.githubusercontent.com/498229/101128533-397af400-3643-11eb-8555-c78113d57aa5.png">
|
||||
|
||||
## Strategy
|
||||
|
||||
|
|
47
day4/README
Normal file
47
day4/README
Normal file
|
@ -0,0 +1,47 @@
|
|||
Day 4 Notes
|
||||
|
||||
+--------+
|
||||
| Part 1 |
|
||||
+--------+
|
||||
|
||||
$ elixir day4part1.exs
|
||||
210
|
||||
|
||||
Thoughts:
|
||||
|
||||
Parse each passport into a list of key-value pairs, and extract the keys.
|
||||
Not sure if there will be extra keys, so store required keys in a Mapset, which means I can use
|
||||
MapSet.subset to make sure all the required keys are present.
|
||||
Embedded enums are kind of ugly.
|
||||
Nice usage of Enum.into, IMO 🍠.
|
||||
|
||||
+--------+
|
||||
| Part 2 |
|
||||
+--------+
|
||||
|
||||
$ elixir day4part2.exs
|
||||
131
|
||||
|
||||
Thoughts:
|
||||
|
||||
Need the values too now, so refactor a bit to preserve them, storing each passport at a map.
|
||||
Can still use part 1 logic to filter out passports that have missing keys.
|
||||
- just pull out the keys and convert to a MapSet as before.
|
||||
Delete the cid key if present, since needs to be ignored.
|
||||
|
||||
Validation code:
|
||||
Mostly just implementing the spec.
|
||||
Use regex for fiddly requirements.
|
||||
hgt was a bit annoying, really wanted to fail-fast if the regex failed to match the units,
|
||||
maybe will come back to that and think of a nicer way later.
|
||||
For valid?: Is there a nicer way to call a bunch of functions with the same argument and
|
||||
aggregate their results? 🤔
|
||||
|
||||
|
||||
+------------------+
|
||||
| Overall Thoughts |
|
||||
+------------------+
|
||||
|
||||
Starting to take me longer now, about an hour for this one.
|
||||
Ended up not using Enum.reduce here, but every time I do use it I forget the order of the
|
||||
acc/item pair in the reducer function... 😩
|
19
day4/day4part1.exs
Normal file
19
day4/day4part1.exs
Normal file
|
@ -0,0 +1,19 @@
|
|||
defmodule Day4Part1 do
|
||||
@required MapSet.new(["byr", "ecl", "eyr", "hcl", "hgt", "iyr", "pid"])
|
||||
|
||||
def run do
|
||||
File.read!("input")
|
||||
|> String.trim()
|
||||
|> String.split("\n\n")
|
||||
|> Enum.map(fn passport ->
|
||||
passport
|
||||
|> String.split([" ", "\n"])
|
||||
|> Enum.map(&String.split(&1, ":"))
|
||||
|> Enum.into(MapSet.new(), fn [k, _] -> k end)
|
||||
end)
|
||||
|> Enum.count(&MapSet.subset?(@required, &1))
|
||||
|> IO.puts()
|
||||
end
|
||||
end
|
||||
|
||||
Day4Part1.run()
|
67
day4/day4part2.exs
Normal file
67
day4/day4part2.exs
Normal file
|
@ -0,0 +1,67 @@
|
|||
defmodule Day4Part2 do
|
||||
@required MapSet.new(["byr", "ecl", "eyr", "hcl", "hgt", "iyr", "pid"])
|
||||
|
||||
def run do
|
||||
File.read!("input")
|
||||
|> String.trim()
|
||||
|> String.split("\n\n")
|
||||
|> Enum.map(fn passport ->
|
||||
passport
|
||||
|> String.split([" ", "\n"])
|
||||
|> Enum.map(&String.split(&1, ":"))
|
||||
|> Map.new(fn [k, v] -> {k, v} end)
|
||||
end)
|
||||
|> Enum.map(&Map.delete(&1, "cid"))
|
||||
|> Enum.filter(&MapSet.subset?(@required, &1 |> Map.keys() |> MapSet.new()))
|
||||
|> Enum.count(&valid?/1)
|
||||
|> IO.puts()
|
||||
end
|
||||
|
||||
def valid?(passport) do
|
||||
byr?(passport) && iyr?(passport) && eyr?(passport) && hgt?(passport) && hcl?(passport) &&
|
||||
ecl?(passport) && pid?(passport)
|
||||
end
|
||||
|
||||
def byr?(%{"byr" => byr}) do
|
||||
date = String.to_integer(byr)
|
||||
1920 <= date && date <= 2002
|
||||
end
|
||||
|
||||
def iyr?(%{"iyr" => iyr}) do
|
||||
date = String.to_integer(iyr)
|
||||
2010 <= date && date <= 2020
|
||||
end
|
||||
|
||||
def eyr?(%{"eyr" => eyr}) do
|
||||
date = String.to_integer(eyr)
|
||||
2020 <= date && date <= 2030
|
||||
end
|
||||
|
||||
def hgt?(%{"hgt" => hgt}) do
|
||||
{hgt, unit} =
|
||||
case Regex.run(~r/\A(\d+)([^\d]+)\z/, hgt, capture: :all_but_first) do
|
||||
[hgt, unit] -> {String.to_integer(hgt), unit}
|
||||
nil -> {0, nil}
|
||||
end
|
||||
|
||||
case unit do
|
||||
"cm" -> 150 <= hgt && hgt <= 193
|
||||
"in" -> 59 <= hgt && hgt <= 76
|
||||
nil -> false
|
||||
end
|
||||
end
|
||||
|
||||
def hcl?(%{"hcl" => hcl}) do
|
||||
Regex.match?(~r/\A#[0-9a-f]{6}\z/, hcl)
|
||||
end
|
||||
|
||||
def ecl?(%{"ecl" => ecl}) do
|
||||
ecl in ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"]
|
||||
end
|
||||
|
||||
def pid?(%{"pid" => pid}) do
|
||||
Regex.match?(~r/\A\d{9}\z/, pid)
|
||||
end
|
||||
end
|
||||
|
||||
Day4Part2.run()
|
1029
day4/input
Normal file
1029
day4/input
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue