This commit is contained in:
2024-12-05 22:08:53 +01:00
parent 48c6f5db00
commit 14a90754c2
7 changed files with 227 additions and 0 deletions

60
day-05-rust/src/common.rs Normal file
View File

@@ -0,0 +1,60 @@
use std::collections::HashMap;
use std::io::{Bytes, Read};
use std::iter::Peekable;
use crate::common;
pub type Number = i32;
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Rule {
pub first: Number,
pub second: Number,
}
pub fn read_rules<R: Read>(mut input: &mut Peekable<Bytes<R>>) -> HashMap<Number, Vec<Rule>> {
let mut rules_by_number = HashMap::<Number, Vec<Rule>>::new();
while let Some(Ok(ch)) = input.peek() {
if ch == &b'\n' {
input.next();
break;
}
let first = common::read_number(&mut input);
input.next();
let second = common::read_number(&mut input);
input.next();
let rule = Rule { first, second };
rules_by_number
.entry(rule.first)
.or_default()
.push(rule.clone());
rules_by_number.entry(rule.second).or_default().push(rule);
}
rules_by_number
}
pub fn read_number_list<R: Read>(mut input: &mut Peekable<Bytes<R>>) -> Vec<Number> {
let mut numbers = Vec::<Number>::new();
while let Some(Ok(ch)) = input.peek() {
if ch == &b'\n' {
break;
} else if ch == &b',' {
input.next();
continue;
}
let number = common::read_number(&mut input);
numbers.push(number);
}
numbers
}
pub fn read_number<R: Read>(input: &mut Peekable<Bytes<R>>) -> Number {
let mut number: Number = 0;
while let Some(Ok(b'0'..=b'9')) = input.peek() {
number *= 10;
number += (input.next().unwrap().unwrap() - b'0') as Number;
}
number
}

22
day-05-rust/src/main.rs Normal file
View File

@@ -0,0 +1,22 @@
mod task1;
mod task2;
mod common;
fn main() {
let args = std::env::args().collect::<Vec<String>>();
if args.len() != 3 {
eprintln!("Usage: {} <1|2> <input file>", args[0]);
std::process::exit(1);
}
match args[1].as_str() {
"1" => {
task1::run(std::fs::File::open(&args[2]).expect("File not found"));
}
"2" => {
task2::run(std::fs::File::open(&args[2]).expect("File not found"));
}
_ => eprintln!("Unknown task: {}", args[2]),
}
}

45
day-05-rust/src/task1.rs Normal file
View File

@@ -0,0 +1,45 @@
use crate::common::{read_number_list, read_rules, Number};
use std::collections::HashSet;
use std::io::Read;
use std::ops::Rem;
pub fn run<R: Read>(read: R) {
let mut input = read.bytes().peekable();
let rules_by_number = read_rules(&mut input);
let mut result: Number = 0;
while let Some(Ok(ch)) = input.peek() {
if ch == &b'\n' {
input.next();
continue;
}
let numbers = read_number_list(&mut input);
let rules = numbers
.iter()
.flat_map(|number| rules_by_number.get(number))
.flatten()
.filter(|rule| numbers.contains(&rule.first) && numbers.contains(&rule.second))
.collect::<HashSet<_>>();
if rules.iter().all(|rule| {
numbers
.iter()
.position(|number| *number == rule.first)
.zip(numbers.iter().position(|number| *number == rule.second))
.map(|(first_index, second_index)| first_index < second_index)
.unwrap_or(false)
}) {
if numbers.len().rem(2) == 1 {
result += numbers[numbers.len() / 2];
} else {
eprintln!("Length of numbers is not odd!")
}
}
}
println!("Result {}", result);
}

86
day-05-rust/src/task2.rs Normal file
View File

@@ -0,0 +1,86 @@
use crate::common::{read_number_list, read_rules, Number, Rule};
use std::collections::{HashMap, HashSet};
use std::io::Read;
use std::ops::{Not, Rem};
#[derive(Debug, Default, Clone)]
struct Edges {
incoming: HashSet<Rule>,
outgoing: HashSet<Rule>,
}
pub fn run<R: Read>(read: R) {
let mut input = read.bytes().peekable();
let rules_by_number = read_rules(&mut input);
let mut result: Number = 0;
while let Some(Ok(ch)) = input.peek() {
if ch == &b'\n' {
input.next();
continue;
}
let numbers = read_number_list(&mut input);
let rules = numbers
.iter()
.flat_map(|number| rules_by_number.get(number))
.flatten()
.filter(|rule| numbers.contains(&rule.first) && numbers.contains(&rule.second))
.collect::<HashSet<_>>();
if !rules.iter().all(|rule| {
numbers
.iter()
.position(|number| *number == rule.first)
.zip(numbers.iter().position(|number| *number == rule.second))
.map(|(first_index, second_index)| first_index < second_index)
.unwrap_or(false)
}) {
let mut edges_by_nodes = HashMap::<Number, Edges>::new();
rules.iter().for_each(|rule| {
edges_by_nodes
.entry(rule.first)
.or_default()
.outgoing
.insert((*rule).clone());
edges_by_nodes
.entry(rule.second)
.or_default()
.incoming
.insert((*rule).clone());
});
let mut sorted_numbers = Vec::<Number>::with_capacity(numbers.len());
while edges_by_nodes.is_empty().not() {
if let Some(start_node) = edges_by_nodes
.iter()
.filter(|(_node, edges)| edges.incoming.is_empty())
.next()
.map(|(node, _edges)| *node)
{
sorted_numbers.push(start_node);
let edges = edges_by_nodes.remove(&start_node).unwrap();
for outgoing in edges.outgoing {
if let Some(target_edges) = edges_by_nodes.get_mut(&outgoing.second) {
target_edges.incoming.remove(&outgoing);
}
}
} else {
eprintln!("Inconsistent situation");
break;
}
}
if sorted_numbers.len().rem(2) == 1 {
result += sorted_numbers[sorted_numbers.len() / 2];
} else {
eprintln!("Line doesn't have odd length")
}
}
}
println!("Result {}", result);
}