advent-of-code/2023/day4/src/main.rs
2023-12-18 04:21:35 +01:00

162 lines
4.0 KiB
Rust

use std::fs;
use std::process;
use std::str::FromStr;
#[derive(Debug)]
enum ParseCardError {
InvalidInput,
ParseFailed,
}
#[derive(Clone)]
#[derive(Debug)]
struct Card {
id: i32,
win: Vec<i32>,
own: Vec<i32>,
}
impl Card {
fn new(id: i32, win: Vec<i32>, own: Vec<i32>) -> Self {
Self { id, win, own }
}
fn get_win_number(&self) -> Vec<i32> {
let mut winning: Vec<i32> = vec![];
for number in &self.own {
if self.win.contains(&number) {
winning.push(number.clone());
};
}
return winning;
}
fn get_points(&self) -> i32 {
let winning = self.get_win_number();
let mut points: i32 = 0;
if winning.len() > 0 {
points = points + 1;
for i in 0..(winning.len() - 1) as u32 {
let pow = 2_i32.pow(i);
points = points + pow;
}
}
return points;
}
fn card_winned(&self) -> Vec<i32> {
let win_number = self.get_win_number();
let mut winned: Vec<i32> = vec![];
for i in 1..(win_number.len() + 1) as i32 {
winned.push(self.id + i);
}
// println!("Winned card {} : {:?}", self.id, winned);
return winned;
}
}
impl FromStr for Card {
type Err = ParseCardError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let segments: Vec<&str> = s.split(":").collect::<Vec<_>>();
if segments.len() != 2 {
return Err(ParseCardError::InvalidInput);
}
let Ok(card_id) = segments[0].split_whitespace().collect::<Vec<_>>()[1].parse::<i32>()
else {
return Err(ParseCardError::ParseFailed);
};
let win_numbers: Vec<i32> = segments[1].split("|").collect::<Vec<_>>()[0]
.split_whitespace()
.map(|x| x.parse::<i32>().unwrap())
.collect();
let own_numbers: Vec<i32> = segments[1].split("|").collect::<Vec<_>>()[1]
.split_whitespace()
.map(|x| x.parse::<i32>().unwrap())
.collect();
return Ok(Card::new(card_id, win_numbers, own_numbers));
}
}
fn puzzle1() {
let read = fs::read_to_string("./day4.txt").expect("Don't find the file");
let lines = read.lines();
let mut cards: Vec<i32> = vec![];
for line in lines {
match line.parse::<Card>() {
Ok(card) => {
// println!("Card {} : {:?}", card.id, card.get_points());
cards.push(card.get_points());
}
Err(error) => {
eprintln!("Parsing error: {:?}", error);
process::exit(1);
}
}
}
let sum: i32 = cards.iter().sum();
println!("Puzzle 1 : {:?}", sum)
}
fn get_winned_card(cards: Vec<Card>, test_cards: Vec<Card>) -> Vec<Card> {
let mut return_cards: Vec<Card> = vec![];
for card in &test_cards {
let winned = card.card_winned();
for i in winned {
let a = usize::try_from(i).unwrap();
let c = &cards[a - 1];
return_cards.push(c.clone());
// print!("C : {:?} ", c.id);
}
// println!();
};
if return_cards.is_empty() {
return return_cards;
} else {
let mut a = get_winned_card(cards.clone(), return_cards.clone());
a.extend(return_cards);
return a;
}
}
fn puzzle2() {
let read = fs::read_to_string("./day4.txt").expect("Don't find the file");
let lines = read.lines();
let mut cards: Vec<Card> = vec![];
for line in lines {
match line.parse::<Card>() {
Ok(card) => {
// println!("Card {} : {:?}", card.id, card.get_points());
cards.push(card);
}
Err(error) => {
eprintln!("Parsing error: {:?}", error);
process::exit(1);
}
}
}
let c = get_winned_card(cards.clone(), cards.clone());
println!("Puzzle 2 : {:?}", c.len() + cards.len())
}
fn main() {
puzzle1();
puzzle2();
}