02-12-2015, 06:11 PM
This has come up and some numbers have been given...I decided to write some code and see what the results looked like.
The code:
package pinochle;
import tools.MersenneTwisterFast;
public class SimpleDealingTest {
MersenneTwisterFast mt = new MersenneTwisterFast();
public void test() {
int[] counts = new int[3];
int[] numRounds = new int[6];
for (int myLength=4; myLength<=9; myLength++) {
for (int i=0; i<6; i++)
numRounds[i] = 0;
for (int aCase=1; aCase<=1000000; aCase++) {
// re-initialize
int whoseCard = 0;
for (int i=0; i<3; i++)
counts[i] = 0;
// deal
double lengthOut = 20.0 - myLength;
double cardsOut = 60.0;
do {
whoseCard = (whoseCard+1) % 3;
double prob = lengthOut / cardsOut;
cardsOut--;
if (mt.nextDouble() <= prob) {
counts[whoseCard]++;
lengthOut--;
}
}
while ((int) lengthOut > 0);
//analyze
int shortest = Math.min(counts[2], Math.min(counts[0], counts[1]));
//System.out.println(shortest + " " + Arrays.toString(counts));
numRounds[shortest]++;
}
//report
System.out.print("My length= " + myLength + "; ");
for (int i=0; i<=5; i++)
System.out.print(i + " rounds= " + numRounds[i] + "; ");
System.out.println();
}
}
public static void main(String[] args) {
SimpleDealingTest deal = new SimpleDealingTest();
deal.test();
}
}
The heart of the code is lines 23-34. In English, what's going on is, given I have myLength cards in the suit, the rest of the deck has (20 - myLength) cards in it, called lengthOut. The probability that the top card is in the right suit is lengthOut/cardsOut, so draw between 0 and 1. If the result is less than or equal to lengthOut/cardsOut, then it's the right suit, and we track who got it. (That's what whoseCard is for.) Continue until the length in the key suit reaches 0.
That deals the key suit, and I believe does so correctly. The rest is simple counting. If the SHORTEST length in the key suit is N, then N rounds will NOT be ruffed. The way I binned things, I'm giving the exact count that N rounds will not be ruffed. If you want to know, what's the probability that the 4th ace of a suit will cash (not get ruffed) then you need to add the "4 rounds" and "5 rounds" counts. Here are the results:
My length= 4; 0 rounds= 1248; 1 rounds= 16180; 2 rounds= 87860; 3 rounds= 268955; 4 rounds= 439051; 5 rounds= 186706;
My length= 5; 0 rounds= 2277; 1 rounds= 26409; 2 rounds= 128228; 3 rounds= 342382; 4 rounds= 430936; 5 rounds= 69768;
My length= 6; 0 rounds= 4074; 1 rounds= 41914; 2 rounds= 182242; 3 rounds= 413043; 4 rounds= 358727; 5 rounds= 0;
My length= 7; 0 rounds= 6921; 1 rounds= 65202; 2 rounds= 250366; 3 rounds= 466177; 4 rounds= 211334; 5 rounds= 0;
My length= 8; 0 rounds= 12055; 1 rounds= 99216; 2 rounds= 332096; 3 rounds= 475138; 4 rounds= 81495; 5 rounds= 0;
My length= 9; 0 rounds= 20275; 1 rounds= 147854; 2 rounds= 420740; 3 rounds= 411131; 4 rounds= 0; 5 rounds= 0;
So when I have a 5 card suit, it's just about smack-on 50% that the 4th ace is a trick. The counting/sorting stuff looks fine; the RNG is solid. (It's on the web at
http://www.google.com/url?sa=t&rct=j&q=&...0519,d.aWw
or just search for MersenneTwisterFast.java)
I believe the draw logic is sound, as well; it's properly handling each card in the deck, one at a time, and tracking the player to get the card properly. So I believe this is correct code...but if I've got something wrong, I will fix it. Feel free to copy the code and play with it yourself; it's rather simple code. Note that it's relying on my personal package structure, but that's trivial to adjust. Java's free, and I just use Eclipse for my IDE.
The code:
package pinochle;
import tools.MersenneTwisterFast;
public class SimpleDealingTest {
MersenneTwisterFast mt = new MersenneTwisterFast();
public void test() {
int[] counts = new int[3];
int[] numRounds = new int[6];
for (int myLength=4; myLength<=9; myLength++) {
for (int i=0; i<6; i++)
numRounds[i] = 0;
for (int aCase=1; aCase<=1000000; aCase++) {
// re-initialize
int whoseCard = 0;
for (int i=0; i<3; i++)
counts[i] = 0;
// deal
double lengthOut = 20.0 - myLength;
double cardsOut = 60.0;
do {
whoseCard = (whoseCard+1) % 3;
double prob = lengthOut / cardsOut;
cardsOut--;
if (mt.nextDouble() <= prob) {
counts[whoseCard]++;
lengthOut--;
}
}
while ((int) lengthOut > 0);
//analyze
int shortest = Math.min(counts[2], Math.min(counts[0], counts[1]));
//System.out.println(shortest + " " + Arrays.toString(counts));
numRounds[shortest]++;
}
//report
System.out.print("My length= " + myLength + "; ");
for (int i=0; i<=5; i++)
System.out.print(i + " rounds= " + numRounds[i] + "; ");
System.out.println();
}
}
public static void main(String[] args) {
SimpleDealingTest deal = new SimpleDealingTest();
deal.test();
}
}
The heart of the code is lines 23-34. In English, what's going on is, given I have myLength cards in the suit, the rest of the deck has (20 - myLength) cards in it, called lengthOut. The probability that the top card is in the right suit is lengthOut/cardsOut, so draw between 0 and 1. If the result is less than or equal to lengthOut/cardsOut, then it's the right suit, and we track who got it. (That's what whoseCard is for.) Continue until the length in the key suit reaches 0.
That deals the key suit, and I believe does so correctly. The rest is simple counting. If the SHORTEST length in the key suit is N, then N rounds will NOT be ruffed. The way I binned things, I'm giving the exact count that N rounds will not be ruffed. If you want to know, what's the probability that the 4th ace of a suit will cash (not get ruffed) then you need to add the "4 rounds" and "5 rounds" counts. Here are the results:
My length= 4; 0 rounds= 1248; 1 rounds= 16180; 2 rounds= 87860; 3 rounds= 268955; 4 rounds= 439051; 5 rounds= 186706;
My length= 5; 0 rounds= 2277; 1 rounds= 26409; 2 rounds= 128228; 3 rounds= 342382; 4 rounds= 430936; 5 rounds= 69768;
My length= 6; 0 rounds= 4074; 1 rounds= 41914; 2 rounds= 182242; 3 rounds= 413043; 4 rounds= 358727; 5 rounds= 0;
My length= 7; 0 rounds= 6921; 1 rounds= 65202; 2 rounds= 250366; 3 rounds= 466177; 4 rounds= 211334; 5 rounds= 0;
My length= 8; 0 rounds= 12055; 1 rounds= 99216; 2 rounds= 332096; 3 rounds= 475138; 4 rounds= 81495; 5 rounds= 0;
My length= 9; 0 rounds= 20275; 1 rounds= 147854; 2 rounds= 420740; 3 rounds= 411131; 4 rounds= 0; 5 rounds= 0;
So when I have a 5 card suit, it's just about smack-on 50% that the 4th ace is a trick. The counting/sorting stuff looks fine; the RNG is solid. (It's on the web at
http://www.google.com/url?sa=t&rct=j&q=&...0519,d.aWw
or just search for MersenneTwisterFast.java)
I believe the draw logic is sound, as well; it's properly handling each card in the deck, one at a time, and tracking the player to get the card properly. So I believe this is correct code...but if I've got something wrong, I will fix it. Feel free to copy the code and play with it yourself; it's rather simple code. Note that it's relying on my personal package structure, but that's trivial to adjust. Java's free, and I just use Eclipse for my IDE.