Day 7a. After this we will change the card values.
This commit is contained in:
parent
38f1be8181
commit
0700310d4c
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,249 @@
|
||||||
|
use std::{
|
||||||
|
cmp::Ordering,
|
||||||
|
collections::{HashMap, HashSet},
|
||||||
|
};
|
||||||
|
|
||||||
|
const INPUT: &str = include_str!("../data/day7.txt");
|
||||||
|
|
||||||
|
pub fn day7a() -> String {
|
||||||
|
format!("{}", calculate_game(INPUT))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn day7b() -> String {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calculate_game(game: &str) -> u64 {
|
||||||
|
let mut hands = game
|
||||||
|
.lines()
|
||||||
|
.map(|line| parse_line(line))
|
||||||
|
.collect::<Vec<(Hand, u64)>>();
|
||||||
|
for hand in hands.iter() {
|
||||||
|
println!("{:?} {:?} ", hand.0, hand.0.classify());
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("");
|
||||||
|
|
||||||
|
hands.sort_by(|(hand1, bid1), (hand2, bid2)| {
|
||||||
|
if hand1.cmp(hand2) == Ordering::Equal {
|
||||||
|
bid1.cmp(bid2)
|
||||||
|
} else {
|
||||||
|
hand1.cmp(hand2)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for hand in hands.iter() {
|
||||||
|
println!("{:?} {:?} ", hand.0, hand.0.classify());
|
||||||
|
}
|
||||||
|
|
||||||
|
hands
|
||||||
|
.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(rank, (_, bid))| (rank as u64 + 1) * bid)
|
||||||
|
.fold(0, |acc, val| acc + val)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_line(s: &str) -> (Hand, u64) {
|
||||||
|
let mut parts = s.split(" ");
|
||||||
|
let hand = parts.next().unwrap();
|
||||||
|
let bid = parts.next().unwrap();
|
||||||
|
|
||||||
|
(Hand::from(hand), bid.parse::<u64>().unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Hash, Eq, Ord)]
|
||||||
|
struct Card(u32);
|
||||||
|
|
||||||
|
impl From<char> for Card {
|
||||||
|
fn from(s: char) -> Card {
|
||||||
|
match s {
|
||||||
|
'2' => Card(2),
|
||||||
|
'3' => Card(3),
|
||||||
|
'4' => Card(4),
|
||||||
|
'5' => Card(5),
|
||||||
|
'6' => Card(6),
|
||||||
|
'7' => Card(7),
|
||||||
|
'8' => Card(8),
|
||||||
|
'9' => Card(9),
|
||||||
|
'T' => Card(10),
|
||||||
|
'J' => Card(11),
|
||||||
|
'Q' => Card(12),
|
||||||
|
'K' => Card(13),
|
||||||
|
'A' => Card(14),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)]
|
||||||
|
enum HandType {
|
||||||
|
HighCard,
|
||||||
|
OnePair,
|
||||||
|
TwoPair,
|
||||||
|
ThreeOfAKind,
|
||||||
|
FullHouse,
|
||||||
|
FourOfAKind,
|
||||||
|
FiveOfAKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
struct Hand(Vec<Card>);
|
||||||
|
|
||||||
|
impl Hand {
|
||||||
|
fn classify(&self) -> HandType {
|
||||||
|
let mut cards: HashSet<Card> = HashSet::new();
|
||||||
|
let mut pairs: HashSet<Card> = HashSet::new();
|
||||||
|
let mut triples: HashSet<Card> = HashSet::new();
|
||||||
|
let mut quads: HashSet<Card> = HashSet::new();
|
||||||
|
let mut quints: HashSet<Card> = HashSet::new();
|
||||||
|
|
||||||
|
for card in self.0.iter() {
|
||||||
|
if quads.contains(card) {
|
||||||
|
quads.remove(card);
|
||||||
|
quints.insert(*card);
|
||||||
|
} else if triples.contains(card) {
|
||||||
|
triples.remove(card);
|
||||||
|
quads.insert(*card);
|
||||||
|
} else if pairs.contains(card) {
|
||||||
|
pairs.remove(card);
|
||||||
|
triples.insert(*card);
|
||||||
|
} else if cards.contains(card) {
|
||||||
|
cards.remove(card);
|
||||||
|
pairs.insert(*card);
|
||||||
|
} else {
|
||||||
|
cards.insert(*card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if quints.len() > 0 {
|
||||||
|
HandType::FiveOfAKind
|
||||||
|
} else if quads.len() > 0 {
|
||||||
|
HandType::FourOfAKind
|
||||||
|
} else if triples.len() > 0 && pairs.len() > 0 {
|
||||||
|
HandType::FullHouse
|
||||||
|
} else if triples.len() > 0 {
|
||||||
|
HandType::ThreeOfAKind
|
||||||
|
} else if pairs.len() == 2 {
|
||||||
|
HandType::TwoPair
|
||||||
|
} else if pairs.len() == 1 {
|
||||||
|
HandType::OnePair
|
||||||
|
} else {
|
||||||
|
HandType::HighCard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for Hand {
|
||||||
|
fn from(s: &str) -> Hand {
|
||||||
|
Hand(s.chars().map(|c| Card::from(c)).collect::<Vec<Card>>())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Hand {
|
||||||
|
fn partial_cmp(&self, other: &Hand) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for Hand {
|
||||||
|
fn cmp(&self, other: &Hand) -> Ordering {
|
||||||
|
let class1 = self.classify();
|
||||||
|
let class2 = other.classify();
|
||||||
|
|
||||||
|
if class1 == class2 {
|
||||||
|
for (card1, card2) in self.0.iter().zip(other.0.clone()) {
|
||||||
|
let cmp = card1.cmp(&card2);
|
||||||
|
if cmp != Ordering::Equal {
|
||||||
|
return cmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ordering::Equal;
|
||||||
|
} else {
|
||||||
|
class1.cmp(&class2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const INPUT: &str = "32T3K 765
|
||||||
|
T55J5 684
|
||||||
|
KK677 28
|
||||||
|
KTJJT 220
|
||||||
|
QQQJA 483";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_calculates_test_data() {
|
||||||
|
assert_eq!(calculate_game(INPUT), 6440);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parses_hand() {
|
||||||
|
let test_cases = [
|
||||||
|
(
|
||||||
|
"32T3K",
|
||||||
|
Hand(vec![Card(3), Card(2), Card(10), Card(3), Card(13)]),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"T55J5",
|
||||||
|
Hand(vec![Card(10), Card(5), Card(5), Card(11), Card(5)]),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"KK677",
|
||||||
|
Hand(vec![Card(13), Card(13), Card(6), Card(7), Card(7)]),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"KTJJT",
|
||||||
|
Hand(vec![Card(13), Card(10), Card(11), Card(11), Card(10)]),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"QQQJA",
|
||||||
|
Hand(vec![Card(12), Card(12), Card(12), Card(11), Card(14)]),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (hand_str, hand) in test_cases {
|
||||||
|
assert_eq!(Hand::from(hand_str), hand)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn classifies_a_hand() {
|
||||||
|
let test_cases = [
|
||||||
|
(
|
||||||
|
Hand(vec![Card(12), Card(11), Card(10), Card(9), Card(8)]),
|
||||||
|
HandType::HighCard,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Hand(vec![Card(3), Card(2), Card(10), Card(3), Card(13)]),
|
||||||
|
HandType::OnePair,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Hand(vec![Card(10), Card(5), Card(5), Card(11), Card(5)]),
|
||||||
|
HandType::ThreeOfAKind,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Hand(vec![Card(13), Card(13), Card(6), Card(7), Card(7)]),
|
||||||
|
HandType::TwoPair,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Hand(vec![Card(13), Card(10), Card(11), Card(11), Card(10)]),
|
||||||
|
HandType::TwoPair,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Hand(vec![Card(12), Card(12), Card(12), Card(11), Card(14)]),
|
||||||
|
HandType::ThreeOfAKind,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Hand(vec![Card(12), Card(12), Card(12), Card(11), Card(11)]),
|
||||||
|
HandType::FullHouse,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (hand, classification) in test_cases {
|
||||||
|
assert_eq!(hand.classify(), classification, "{:?}", hand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ mod day3;
|
||||||
mod day4;
|
mod day4;
|
||||||
mod day5;
|
mod day5;
|
||||||
mod day6;
|
mod day6;
|
||||||
|
mod day7;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let day = std::env::args().skip(1).next();
|
let day = std::env::args().skip(1).next();
|
||||||
|
@ -21,6 +22,8 @@ fn main() {
|
||||||
Some("5b") => day5::day5b(),
|
Some("5b") => day5::day5b(),
|
||||||
Some("6a") => day6::day6a(),
|
Some("6a") => day6::day6a(),
|
||||||
Some("6b") => day6::day6b(),
|
Some("6b") => day6::day6b(),
|
||||||
|
Some("7a") => day7::day7a(),
|
||||||
|
Some("7b") => day7::day7b(),
|
||||||
_ => panic!("unrecognized day"),
|
_ => panic!("unrecognized day"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue