97 lines
2.9 KiB
Rust
97 lines
2.9 KiB
Rust
use std::collections::HashSet;
|
|
use std::error::Error;
|
|
use std::fs::File;
|
|
use std::io::{self, BufRead};
|
|
use std::vec::Vec;
|
|
|
|
fn recursive_combat(mut deck1: Vec<u32>, mut deck2: Vec<u32>) -> (Vec<u32>, Vec<u32>) {
|
|
let mut deck_configs1: HashSet<Vec<u32>> = HashSet::new();
|
|
let mut deck_configs2: HashSet<Vec<u32>> = HashSet::new();
|
|
|
|
while deck1.len() != 0 && deck2.len() != 0 {
|
|
println!("Deck 1: {:?}", deck1);
|
|
println!("Deck 2: {:?}", deck2);
|
|
|
|
if deck_configs1.contains(&deck1) || deck_configs2.contains(&deck2) {
|
|
println!("Player 1 wins by deck configuration.");
|
|
return (deck1, Vec::new());
|
|
}
|
|
deck_configs1.insert(deck1.clone());
|
|
deck_configs2.insert(deck2.clone());
|
|
|
|
let card1 = deck1.remove(0);
|
|
let card2 = deck2.remove(0);
|
|
|
|
if deck1.len() as u32 >= card1 && deck2.len() as u32 >= card2 {
|
|
println!("Recursing !");
|
|
let rec_deck1: Vec<u32> = deck1.iter().cloned().take(card1 as usize).collect();
|
|
let rec_deck2: Vec<u32> = deck2.iter().cloned().take(card2 as usize).collect();
|
|
|
|
let (result_deck1, result_deck2) = recursive_combat(rec_deck1, rec_deck2);
|
|
if result_deck1.len() > result_deck2.len() {
|
|
println!("Player 1 wins by recursion");
|
|
deck1.push(card1);
|
|
deck1.push(card2);
|
|
} else {
|
|
println!("Player 2 wins by recursion");
|
|
deck2.push(card2);
|
|
deck2.push(card1);
|
|
}
|
|
} else {
|
|
if card1 > card2 {
|
|
println!("Player 1 wins");
|
|
deck1.push(card1);
|
|
deck1.push(card2);
|
|
} else {
|
|
println!("Player 2 wins");
|
|
deck2.push(card2);
|
|
deck2.push(card1);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (deck1, deck2);
|
|
}
|
|
|
|
fn main() -> Result<(), Box<dyn Error>> {
|
|
let file = File::open("inputs/day22.txt")?;
|
|
let mut lines = io::BufReader::new(file).lines().map(|l| l.unwrap());
|
|
|
|
lines.next();
|
|
let mut deck1: Vec<u32> = Vec::new();
|
|
while let Some(line) = lines.next() {
|
|
if line == "" {
|
|
break;
|
|
}
|
|
deck1.push(line.parse().expect("Unable to parse card number"));
|
|
}
|
|
|
|
lines.next();
|
|
let mut deck2: Vec<u32> = Vec::new();
|
|
while let Some(line) = lines.next() {
|
|
if line == "" {
|
|
break;
|
|
}
|
|
deck2.push(line.parse().expect("Unable to parse card number"));
|
|
}
|
|
|
|
let (deck1, deck2) = recursive_combat(deck1, deck2);
|
|
|
|
let winning_deck = if deck1.len() != 0 { deck1 } else { deck2 };
|
|
let points = winning_deck
|
|
.iter()
|
|
.rev()
|
|
.enumerate()
|
|
.map(|(pos, card)| ((pos + 1) as u32) * card)
|
|
.fold(0, |p, acc| p + acc);
|
|
|
|
println!("Points: {}", points);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use crate::*;
|
|
}
|