*: small refactors and test changes
This commit is contained in:
@@ -17,7 +17,7 @@ impl Iterator for CardIterator {
|
||||
suit: Suit::Spade,
|
||||
deck,
|
||||
}) => {
|
||||
self.0 = Card::Joker((deck + 1) * -1);
|
||||
self.0 = Card::Joker(-(deck + 1));
|
||||
None
|
||||
}
|
||||
Card::PlayingCard(pc) => {
|
||||
@@ -40,7 +40,7 @@ impl DoubleEndedIterator for CardIterator {
|
||||
suit: Suit::Diamond,
|
||||
deck,
|
||||
}) => {
|
||||
self.0 = Card::Joker((deck + 1) * -1);
|
||||
self.0 = Card::Joker(-(deck + 1));
|
||||
None
|
||||
}
|
||||
Card::PlayingCard(pc) => {
|
||||
|
||||
@@ -273,11 +273,18 @@ mod test_impls {
|
||||
|
||||
#[test]
|
||||
fn rank() {
|
||||
let ranks = Rank::iter_all().into_iter().collect::<HashSet<_>>();
|
||||
let ranks = Rank::all().into_iter().collect::<HashSet<_>>();
|
||||
// TEST: Rank::iter_all produces all 13 unique ranks.
|
||||
assert_eq!(ranks.len(), 13);
|
||||
|
||||
for rank in Rank::iter_all() {
|
||||
for (ind, rank) in Rank::all().iter().enumerate() {
|
||||
let rest = rank.iter_rest().collect::<HashSet<_>>();
|
||||
// TEST: Rank::iter_rest should generate the remaining ranks after
|
||||
// the current rank in order.
|
||||
assert_eq!(rest.len(), 13 - ind - 1);
|
||||
}
|
||||
|
||||
for rank in Rank::all() {
|
||||
let cards = rank.cards().into_iter().collect::<HashSet<_>>();
|
||||
assert_eq!(cards.len(), 4, "Expected 4 cards per rank");
|
||||
for c in cards {
|
||||
@@ -293,8 +300,8 @@ mod test_impls {
|
||||
|
||||
// Since there are 4 unique cards generated by rank.cards(), and
|
||||
// they all have the same deck (0) and rank (rank), they must differ
|
||||
// by Suit by virtue of ord. 4 suits suggests (by pigeonhole
|
||||
// principle) that all suits must have been used.
|
||||
// by Suit. 4 suits suggests (by pigeonhole principle) that all
|
||||
// suits must have been used.
|
||||
|
||||
// So rank.cards() generates all cards of deck 0 that have that rank
|
||||
// (which is precisely 4 cards). QED.
|
||||
@@ -408,7 +415,7 @@ mod test_impls {
|
||||
counter
|
||||
};
|
||||
|
||||
for (rank, suit) in Rank::iter_all()
|
||||
for (rank, suit) in Rank::all()
|
||||
.into_iter()
|
||||
.zip_cartesian(Suit::iter_all().into_iter())
|
||||
{
|
||||
|
||||
@@ -113,11 +113,11 @@ mod tests {
|
||||
assert_eq!(Pair::new(Card::make_joker(), Card::make_joker()), None);
|
||||
|
||||
// TEST: Non pair tests.
|
||||
for (c1, c2) in Rank::iter_all()
|
||||
for (c1, c2) in Rank::all()
|
||||
.into_iter()
|
||||
// Generate tuples (r1, r2) where r1 != r2
|
||||
.flat_map(|r1| {
|
||||
Rank::iter_all()
|
||||
Rank::all()
|
||||
.into_iter()
|
||||
.filter(move |&r2| r2 != r1)
|
||||
.map(move |r2| (r1, r2))
|
||||
|
||||
@@ -150,18 +150,22 @@ mod tests {
|
||||
// Triple::2.
|
||||
assert_eq!(
|
||||
trip.2, card,
|
||||
"Expected the highest card of the triple ({}) to be the sole PlayingCard ({card})",
|
||||
trip.2
|
||||
"Expected Triple::2 to be the sole PlayingCard"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
trip.high_card(),
|
||||
card,
|
||||
"Expected Triple::HighCard = card"
|
||||
);
|
||||
}
|
||||
|
||||
// Iterate over all pairs of cards with similar ranks
|
||||
for (c1, c2) in Rank::iter_all().into_iter().flat_map(|r| {
|
||||
for (c1, c2) in Rank::all().into_iter().flat_map(|r| {
|
||||
r.cards().into_iter().zip_cartesian(r.cards().into_iter())
|
||||
}) {
|
||||
let trip = Triple::new(c1, c2, joker);
|
||||
// TEST: Any two similar rank cards with 1 joker are a
|
||||
// Triple.
|
||||
// TEST: Any two similar rank cards with 1 joker is a Triple.
|
||||
assert_ne!(
|
||||
trip, None,
|
||||
"Expected ({c1}, {c2}, Joker) to make a Triple"
|
||||
@@ -190,13 +194,16 @@ mod tests {
|
||||
trip.1,
|
||||
trip.2,
|
||||
);
|
||||
|
||||
// TEST: Expect triple high card to be the highest card of c1,c2.
|
||||
assert_eq!(trip.high_card(), c2);
|
||||
}
|
||||
|
||||
// Iterate over all pairs of cards with differing ranks
|
||||
for (c1, c2) in Rank::iter_all()
|
||||
for (c1, c2) in Rank::all()
|
||||
.into_iter()
|
||||
.flat_map(|r1| {
|
||||
Rank::iter_all()
|
||||
Rank::all()
|
||||
.into_iter()
|
||||
.filter(move |&r2| r2 != r1)
|
||||
.map(move |r2| (r1, r2))
|
||||
@@ -246,6 +253,10 @@ mod tests {
|
||||
|
||||
let [c1, c2, c3] = ordered([c1, c2, c3]);
|
||||
|
||||
// TEST: Triple::high_card should be c3 (the highest card of the
|
||||
// ordered set).
|
||||
assert_eq!(trip.high_card(), c3);
|
||||
|
||||
// TEST: If a triple is formed of 3 playing cards, they are
|
||||
// ordered s.t. Triple::2 > Triple::1 > Triple::0.
|
||||
assert_eq!(
|
||||
@@ -286,18 +297,11 @@ mod tests {
|
||||
let joker = Card::make_joker();
|
||||
|
||||
for (t1, t2) in
|
||||
// Iterate through all pairs of differing ranks (r1, r2) where r2 >
|
||||
// r1
|
||||
Rank::iter_all()
|
||||
// Generate an exhaustive set of triples where rank(t1) <
|
||||
// rank(t2)
|
||||
Rank::all()
|
||||
.into_iter()
|
||||
.flat_map(|r1| {
|
||||
Rank::iter_all()
|
||||
.into_iter()
|
||||
.filter(move |&r2| r2 > r1)
|
||||
.map(move |r2| (r1, r2))
|
||||
})
|
||||
// Generate an exhaustive set of triples where rank(t1) <
|
||||
// rank(t2)
|
||||
.flat_map(move |r1| r1.iter_rest().map(move |r2| (r1, r2)))
|
||||
.flat_map(|(r1, r2)| {
|
||||
exhaustive_triples_rank(r1)
|
||||
.zip_cartesian(exhaustive_triples_rank(r2))
|
||||
@@ -310,39 +314,38 @@ mod tests {
|
||||
}
|
||||
|
||||
// So high card rank determines ordering between differing ranked
|
||||
// triples.
|
||||
// triples. Let's test what happens within triples of the same high
|
||||
// card rank.
|
||||
|
||||
// Iterate through all ranks
|
||||
for rank in Rank::iter_all() {
|
||||
for rank in Rank::all() {
|
||||
let cards = rank.cards();
|
||||
|
||||
// All possible 2 joker triples for this rank.
|
||||
let two_joker_triples = cards
|
||||
.map(|c| Triple::new(c, joker, joker))
|
||||
.map(Option::unwrap);
|
||||
|
||||
for triple in
|
||||
exhaustive_triples_rank(rank).filter(|x| x.count_jokers() < 2)
|
||||
{
|
||||
for two_joker_trip in two_joker_triples {
|
||||
// TEST: A two joker triple is always worse than any triples
|
||||
// in the same rank that have at most 1 joker.
|
||||
assert!(two_joker_trip < triple);
|
||||
}
|
||||
}
|
||||
|
||||
let [diamond, _, _, spade] = cards;
|
||||
|
||||
// NOTE: By new test this should be safe to unwrap.
|
||||
let minima = Triple::new(diamond, joker, joker).unwrap();
|
||||
let maxima = Triple::new(spade, spade, spade).unwrap();
|
||||
|
||||
// All possible 2 joker triples for this rank.
|
||||
let two_joker_triples = cards
|
||||
.map(|c| Triple::new(c, joker, joker))
|
||||
.map(Option::unwrap);
|
||||
|
||||
for triple in exhaustive_triples_rank(rank) {
|
||||
// TEST: The lowest possible triple in a rank is a diamond + 2
|
||||
// jokers
|
||||
assert!(minima <= triple);
|
||||
// TEST: The highest possible triple in a rank is 3 spades
|
||||
assert!(maxima >= triple);
|
||||
|
||||
if triple.count_jokers() < 2 {
|
||||
for two_joker_trip in two_joker_triples {
|
||||
// TEST: A two joker triple is always worse than any
|
||||
// triples in the same rank that have at most 1 joker.
|
||||
assert!(two_joker_trip < triple);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -350,8 +353,8 @@ mod tests {
|
||||
#[test]
|
||||
fn footstool() {
|
||||
let triples = exhaustive_triples_deck().collect::<Vec<_>>();
|
||||
for t1 in &triples {
|
||||
for t2 in &triples {
|
||||
for (ind, t1) in triples.iter().enumerate() {
|
||||
for t2 in &triples[ind..] {
|
||||
// TEST: Expected footstool condition
|
||||
test_footstool(t1, t2);
|
||||
}
|
||||
|
||||
@@ -19,18 +19,17 @@ where
|
||||
I::Item: Copy,
|
||||
{
|
||||
/// Exhaustive coupling of two iterators.
|
||||
/// For each x in `self`: for each y in `b`: yield (x, y).
|
||||
/// b: B must implement `Clone`.
|
||||
fn zip_cartesian<B>(
|
||||
/// For each x in `self`: for each y in `other`: yield (x, y).
|
||||
fn zip_cartesian<Other>(
|
||||
self,
|
||||
b: B,
|
||||
) -> impl Iterator<Item = (Self::Item, B::Item)> + Clone
|
||||
other: Other,
|
||||
) -> impl Iterator<Item = (Self::Item, Other::Item)> + Clone
|
||||
where
|
||||
B::Item: Copy,
|
||||
B: Iterator + Clone,
|
||||
Other::Item: Copy,
|
||||
Other: Iterator + Clone,
|
||||
{
|
||||
self.flat_map(move |a_item| {
|
||||
b.clone().map(move |b_item| (a_item, b_item))
|
||||
other.clone().map(move |b_item| (a_item, b_item))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user