mirror of
https://github.com/chylex/Advent-of-Code.git
synced 2025-06-05 06:34:03 +02:00
Add 2020 - Day 4 - Part 1
This commit is contained in:
parent
63f86596b2
commit
aaec7168fb
18
.idea/runConfigurations/2020___Day_04.xml
Normal file
18
.idea/runConfigurations/2020___Day_04.xml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="2020 - Day 04" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
|
||||||
|
<option name="command" value="run --bin 04" />
|
||||||
|
<option name="workingDirectory" value="file://$PROJECT_DIR$/2020/04" />
|
||||||
|
<option name="channel" value="DEFAULT" />
|
||||||
|
<option name="requiredFeatures" value="true" />
|
||||||
|
<option name="allFeatures" value="false" />
|
||||||
|
<option name="emulateTerminal" value="false" />
|
||||||
|
<option name="withSudo" value="false" />
|
||||||
|
<option name="backtrace" value="SHORT" />
|
||||||
|
<envs />
|
||||||
|
<option name="isRedirectInput" value="false" />
|
||||||
|
<option name="redirectInputPath" value="" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
1146
2020/04/input/1.txt
Normal file
1146
2020/04/input/1.txt
Normal file
File diff suppressed because it is too large
Load Diff
101
2020/04/main.rs
Normal file
101
2020/04/main.rs
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
|
use crate::utils::GenericError;
|
||||||
|
|
||||||
|
#[path = "../utils/mod.rs"]
|
||||||
|
mod utils;
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let lines = utils::read_input_lines()?;
|
||||||
|
let passports = load_passports(&lines)?;
|
||||||
|
|
||||||
|
let valid_passports = passports.iter().filter(|p| p.is_valid_or_from_north_pole()).count();
|
||||||
|
println!("Valid passports: {}", valid_passports);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_passports(lines: &Vec<String>) -> Result<Vec<Passport>, GenericError> {
|
||||||
|
let mut passports = Vec::new();
|
||||||
|
let mut passport = Passport::new();
|
||||||
|
|
||||||
|
for line in lines {
|
||||||
|
if line.is_empty() {
|
||||||
|
passports.push(passport);
|
||||||
|
passport = Passport::new();
|
||||||
|
} else {
|
||||||
|
passport.load_fields_from_line(line.as_str())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
passports.push(passport);
|
||||||
|
Ok(passports)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Hash, Debug, Copy, Clone)]
|
||||||
|
enum PassportField {
|
||||||
|
BirthYear,
|
||||||
|
IssueYear,
|
||||||
|
ExpirationYear,
|
||||||
|
Height,
|
||||||
|
HairColor,
|
||||||
|
EyeColor,
|
||||||
|
PassportId,
|
||||||
|
CountryId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PassportField {
|
||||||
|
fn from(s: &str) -> Option<PassportField> {
|
||||||
|
match s {
|
||||||
|
"byr" => Some(PassportField::BirthYear),
|
||||||
|
"iyr" => Some(PassportField::IssueYear),
|
||||||
|
"eyr" => Some(PassportField::ExpirationYear),
|
||||||
|
"hgt" => Some(PassportField::Height),
|
||||||
|
"hcl" => Some(PassportField::HairColor),
|
||||||
|
"ecl" => Some(PassportField::EyeColor),
|
||||||
|
"pid" => Some(PassportField::PassportId),
|
||||||
|
"cid" => Some(PassportField::CountryId),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Passport {
|
||||||
|
fields: HashMap<PassportField, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref REQUIRED_FIELDS: HashSet<PassportField> = HashSet::from([
|
||||||
|
PassportField::BirthYear,
|
||||||
|
PassportField::IssueYear,
|
||||||
|
PassportField::ExpirationYear,
|
||||||
|
PassportField::Height,
|
||||||
|
PassportField::HairColor,
|
||||||
|
PassportField::EyeColor,
|
||||||
|
PassportField::PassportId
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Passport {
|
||||||
|
fn new() -> Passport {
|
||||||
|
Passport { fields: HashMap::new() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_fields_from_line(&mut self, line: &str) -> Result<(), GenericError> {
|
||||||
|
for field_entry in line.split(' ') {
|
||||||
|
let (field_name, field_value) = field_entry.split_once(':').ok_or_else(|| GenericError::new("Passport entry is missing a colon."))?;
|
||||||
|
let field = PassportField::from(field_name).ok_or_else(|| GenericError::new(format!("Passport field is invalid: {}", field_name)))?;
|
||||||
|
self.fields.insert(field, field_value.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_valid_or_from_north_pole(&self) -> bool {
|
||||||
|
let fields = &self.fields.keys().map(|f| *f).collect::<HashSet<PassportField>>();
|
||||||
|
return fields.is_superset(&REQUIRED_FIELDS);
|
||||||
|
}
|
||||||
|
}
|
9
2020/Cargo.lock
generated
9
2020/Cargo.lock
generated
@ -5,3 +5,12 @@ version = 3
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "chylex-aoc-2020"
|
name = "chylex-aoc-2020"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
@ -3,6 +3,9 @@ name = "chylex-aoc-2020"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
lazy_static = "1.4.0"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "01"
|
name = "01"
|
||||||
path = "01/main.rs"
|
path = "01/main.rs"
|
||||||
@ -14,3 +17,7 @@ path = "02/main.rs"
|
|||||||
[[bin]]
|
[[bin]]
|
||||||
name = "03"
|
name = "03"
|
||||||
path = "03/main.rs"
|
path = "03/main.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "04"
|
||||||
|
path = "04/main.rs"
|
||||||
|
@ -10,6 +10,7 @@ pub fn read_input_lines() -> Result<Vec<String>, io::Error> {
|
|||||||
return BufReader::new(file).lines().collect();
|
return BufReader::new(file).lines().collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn parse_input_lines<T : FromStr>() -> Result<Vec<T>, Box<dyn Error>> where <T as FromStr>::Err : Into<Box<dyn Error>> {
|
pub fn parse_input_lines<T : FromStr>() -> Result<Vec<T>, Box<dyn Error>> where <T as FromStr>::Err : Into<Box<dyn Error>> {
|
||||||
return read_input_lines()?.iter().map(|line| line.parse::<T>()).collect::<Result<Vec<T>, T::Err>>().map_err(Into::into);
|
return read_input_lines()?.iter().map(|line| line.parse::<T>()).collect::<Result<Vec<T>, T::Err>>().map_err(Into::into);
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ The versions should not matter, but I used Visual Studio 2019 with `MSVC v142 (1
|
|||||||
| 2020 | 01 | Rust |
|
| 2020 | 01 | Rust |
|
||||||
| 2020 | 02 | Rust |
|
| 2020 | 02 | Rust |
|
||||||
| 2020 | 03 | Rust |
|
| 2020 | 03 | Rust |
|
||||||
|
| 2020 | 04 | Rust |
|
||||||
| 2021 | 01 | Kotlin |
|
| 2021 | 01 | Kotlin |
|
||||||
| 2021 | 02 | Kotlin |
|
| 2021 | 02 | Kotlin |
|
||||||
| 2021 | 03 | Kotlin |
|
| 2021 | 03 | Kotlin |
|
||||||
|
Loading…
Reference in New Issue
Block a user