Skip to content

Instantly share code, notes, and snippets.

@gdejohn
Last active February 27, 2023 21:29
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gdejohn/8293321 to your computer and use it in GitHub Desktop.
Save gdejohn/8293321 to your computer and use it in GitHub Desktop.
straightforward five-card poker hand comparison
package poker;
public record Card(Rank rank, Suit suit) {}
package poker;
public enum Category {
HIGH_CARD,
ONE_PAIR,
TWO_PAIR,
THREE_OF_A_KIND,
STRAIGHT,
FLUSH,
FULL_HOUSE,
FOUR_OF_A_KIND,
STRAIGHT_FLUSH
}
package poker;
import static poker.Category.*;
import static poker.Rank.*; // ACE, FIVE
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.*; // counting, groupingBy
import java.util.*; // Arrays, Set
import java.util.Map.Entry;
public record Hand(Category category, Rank... ranks) implements Comparable<Hand> {
public static Hand evaluate(Set<Card> cards) {
if (cards.size() != 5) {
throw new IllegalArgumentException();
}
var flush = cards.stream().map(Card::suit).distinct().count() == 1;
var counts = cards.stream().collect(groupingBy(Card::rank, counting()));
var ranks = counts.entrySet().stream().sorted(
comparing(Entry<Rank, Long>::getValue).thenComparing(Entry::getKey).reversed()
).map(Entry::getKey).toArray(Rank[]::new);
if (ranks.length == 4) {
return new Hand(ONE_PAIR, ranks);
} else if (ranks.length == 3) {
return new Hand(counts.get(ranks[0]) == 2 ? TWO_PAIR : THREE_OF_A_KIND, ranks);
} else if (ranks.length == 2) {
return new Hand(counts.get(ranks[0]) == 3 ? FULL_HOUSE : FOUR_OF_A_KIND, ranks);
} else if (ranks[0].ordinal() - ranks[4].ordinal() == 4) {
return new Hand(flush ? STRAIGHT_FLUSH : STRAIGHT, ranks[0]);
} else if (ranks[0].equals(ACE) && ranks[1].equals(FIVE)) { // A-2-3-4-5
return new Hand(flush ? STRAIGHT_FLUSH : STRAIGHT, FIVE);
} else {
return new Hand(flush ? FLUSH : HIGH_CARD, ranks);
}
}
@Override
public int compareTo(Hand that) { // first compare by category, then compare ranks lexicographically
return comparing(Hand::category).thenComparing(Hand::ranks, Arrays::compare).compare(this, that);
}
}
package poker;
public enum Rank {
TWO,
THREE,
FOUR,
FIVE,
SIX,
SEVEN,
EIGHT,
NINE,
TEN,
JACK,
QUEEN,
KING,
ACE
}
package poker;
public enum Suit {
DIAMONDS,
CLUBS,
HEARTS,
SPADES
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment