Alexey Dorokhov vor 2 Jahren
Ursprung
Commit
ec38e0a4b4
8 geänderte Dateien mit 358 neuen und 0 gelöschten Zeilen
  1. 1 0
      day_7a/.gitignore
  2. 32 0
      day_7a/Cargo.lock
  3. 9 0
      day_7a/Cargo.toml
  4. 125 0
      day_7a/src/main.rs
  5. 1 0
      day_7b/.gitignore
  6. 32 0
      day_7b/Cargo.lock
  7. 9 0
      day_7b/Cargo.toml
  8. 149 0
      day_7b/src/main.rs

+ 1 - 0
day_7a/.gitignore

@@ -0,0 +1 @@
+target

+ 32 - 0
day_7a/Cargo.lock

@@ -0,0 +1,32 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "day_7a"
+version = "0.1.0"
+dependencies = [
+ "nom",
+]
+
+[[package]]
+name = "memchr"
+version = "2.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "nom"
+version = "7.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]

+ 9 - 0
day_7a/Cargo.toml

@@ -0,0 +1,9 @@
+[package]
+name = "day_7a"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+nom = "7"

+ 125 - 0
day_7a/src/main.rs

@@ -0,0 +1,125 @@
+use std::fs;
+use std::env;
+use std::cmp::Ordering;
+
+use nom::IResult;
+use nom::character::complete::char;
+use nom::combinator::value;
+use nom::branch::alt;
+use nom::multi::many1;
+use nom::sequence::separated_pair;
+use nom::character::complete::space1;
+use nom::character::complete::i64;
+use nom::combinator::map;
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+struct Hand {
+    cards: Vec<i32>,
+}
+
+impl Hand {
+    fn strength(&self) -> i32 {
+        let mut kinds: [i32; 15] = [0; 15];
+        for c in &self.cards {
+            kinds[*c as usize] += 1;
+        }
+
+        // descending sort
+        kinds.sort_by(|a, b|b.cmp(a));
+        if kinds[0] == 5 {
+            return 6;
+        } else if kinds[0] == 4 {
+            return 5;
+        } else if kinds[0] == 3 && kinds[1] == 2 {
+            return 4;
+        } else if kinds[0] == 3 {
+            return 3;
+        } else if kinds[0] == 2 && kinds[1] == 2 {
+            return 2;
+        } else if kinds[0] == 2 {
+            return 1;
+        }
+
+        0
+    }
+}
+
+impl PartialOrd for Hand {
+    fn partial_cmp(&self, other: &Hand) -> Option<Ordering> {
+        let str_cmp = self.strength().cmp(&other.strength());
+        if str_cmp != Ordering::Equal {
+            return Some(str_cmp);
+        }
+        for i in 0..self.cards.len() {
+            let card_cmp = self.cards[i].cmp(&other.cards[i]);
+            if card_cmp != Ordering::Equal {
+                return Some(card_cmp);
+            }
+        }
+        Some(Ordering::Equal)
+    }
+}
+
+impl Ord for Hand {
+    fn cmp(&self, other: &Hand) -> Ordering {
+        self.partial_cmp(other).unwrap()
+    }
+}
+
+fn parse_card(input: &str) -> IResult<&str, i32> {
+    alt((
+        value(2, char('2')),
+        value(3, char('3')),
+        value(4, char('4')),
+        value(5, char('5')),
+        value(6, char('6')),
+        value(7, char('7')),
+        value(8, char('8')),
+        value(9, char('9')),
+        value(10, char('T')),
+        value(11, char('J')),
+        value(12, char('Q')),
+        value(13, char('K')),
+        value(14, char('A')),
+    ))(input)
+}
+
+fn parse_hand(input: &str) -> IResult<&str, Hand> {
+    map(many1(parse_card), |cards:Vec<i32>| Hand{cards})(input)
+}
+
+fn parse_hand_and_bid(input: &str) -> IResult<&str, (Hand, i64)> {
+    separated_pair(parse_hand, space1, i64)(input)
+}
+
+fn parse_line(input: &str) -> Result<(Hand, i64), String> {
+    match parse_hand_and_bid(input) {
+        Ok((rest, data)) => if rest == "" {
+            Ok(data)
+        } else {
+            Err(format!("Incomplete parse, remaining: {}", rest))
+        },
+        Err(error) => Err(error.to_string()),
+    }
+}
+
+fn main() {
+    let args: Vec<String> = env::args().collect();
+    let file_path = &args[1];
+    let input_data = fs::read_to_string(file_path).unwrap_or_else(
+        |_|{panic!("Can't read file {}", file_path)});
+
+    let mut hands_and_bids = Vec::new();
+    for line in input_data.lines() {
+        let hand_and_bid = parse_line(line).unwrap_or_else(
+            |e|panic!("Failed to parse line: {}", e));
+        hands_and_bids.push(hand_and_bid);
+    }
+   
+    hands_and_bids.sort_by(|a,b|a.0.cmp(&b.0));
+    let mut result:i64 = 0;
+    for i in 0..hands_and_bids.len() {
+        result += hands_and_bids[i].1 * (i+1) as i64;
+    }
+    println!("{result}");
+}

+ 1 - 0
day_7b/.gitignore

