summaryrefslogtreecommitdiff
path: root/2020/src/bin/day_2.rs
diff options
context:
space:
mode:
Diffstat (limited to '2020/src/bin/day_2.rs')
-rw-r--r--2020/src/bin/day_2.rs104
1 files changed, 104 insertions, 0 deletions
diff --git a/2020/src/bin/day_2.rs b/2020/src/bin/day_2.rs
new file mode 100644
index 0000000..6c26647
--- /dev/null
+++ b/2020/src/bin/day_2.rs
@@ -0,0 +1,104 @@
+use bevy::prelude::*;
+use std::fs::File;
+use std::io::{BufRead, BufReader};
+
+fn main() {
+ App::build()
+ .add_resource(WindowDescriptor {
+ title: "Advent of Code".to_string(),
+ width: 1920,
+ height: 1080,
+ ..Default::default()
+ })
+ .add_resource(ClearColor(Color::rgb(0., 0., 0.)))
+ .add_startup_system(setup_camera.system())
+ .add_startup_system(read_input_file.system())
+ .add_stage("mark")
+ .add_system_to_stage("mark", validate_sled_passwords.system())
+ .add_system_to_stage("mark", validate_toboggan_passwords.system())
+ .add_stage("report")
+ .add_system_to_stage("report", count_valid_sled_passwords.system())
+ .add_system_to_stage("report", count_valid_toboggan_passwords.system())
+ //.add_plugins(DefaultPlugins)
+ .run();
+}
+
+fn setup_camera(mut commands: Commands) {
+ commands.spawn(Camera2dComponents::default());
+}
+
+struct PasswordRule {
+ num_1: usize,
+ num_2: usize,
+ c: char,
+}
+struct Password(String);
+struct SledPasswordValidation(bool);
+struct TobogganPasswordValidation(bool);
+
+fn read_input_file(mut commands: Commands) {
+ let f = File::open("./inputs/day_2.txt").expect("Failed to read file"); // TODO: Use the asset loading system to load this rather?
+ for line in BufReader::new(f).lines() {
+ let line = line.expect("Error reading file");
+ let line = line.trim();
+ let mut parts = line.split_whitespace();
+ let range = parts.next().expect("File was missing a range");
+ let chars = parts.next().expect("File was missing chars");
+ let password = parts.next().expect("File was missing a password");
+
+ let mut range_parts = range.split('-');
+
+ let rule = PasswordRule {
+ num_1: range_parts
+ .next()
+ .expect("Range did not have a minimum")
+ .parse()
+ .expect("Minimum was not a number"),
+ num_2: range_parts
+ .next()
+ .expect("Range did not have a maximum")
+ .parse()
+ .expect("Maximum was not a number"),
+ c: chars.chars().next().expect("File was missing chars"),
+ };
+ let password = Password(password.to_owned());
+
+ commands.spawn((rule, password));
+ }
+}
+
+fn validate_sled_passwords(
+ mut commands: Commands,
+ passwords: Query<Without<SledPasswordValidation, (Entity, &PasswordRule, &Password)>>,
+) {
+ for (entity, rule, password) in passwords.iter() {
+ let actual = password.0.chars().filter(|c| c == &rule.c).count();
+ let valid = actual >= rule.num_1 && actual <= rule.num_2;
+ commands.insert_one(entity, SledPasswordValidation(valid));
+ }
+}
+
+fn validate_toboggan_passwords(
+ mut commands: Commands,
+ passwords: Query<Without<TobogganPasswordValidation, (Entity, &PasswordRule, &Password)>>,
+) {
+ for (entity, rule, password) in passwords.iter() {
+ let actual_1 = password.0.chars().nth(rule.num_1 - 1);
+ let actual_2 = password.0.chars().nth(rule.num_2 - 1);
+ let actual_1_match = actual_1.map_or(false, |c| c == rule.c);
+ let actual_2_match = actual_2.map_or(false, |c| c == rule.c);
+
+ let valid = actual_1_match != actual_2_match;
+ commands.insert_one(entity, TobogganPasswordValidation(valid));
+ }
+}
+
+fn count_valid_sled_passwords(validation: Query<&SledPasswordValidation>) {
+ let count = validation.iter().filter(|v| v.0).count();
+ println!("Valid Sled Passwords: {}", count);
+}
+
+fn count_valid_toboggan_passwords(validation: Query<&TobogganPasswordValidation>) {
+ let count = validation.iter().filter(|v| v.0).count();
+ println!("Valid Toboggan Passwords: {}", count);
+}