162 lines
4.0 KiB
Rust
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();
|
|
}
|