summaryrefslogtreecommitdiff
path: root/2020/src/bin/day_9.rs
diff options
context:
space:
mode:
Diffstat (limited to '2020/src/bin/day_9.rs')
-rw-r--r--2020/src/bin/day_9.rs120
1 files changed, 120 insertions, 0 deletions
diff --git a/2020/src/bin/day_9.rs b/2020/src/bin/day_9.rs
new file mode 100644
index 0000000..b5a02e6
--- /dev/null
+++ b/2020/src/bin/day_9.rs
@@ -0,0 +1,120 @@
+use bevy::{app::AppExit, 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("add")
+ .add_system_to_stage("add", check_next_num.system())
+ .add_stage("remove")
+ .add_system_to_stage("remove", remove_oldest_line.system())
+ .add_stage("find_range")
+ .add_system_to_stage("find_range", find_contiguous_range.system())
+ .add_plugins(DefaultPlugins)
+ .run();
+}
+
+fn setup_camera(mut commands: Commands) {
+ commands.spawn(Camera2dComponents::default());
+}
+
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
+struct LineNum(usize);
+#[derive(Clone)]
+struct Num(i64);
+struct Active;
+struct Invalid;
+struct Done;
+
+fn read_input_file(mut commands: Commands) {
+ let f = File::open("./inputs/day_9.txt").unwrap();
+
+ for (line_num, line) in BufReader::new(f).lines().enumerate() {
+ let line = line.unwrap();
+ let line = line.trim();
+ let num = line.parse().unwrap();
+ commands.spawn((LineNum(line_num), Num(num)));
+ if line_num < 25 {
+ commands.with(Active);
+ }
+ }
+}
+
+fn check_next_num(
+ mut commands: Commands,
+ active: Query<With<Active, &Num>>,
+ next: Query<Without<Done, Without<Active, (Entity, &LineNum, &Num)>>>,
+) {
+ if let Some((min_entity, line, num)) = next.iter().min_by_key(|(_, line, _)| line.0) {
+ let mut is_sum = false;
+ for active_1 in active.iter() {
+ for active_2 in active.iter() {
+ is_sum = is_sum || (num.0 == active_1.0 + active_2.0)
+ }
+ }
+ commands.insert_one(min_entity, Active);
+
+ if !is_sum {
+ commands.insert_one(min_entity, Invalid);
+ println!(
+ "{} on line {} was not a sum of the previous lot!",
+ num.0, line.0
+ );
+ }
+ }
+}
+
+fn remove_oldest_line(
+ mut commands: Commands,
+ line_nums: Query<Without<Done, With<Active, (Entity, &LineNum)>>>,
+) {
+ if let Some((min_entity, _)) = line_nums.iter().min_by_key(|(_, line)| line.0) {
+ commands.remove_one::<Active>(min_entity);
+ commands.insert_one(min_entity, Done);
+ } else {
+ println!("All numbers cleared");
+ }
+}
+
+fn find_contiguous_range(
+ mut exit_events: ResMut<Events<AppExit>>,
+ line_nums: Query<(&LineNum, &Num)>,
+ invalid: Query<With<Invalid, &Num>>,
+) {
+ for invalid in invalid.iter() {
+ let mut nums: Vec<(LineNum, Num)> = line_nums
+ .iter()
+ .map(|(line, num)| (line.clone(), num.clone()))
+ .collect();
+
+ nums.sort_by_key(|(line, _num)| line.clone());
+ let nums: Vec<i64> = nums.into_iter().map(|(_line, num)| num.0).collect();
+
+ for min in 0..nums.len() {
+ for max in min + 2..nums.len() + 1 {
+ let sum: i64 = nums[min..max].iter().sum();
+ if sum == invalid.0 {
+ let min_in_range = nums[min..max].iter().min().unwrap();
+ let max_in_range = nums[min..max].iter().max().unwrap();
+ println!(
+ "Range found! {} + {} = {}",
+ min_in_range,
+ max_in_range,
+ min_in_range + max_in_range
+ );
+ }
+ }
+ }
+
+ exit_events.send(AppExit);
+ }
+}