@@ -0,0 +1 @@
+target

+ 32 - 0
day_7b/Cargo.lock

@@ -0,0 +1,32 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "day_7b"
+version = "0.1.0"
+dependencies = [
+ "nom",
+]
+
+[[package]]
+name = "memchr"
+version = "2.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "nom"
+version = "7.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]

+ 9 - 0
day_7b/Cargo.toml

@@ -0,0 +1,9 @@
+[package]
+name = "day_7b"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+nom = "7"

+ 149 - 0
day_7b/src/main.rs

@@ -0,0 +1,149 @@
+use std::fs;
+use std::env;
+use std::cmp::max;
+
+use nom::IResult;
+use nom::character::complete::char;
+use nom::combinator::value;
+use nom::branch::alt;
+use nom::multi::many1;
+use nom::sequence::separated_pair;
+use nom::character::complete::space1;
+use nom::character::complete::i64;
+use nom::combinator::map;
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+struct Hand {
+    cards: Vec<i32>,
+    cached_strength: Option<i32>,
+}
+
+fn hand_strength(cards: &Vec<i32>) -> i32 {
+    let mut kinds: [i32; 15] = [0; 15];
+    for c in cards {
+        kinds[*c as usize] += 1;
+    }
+
+    // descending sort
+    kinds.sort_by(|a, b|b.cmp(a));
+    if kinds[0] == 5 {
+        return 6;
+    } else if kinds[0] == 4 {
+        return 5;
+    } else if kinds[0] == 3 && kinds[1] == 2 {
+        return 4;
+    } else if kinds[0] == 3 {
+        return 3;
+    } else if kinds[0] == 2 && kinds[1] == 2 {
+        return 2;
+    } else if kinds[0] == 2 {
+        return 1;
+    }
+
+    0
+}
+
+impl Hand {
+    fn strength(&mut self) -> i32 {
+        if self.cached_strength.is_some() {
+            return self.cached_strength.unwrap();
+        }
+
+        let mut joker_indices = Vec::new();
+        for i in 0..self.cards.len() {
+            if self.cards[i] == 0 {
+                joker_indices.push(i);
+            }
+        }
+
+        let mut hands = vec![self.cards.clone()];
+        for joker_index in joker_indices {
+            let mut next_hands = Vec::new();
+            for hand in &hands {
+                for card in 0..13 {
+                    let mut next_hand = hand.clone();
+                    next_hand[joker_index] = card;
+                    next_hands.push(next_hand);
+                }
+            }
+            hands = next_hands;
+        }
+
+        self.cached_strength = Some(hands.into_iter().map(|h|hand_strength(&h)).fold(0, |acc, s| max(acc, s)));
+        self.cached_strength.unwrap()
+    }
+}
+
+fn parse_card(input: &str) -> IResult<&str, i32> {
+    alt((
+        value(0, char('J')),
+        value(1, char('2')),
+        value(2, char('3')),
+        value(3, char('4')),
+        value(4, char('5')),
+        value(5, char('6')),
+        value(6, char('7')),
+        value(7, char('8')),
+        value(8, char('9')),
+        value(9, char('T')),
+        value(10, char('Q')),
+        value(11, char('K')),
+        value(12, char('A')),
+    ))(input)
+}
+
+fn parse_hand(input: &str) -> IResult<&str, Hand> {
+    map(many1(parse_card), |cards:Vec<i32>| Hand{cards, cached_strength:None})(input)
+}
+
+fn parse_hand_and_bid(input: &str) -> IResult<&str, (Hand, i64)> {
+    separated_pair(parse_hand, space1, i64)(input)
+}
+
+fn parse_line(input: &str) -> Result<(Hand, i64), String> {
+    match parse_hand_and_bid(input) {
+        Ok((rest, data)) => if rest == "" {
+            Ok(data)
+        } else {
+            Err(format!("Incomplete parse, remaining: {}", rest))
+        },
+        Err(error) => Err(error.to_string()),
+    }
+}
+
+fn main() {
+    let args: Vec<String> = env::args().collect();
+    let file_path = &args[1];
+    let input_data = fs::read_to_string(file_path).unwrap_or_else(
+        |_|{panic!("Can't read file {}", file_path)});
+
+    let mut order:Vec<usize> = Vec::new();
+    let mut hands_and_bids = Vec::new();
+
+    let mut offset:usize = 0;
+    for line in input_data.lines() {
+        let hand_and_bid = parse_line(line).unwrap_or_else(
+            |e|panic!("Failed to parse line: {}", e));
+
+        hands_and_bids.push(hand_and_bid);
+        order.push(offset);
+        offset += 1;
+    }
+
+    order.sort_by(|a,b|{
+        let sa = hands_and_bids[*a].0.strength();
+        let sb = hands_and_bids[*b].0.strength();
+        if sa == sb {
+            hands_and_bids[*a].0.cards.cmp(&hands_and_bids[*b].0.cards)
+        } else {
+            sa.cmp(&sb)
+        }
+    });
+
+   
+    let mut result:i64 = 0;
+    for i in 0..order.len() {
+        result += hands_and_bids[order[i]].1 * (i+1) as i64;
+    }
+    println!("{result}");
+}