问题
Background
For those of you not familiar with Cribbage, it uses a standard 52 card deck with aces being always low. A player's hand consists of 4 cards, and there is 1 turn card that all players can use to help score their hand.
So for a little practice problem for myself, I wrote a we bit of VBA and had all ~12.9 million possible scoring combination printed in an excel sheet. I assigned each card an integer 1 to 52 and set it up so that each suit is a sequential block of 13 cards. 1-13 = Clubs, 14-26 = Diamonds, 27-39 = Hearts, and 40-52 = Spades. I dealt each card into its own separate cell in adjacent columns. Ie B1:E1
is the hand and F1
is the turn. The hand (B1:E1) is also organised in the lowest card ID number (not card value) is on the left and the highest is on the right.
Then I started tinkering with how to score any given hand using excel formulas. So far I have been able to check for a 4 and 5 card flush (flush=all cards same suit), Pairs (which includes three and four of a kind), 15 combinations (2,3,4 and 5 cards). What I have outstanding are checking for straights and 1 point for the knob (Jack in hand matches suit of turn). Checking the later should be easy enough.
A straight in Cribbage is the largest sequence/series of cards. You cannot go around the clock, (ie 3,2,1,13,12 or 3,2,A,K,Q). You cannot count the two 4 card straights of a 5 card straight as only the largest is counted. However you can count double straight such as 2,2,3,4,5 or 2,3,4,4,5. Each card in a straight counts as 1 point.
Problem
I am not sure how to identify a four card straight when there is a double/pair of one of the cards. ei. 2,3,4,5,16 or 2,3,4,5,15 or 2,3,4,5,18. (Face value: 2,3,3,4,5 or 2,2,3,4,5 or 2,3,4,5,5)
What have I tried so far
I was able to figure out the 5 card straight easy enough using: MOD to convert the cards to face value and strip the suit, AGGREGATE to sort the cards, then checking if each card was the appropriate difference from the first card. The formula is a bit unwieldy but works:
=AND(
AGGREGATE(15,6,MOD(B1:F1,13),2)-AGGREGATE(15,6,MOD(B1:F1,13),1)=1,
AGGREGATE(15,6,MOD(B1:F1,13),3)-AGGREGATE(15,6,MOD(B1:F1,13),1)=2,
AGGREGATE(15,6,MOD(B1:F1,13),4)-AGGREGATE(15,6,MOD(B1:F1,13),1)=3,
AGGREGATE(15,6,MOD(B1:F1,13),5)-AGGREGATE(15,6,MOD(B1:F1,13),1)=4
)*5
So then I started on the 4 card sequence. I am able to get it to work as long as it not a double straight.
=OR(AND(AGGREGATE(15,6,MOD(B1:F1,13),2)-AGGREGATE(15,6,MOD(B1:F1,13),1)=1,
AGGREGATE(15,6,MOD(B1:F1,13),3)-AGGREGATE(15,6,MOD(B1:F1,13),1)=2,
AGGREGATE(15,6,MOD(B1:F1,13),4)-AGGREGATE(15,6,MOD(B1:F1,13),1)=3,
AGGREGATE(15,6,MOD(B1:F1,13),5)-AGGREGATE(15,6,MOD(B1:F1,13),1)<>4),
AND(AGGREGATE(14,6,MOD(B1:F1,13),2)-AGGREGATE(14,6,MOD(B1:F1,13),1)=-1,
AGGREGATE(14,6,MOD(B1:F1,13),3)-AGGREGATE(14,6,MOD(B1:F1,13),1)=-2,
AGGREGATE(14,6,MOD(B1:F1,13),4)-AGGREGATE(14,6,MOD(B1:F1,13),1)=-3,
AGGREGATE(14,6,MOD(B1:F1,13),5)-AGGREGATE(14,6,MOD(B1:F1,13),1)<>-4))
*4
Or to break it out into its separate checks.
=AND(
AGGREGATE(15,6,MOD(B1:F1,13),2)-AGGREGATE(15,6,MOD(B1:F1,13),1)=1,
AGGREGATE(15,6,MOD(B1:F1,13),3)-AGGREGATE(15,6,MOD(B1:F1,13),1)=2,
AGGREGATE(15,6,MOD(B1:F1,13),4)-AGGREGATE(15,6,MOD(B1:F1,13),1)=3,
AGGREGATE(15,6,MOD(B1:F1,13),5)-AGGREGATE(15,6,MOD(B1:F1,13),1)<>4
)*4
AND(
AGGREGATE(14,6,MOD(B1:F1,13),2)-AGGREGATE(14,6,MOD(B1:F1,13),1)=-1,
AGGREGATE(14,6,MOD(B1:F1,13),3)-AGGREGATE(14,6,MOD(B1:F1,13),1)=-2,
AGGREGATE(14,6,MOD(B1:F1,13),4)-AGGREGATE(14,6,MOD(B1:F1,13),1)=-3,
AGGREGATE(14,6,MOD(B1:F1,13),5)-AGGREGATE(14,6,MOD(B1:F1,13),1)<>-4
)*4
Question
How to find a four card straight with a double/pair using excel formulas preferably in a single cell eventually. I do not mind multiple cells for building and understanding the formula.
Is there a better way to identify a straight using excel formulas?
I am hoping to build on the concept for 4 card straight, when figured out, to look after 3 card straights.
Sample Data
| B | C | D | E | F |
+---+---+---+---+----+
| 2 | 3 | 4 | 5 | 14 | <= 5 card straight
| 2 | 3 | 4 | 5 | 16 | <= 2 X 4 card straight
| 2 | 3 | 4 | 5 | 15 | <= 2 X 4 card straight
| 2 | 3 | 4 | 5 | 18 | <= 2 X 4 card straight
| 2 | 3 | 4 | 20| 5 | <= 1 X 4 card straight
| 2 | 3 | 4 | 8 | 10 | <= Not a straight
Excel Version
I am running excel 2013
回答1:
We can use SUMPRODUCT with AGGREGATE:
=IF(SUMPRODUCT(--(AGGREGATE(14,7,MOD(B1:F1-1,13)+1,{1,2,3,4})-AGGREGATE(14,7,MOD(B1:F1-1,13)+1,{2,3,4,5})=1))=4,"5 card straight",
IF(AND(SUMPRODUCT(--(AGGREGATE(14,7,MOD(B1:F1-1,13)+1,{1,2,3,4})-AGGREGATE(14,7,MOD(B1:F1-1,13)+1,{2,3,4,5})=1))=3,AGGREGATE(14,7,MOD(B1:F1-1,13)+1,1)-AGGREGATE(15,7,MOD(B1:F1-1,13)+1,1)=3),"2 X 4 card straight",
IF(AND(SUMPRODUCT(--(AGGREGATE(14,7,MOD(B1:F1-1,13)+1,{1,2,3,4})-AGGREGATE(14,7,MOD(B1:F1-1,13)+1,{2,3,4,5})=1))=3,OR(AGGREGATE(14,7,MOD(B1:F1-1,13)+1,2)-AGGREGATE(15,7,MOD(B1:F1-1,13)+1,1)=3,AGGREGATE(14,7,MOD(B1:F1-1,13)+1,1)-AGGREGATE(15,7,MOD(B1:F1-1,13)+1,2)=3)),"1 X 4 card straight","Not a Straight")))
来源:https://stackoverflow.com/questions/62880243/finding-a-straight-in-a-cribbage