]> aoc.elinar.fr Git - aoc_2023/commitdiff
Day07 - part 1
authoralex <null>
Thu, 7 Dec 2023 10:39:15 +0000 (11:39 +0100)
committeralex <null>
Thu, 7 Dec 2023 10:39:15 +0000 (11:39 +0100)
src/day07.rs [new file with mode: 0644]
src/main.rs

diff --git a/src/day07.rs b/src/day07.rs
new file mode 100644 (file)
index 0000000..9e456d1
--- /dev/null
@@ -0,0 +1,165 @@
+use std::io::Read;
+use std::error::Error;
+use std::fs::File;
+
+use std::collections::HashMap;
+use std::cmp::Ordering;
+
+pub fn run(input_file: &str) -> Result<(), Box<dyn Error>> {
+    let mut f = File::open(input_file)?;
+    let mut input = String::new();
+    f.read_to_string(&mut input)?;
+
+    let res = run_part1(&input)?;
+    println!("{res}");
+
+    let res = run_part2(&input)?;
+    println!("{res}");
+
+    Ok(())
+}
+
+static CARDS: &str = "123456789TJQKA";
+
+#[derive(Debug, PartialEq, PartialOrd)]
+enum HandType {
+    HighCard,
+    OnePair,
+    TwoPair,
+    ThreeOfAKind,
+    FullHouse,
+    FourOfAKind,
+    FiveOfAKind,
+}
+
+#[derive(Debug, PartialEq)]
+struct Hand {
+    cards: [char ; 5],
+    bid: u32,
+    hand_type: HandType,
+}
+
+// TODO implémenter l'ordre
+impl Hand {
+    pub fn new(cards: &str, bid: u32) -> Self {
+        let mut hand_cards: [ char ; 5 ] = [ '\0' ; 5];
+        cards.chars().enumerate()
+            .for_each(|(i,c)| hand_cards[i] = c);
+        Self {
+            cards: hand_cards,
+            bid,
+            hand_type: Self::find_type(hand_cards),
+        }
+
+    }
+
+    pub fn find_type(cards: [char; 5]) -> HandType {
+        let mut map = CARDS.chars()
+            .map(|c| (c, 0_u32))
+            .collect::<HashMap<_,_>>();
+        cards.into_iter()
+            .for_each(|c| { map.insert(c, map.get(&c).unwrap() + 1); });
+
+        // on ne conserve que le type de cartes de la main et leur nombre
+        // d'occurrence
+        let occurrence = map.into_iter()
+            .filter(|(_,v)| v > &0)
+            .map(|(_,v)| v)
+            .collect::<Vec<_>>();
+
+        match occurrence.len() {
+            5 => HandType::HighCard,
+            4 => HandType::OnePair,
+            3 => {
+                // TwoPair or ThreeOfAKind
+                if occurrence.contains(&3) {
+                    return HandType::ThreeOfAKind;
+                }
+                HandType::TwoPair
+            },
+            2 => {
+                // FullHouse or FourOfAKind
+                if occurrence.contains(&4) {
+                    return HandType::FourOfAKind;
+                }
+                HandType::FullHouse
+            },
+            1 => HandType::FiveOfAKind,
+            _ => unreachable!(),
+        }
+    }
+}
+
+impl PartialOrd for Hand {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        if self.hand_type == other.hand_type {
+            // comparer les cartes
+            // pour cela on compare les index dans la liste des cartes CARDS
+            let mut i = 0;
+            while self.cards[i] == other.cards[i] {
+                i += 1;
+            }
+            let self_pos = CARDS.chars().position(|c| c == self.cards[i]).unwrap();
+            let other_pos = CARDS.chars().position(|c| c == other.cards[i]).unwrap();
+            return Some(self_pos.cmp(&other_pos));
+        }
+        self.hand_type.partial_cmp(&other.hand_type)
+    }
+}
+
+fn run_part1(input: &str) -> Result<u32, Box<dyn Error>> {
+    println!("Running day07 - part 1");
+
+    let mut hands: Vec<Hand> = Vec::new();
+
+    input.lines()
+        .filter(|l| !l.is_empty())
+        .for_each(|l| {
+            let (cards, bid) = l.split_once(' ').unwrap();
+            hands.push(Hand::new(cards, bid.parse().unwrap()));
+        });
+
+    hands.sort_by(|a, b| {
+        a.partial_cmp(&b).unwrap()
+    });
+
+    let res = hands.iter().enumerate()
+        .map(|(i, h)| {
+            let i: u32 = i as u32;
+            h.bid * (i + 1)
+        })
+        .sum();
+
+    Ok(res)
+}
+
+fn run_part2(input: &str) -> Result<u32, Box<dyn Error>> {
+    println!("Running day07 - part 2");
+    let res = 0;
+    Ok(res)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    static TEXT_INPUT: &str = "\
+32T3K 765
+T55J5 684
+KK677 28
+KTJJT 220
+QQQJA 483
+";
+
+    #[test]
+    fn day07_part1() {
+        let res = run_part1(TEXT_INPUT);
+        assert_eq!(6440, res.unwrap());
+    }
+
+    #[test]
+    fn day07_part2() {
+        let res = run_part2(TEXT_INPUT);
+        assert_eq!(0, res.unwrap());
+    }
+}
index ae0262cfccf712596712c2119db6f81675aada12..d4ac3b35a0634f5d0cfa2f24db2869727cda0966 100644 (file)
@@ -9,6 +9,7 @@ pub mod day03;
 pub mod day04;
 pub mod day05;
 pub mod day06;
+pub mod day07;
 
 fn main() {
     let args: Vec<String> = env::args().collect();
@@ -33,6 +34,7 @@ fn run(day: &str, input_file: &str) -> Result<(), Box<dyn Error>> {
         "day04" => day04::run(input_file)?,
         "day05" => day05::run(input_file)?,
         "day06" => day06::run(input_file)?,
+        "day07" => day07::run(input_file)?,
         _ => return Err(format!("unknown day \"{day}\"").into()),
     }
     Ok(())