add day 10
implemented by myself, but with strategical help from claude
This commit is contained in:
@@ -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}"),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user