add day 10

implemented by myself, but with strategical help from claude
This commit is contained in:
timeshifter
2026-06-30 16:52:44 +02:00
parent 6422973ea7
commit b21143a92a
5 changed files with 429 additions and 0 deletions
+179
View File
@@ -0,0 +1,179 @@
#[cfg(debug_assertions)]
const FILENAME: &str = "example.txt";
#[cfg(not(debug_assertions))]
const FILENAME: &str = "input.txt";
use std::collections::{HashMap, HashSet};
fn main() {
let entities: Vec<_> = std::fs::read_to_string(FILENAME)
.unwrap()
.lines()
.map(parse)
.collect();
let mut bots = HashMap::new();
let mut assignments = HashMap::new();
for entity in entities {
match entity {
Entity::Bot(id, bot) => {
bots.insert(id, bot);
}
Entity::Assignment(value, id) => {
assignments.insert(id, value);
}
}
}
for (value, bot_id) in &assignments {
bots.get_mut(bot_id).unwrap().chips.insert(*value);
}
run_simulation(&mut bots);
}
fn run_simulation(bots: &mut HashMap<u32, Bot>) {
dbg!(&bots);
let mut all_ready = HashMap::new();
let mut outputs: HashMap<u32, u32> = HashMap::new();
loop {
for (id, bot) in bots.iter() {
if bot.chips.contains(&17) && bot.chips.contains(&61) {
println!("{id}");
}
}
for (id, bot) in bots.iter() {
if bot.chips.len() == 2 {
all_ready.insert(*id, bot.clone());
}
}
if all_ready.is_empty() {
break;
}
for (ready_id, ready_bot) in &all_ready {
match ready_bot.low {
Destination::Bot(target_id) => {
bots.get_mut(&target_id)
.unwrap()
.chips
.insert(copy_smaller(&ready_bot.chips));
}
Destination::Output(output_id) => {
outputs.insert(output_id, copy_smaller(&ready_bot.chips));
}
}
match ready_bot.high {
Destination::Bot(target_id) => {
bots.get_mut(&target_id)
.unwrap()
.chips
.insert(copy_larger(&ready_bot.chips));
}
Destination::Output(output_id) => {
outputs.insert(output_id, copy_larger(&ready_bot.chips));
}
}
bots.get_mut(ready_id).unwrap().chips.clear();
}
all_ready.clear();
}
let product = outputs
.into_iter()
.filter(|(k, _)| [0, 1, 2].contains(k))
.map(|(_, v)| v)
.product::<u32>();
println!("{product}");
}
fn copy_larger(h: &HashSet<u32>) -> u32 {
let mut iter = h.iter();
let a = *iter.next().unwrap();
let b = *iter.next().unwrap();
if a > b { a } else { b }
}
fn copy_smaller(h: &HashSet<u32>) -> u32 {
let mut iter = h.iter();
let a = *iter.next().unwrap();
let b = *iter.next().unwrap();
if a > b { b } else { a }
}
#[derive(Debug, PartialEq, Clone)]
struct Bot {
pub chips: HashSet<u32>,
pub low: Destination,
pub high: Destination,
}
impl Bot {
fn new(low: Destination, high: Destination) -> Self {
Self {
chips: HashSet::new(),
low,
high,
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum Destination {
Bot(u32),
Output(u32),
}
#[derive(Debug, PartialEq)]
enum Entity {
Bot(u32, Bot), // maps bot ID to actual bot
Assignment(u32, u32), // maps bot ID to actual value
}
/// Return ID and destination so that in can be collected into a `Simulation` hashmap.
fn parse(s: &str) -> Entity {
let mut split = s.split_whitespace();
match split.next().unwrap() {
"value" => {
let value = split.next().unwrap().parse().unwrap();
let bot_id = split.next_back().unwrap().parse().unwrap();
// todo!();
Entity::Assignment(bot_id, value)
}
"bot" => {
let bot_id = split.next().unwrap().parse().unwrap();
let mut iter = split.skip_while(|w| *w != "to");
let low = parse_destination_type(&mut iter);
let mut iter = iter.skip_while(|w| *w != "to");
let high = parse_destination_type(&mut iter);
let bot = Bot::new(low, high);
Entity::Bot(bot_id, bot)
}
_ => panic!("unknown line type: {s}"),
}
}
fn parse_destination_type<'a>(split: &mut impl Iterator<Item = &'a str>) -> Destination {
let bot_or_output = split.nth(1).unwrap();
let id = split.next().unwrap().parse().unwrap();
match bot_or_output {
"bot" => Destination::Bot(id),
"output" => Destination::Output(id),
_ => panic!("unknown destination type: {bot_or_output}"),
}
}