feat: added day 5 part 1 and 2
All checks were successful
Build and run challenges / Challenge for day (1) (push) Successful in 3s
Build and run challenges / Challenge for day (2) (push) Successful in 3s
Build and run challenges / Challenge for day (4) (push) Successful in 4s
Build and run challenges / Challenge for day (5) (push) Successful in 5s
Build and run challenges / Challenge for day (3) (push) Successful in 10s
All checks were successful
Build and run challenges / Challenge for day (1) (push) Successful in 3s
Build and run challenges / Challenge for day (2) (push) Successful in 3s
Build and run challenges / Challenge for day (4) (push) Successful in 4s
Build and run challenges / Challenge for day (5) (push) Successful in 5s
Build and run challenges / Challenge for day (3) (push) Successful in 10s
Signed-off-by: Louis Vallat <contact@louis-vallat.fr>
This commit is contained in:
parent
33472462bd
commit
77362b50a9
@ -11,7 +11,7 @@ jobs:
|
||||
name: Challenge for day
|
||||
strategy:
|
||||
matrix:
|
||||
day_number: [1, 2, 3, 4]
|
||||
day_number: [1, 2, 3, 4, 5]
|
||||
runs-on: rust-bookworm
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
|
6
day5/Cargo.toml
Normal file
6
day5/Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "day5"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
115
day5/src/main.rs
Normal file
115
day5/src/main.rs
Normal file
@ -0,0 +1,115 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::{env, fs};
|
||||
|
||||
fn read_input(path: &str) -> String {
|
||||
fs::read_to_string(path).expect("Cannot read file.")
|
||||
}
|
||||
|
||||
fn parse_input(input: &str) -> (HashMap<u32, HashSet<u32>>, Vec<Vec<u32>>) {
|
||||
let mut rules: HashMap<u32, HashSet<u32>> = HashMap::new();
|
||||
let mut updates = vec![];
|
||||
let mut lines = input.lines();
|
||||
|
||||
while let Some(line) = lines.next() {
|
||||
if line.is_empty() {
|
||||
break;
|
||||
}
|
||||
|
||||
let rule = line
|
||||
.split_once("|")
|
||||
.map(|l| (l.0.parse().unwrap(), l.1.parse().unwrap()))
|
||||
.unwrap();
|
||||
if rules.contains_key(&rule.0) {
|
||||
rules.get_mut(&rule.0).unwrap().insert(rule.1);
|
||||
} else {
|
||||
rules.insert(rule.0, HashSet::from_iter(vec![rule.1]));
|
||||
}
|
||||
}
|
||||
|
||||
while let Some(line) = lines.next() {
|
||||
if line.is_empty() {
|
||||
break;
|
||||
}
|
||||
updates.push(line.split(",").map(|l| l.parse().unwrap()).collect());
|
||||
}
|
||||
|
||||
(rules, updates)
|
||||
}
|
||||
|
||||
fn middle_if_complied(rules: &HashMap<u32, HashSet<u32>>, update: &Vec<u32>) -> Option<u32> {
|
||||
let mut already_met = HashSet::new();
|
||||
for x in update {
|
||||
if let Some(rules_for_x) = rules.get(&x) {
|
||||
for must_be_after in rules_for_x {
|
||||
if already_met.contains(must_be_after) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
already_met.insert(x);
|
||||
}
|
||||
Some(update[update.len() / 2])
|
||||
}
|
||||
|
||||
fn part_1(rules: &HashMap<u32, HashSet<u32>>, updates: &Vec<Vec<u32>>) -> u32 {
|
||||
updates
|
||||
.iter()
|
||||
.filter_map(|update| middle_if_complied(rules, update))
|
||||
.sum()
|
||||
}
|
||||
|
||||
fn middle_if_reordered(rules: &HashMap<u32, HashSet<u32>>, update: &Vec<u32>) -> Option<u32> {
|
||||
let mut update = update.clone();
|
||||
let mut has_been_reordered = false;
|
||||
let mut already_met: HashMap<u32, usize> = HashMap::from_iter([(update[0], 0)]);
|
||||
let mut pos = 1;
|
||||
while pos < update.len() {
|
||||
let x = update[pos];
|
||||
let mut lowest_pos = None;
|
||||
if let Some(rule) = rules.get(&x) {
|
||||
for must_be_after in rule {
|
||||
if already_met.contains_key(must_be_after) {
|
||||
let old_pos = *already_met.get(must_be_after).unwrap();
|
||||
if lowest_pos.is_none()
|
||||
|| (lowest_pos.is_some() && lowest_pos.unwrap() > old_pos)
|
||||
{
|
||||
lowest_pos = Some(old_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(lowest_pos) = lowest_pos {
|
||||
update.swap(lowest_pos, pos);
|
||||
already_met.insert(x, lowest_pos);
|
||||
has_been_reordered = true;
|
||||
}
|
||||
}
|
||||
if lowest_pos.is_none() {
|
||||
already_met.insert(x, pos);
|
||||
pos += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if has_been_reordered {
|
||||
Some(update[update.len() / 2])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn part_2(rules: &HashMap<u32, HashSet<u32>>, updates: &Vec<Vec<u32>>) -> u32 {
|
||||
updates
|
||||
.iter()
|
||||
.filter_map(|update| middle_if_reordered(rules, update))
|
||||
.sum()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
for arg in args.iter().skip(1) {
|
||||
let input = read_input(&arg);
|
||||
let (rules, updates) = parse_input(&input);
|
||||
println!("[{}]", &arg);
|
||||
println!("\t[Part 1] => Answer is '{}'.", part_1(&rules, &updates));
|
||||
println!("\t[Part 2] => Answer is '{}'.", part_2(&rules, &updates));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user