1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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);
}
}
|