Matching duplicates in vector

I would like to match poker hands. For a flush, I would require the hand to have at least four repeated cards of one suit.

enum Suit {
    Hearts, Clubs, Diamonds, Spades
}

enum Rank {
    Two, Three, Four, Five, Six, Seven,
    Eight, Nine, Ten, Jack, Queen, King, Ace
}

struct Card {
    suit: Suit,
    rank: Rank,
}

I imagine that some nice pattern matching should be able to be done here, but I am not sure about the actual syntax that should be used.

enum HandRanking {
    Flush, HighCard(Rank)
}

fn highest_rank (cards: Vec<Card>) -> Rank {
    cards.iter().max().expect("Empty cards vector provided")
}

fn evaluate_hand(cards: Vec<Card>) -> HandRank {
    match cards[..] {
        [
            Card { rank: rank1, suit },
            Card { rank: rank2, suit },
            Card { rank: rank3, suit },
            Card { rank: rank4, suit },
            Card { rank: rank5, suit2 },
        ] => Flush,
        _ => HighCard(highest_rank(cards))
    }
}

with using suit only once I am trying to indicate that it should be the same across all cards, however Rust does not understand me and gives me the error:
src/main.rs|63 col 33 error 416| identifier `suit` is bound more than once in the same pattern

You can't do this with a match statement. How about something like this?

let mut suit_counter = [0; 4];
for card in &cards {
    suit_counter[card.suit as usize] += 1;
}
for suit in [Hearts, Clubs, Diamonds, Spades] {
    if suit_counter[suit as usize] == 4 {
        ...
    }
}

This uses the fact that C-style enums (i.e. enums without fields on the variants) can be cast to integers.

Well, you can: Rust Playground

But it's not nice, and it only does a part of what's needed (since it implies the first 4 cards need to be the ones to make a flush here),

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.