2025-05-30 07:59:06 -05:00
|
|
|
use std::{
|
|
|
|
|
collections::{HashMap, HashSet},
|
|
|
|
|
env,
|
|
|
|
|
error::Error,
|
|
|
|
|
fs::File,
|
|
|
|
|
io::{BufReader, prelude::*},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
fn main() -> Result<(), Box<dyn Error>> {
|
|
|
|
|
// Handle command input
|
|
|
|
|
let args: Vec<String> = env::args().collect();
|
|
|
|
|
if args.len() != 2 {
|
|
|
|
|
panic!(
|
|
|
|
|
"{} must be run with a single argument of files name!",
|
|
|
|
|
&args[0]
|
|
|
|
|
)
|
|
|
|
|
}
|
2025-05-30 08:07:15 -05:00
|
|
|
let input_file = &args[1];
|
2025-05-30 07:59:06 -05:00
|
|
|
|
2025-05-30 08:07:15 -05:00
|
|
|
let buffer = BufReader::new(File::open(input_file)?);
|
2025-05-30 07:59:06 -05:00
|
|
|
|
|
|
|
|
let mut rules_stage = true;
|
|
|
|
|
let mut page_rules: HashMap<i64, HashSet<i64>> = HashMap::new();
|
|
|
|
|
let mut valid_page_updates: Vec<Vec<i64>> = Vec::new();
|
2025-05-30 08:07:15 -05:00
|
|
|
let mut invalid_page_updates: Vec<Vec<i64>> = Vec::new();
|
2025-05-30 07:59:06 -05:00
|
|
|
for line in buffer.lines() {
|
|
|
|
|
let line = line?;
|
|
|
|
|
if rules_stage {
|
|
|
|
|
// Stage 1: load rules
|
2025-05-30 08:04:33 -05:00
|
|
|
// Load rules that look like 1|1
|
2025-05-30 07:59:06 -05:00
|
|
|
if line.is_empty() {
|
|
|
|
|
// Blank line means end of rules
|
|
|
|
|
rules_stage = false;
|
2025-05-30 08:07:15 -05:00
|
|
|
// println!("Page Rules: {:?}", page_rules);
|
2025-05-30 07:59:06 -05:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
let split_line: Vec<&str> = line.split("|").collect();
|
|
|
|
|
if split_line.len() != 2 {
|
|
|
|
|
Err(format!("Invalid input in rules: {}", line))?;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// parse rule line and insert into out rule sets
|
|
|
|
|
let key = split_line[0].parse::<i64>()?;
|
|
|
|
|
let value = split_line[1].parse::<i64>()?;
|
|
|
|
|
match page_rules.get_mut(&key) {
|
2025-05-30 08:07:15 -05:00
|
|
|
Some(rule_set) => {
|
|
|
|
|
rule_set.insert(value);
|
2025-05-30 07:59:06 -05:00
|
|
|
}
|
|
|
|
|
None => {
|
|
|
|
|
let mut new_rule_set = HashSet::new();
|
|
|
|
|
new_rule_set.insert(value);
|
|
|
|
|
page_rules.insert(key, new_rule_set);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Stage 2: check updates
|
2025-05-30 08:07:15 -05:00
|
|
|
let page_update: Vec<i64> = line
|
2025-05-30 07:59:06 -05:00
|
|
|
.split(",")
|
|
|
|
|
.map(|v| v.parse::<_>())
|
|
|
|
|
.collect::<Result<_, _>>()?;
|
|
|
|
|
|
|
|
|
|
let mut prev_pages: HashSet<i64> = HashSet::new();
|
|
|
|
|
let mut is_valid = true;
|
2025-05-30 08:07:15 -05:00
|
|
|
for page_num in page_update.iter() {
|
2025-05-30 07:59:06 -05:00
|
|
|
if let Some(rule_set) = page_rules.get(page_num) {
|
|
|
|
|
if !prev_pages.is_disjoint(rule_set) {
|
|
|
|
|
is_valid = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
prev_pages.insert(*page_num);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if is_valid {
|
2025-05-30 08:07:15 -05:00
|
|
|
valid_page_updates.push(page_update);
|
|
|
|
|
} else {
|
|
|
|
|
invalid_page_updates.push(page_update);
|
2025-05-30 07:59:06 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut accumulator = 0;
|
|
|
|
|
for update in valid_page_updates {
|
|
|
|
|
let middle_page = update[update.len() / 2];
|
|
|
|
|
accumulator += middle_page;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
println!("Sum of middle pages from valid updates: {}", accumulator);
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|