Well I am not able to give you an analytical answer, but this question just screamed to be programmed. Now I am sorry that I haven't used Matlab ( which would be much less code ) but I implemented it in c++. The code is simply your rules implemented in my not so good c++. I used g++ 4.6.3 on Ubuntu 12.04. If you run the code, it will print the results and also write the pairs (number of dices | avg. number of throws) in out.txt. The result is plotted attached, plotted with gnuplot for number of dices $\leq$ 40.
See the results here as I dont know much about gnuplot and couldn't upload a .ps to MathSE I had to upload it there. For every number of dices, 10000 experiments have been player.
The code is probably terrible slow so everyone feel free to improve it ;)
This here does the same computation for number of dices $\leq 400$ but only 1000 experiments each.
Maybe you can use this to varify any of the formulas.
yahtzee.cpp:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <vector>
#include <fstream>
using namespace std;
int hasYourNumber(vector<int>,int );
int sum(int* ,int );
int mostFrequent ( vector<int> );
vector<int>throwDice(int);
int role();
void playYahtzee(int,int,bool);
int main ( void ) {
int REP = 10000; // Number of repeting the experiment
bool echo = 0; // print information (yes 1,no 0)
for (int numberOfDices=1;numberOfDices<40;numberOfDices++){
playYahtzee(numberOfDices,REP,echo);
}
return 0;
}
void playYahtzee(int N,int REP,bool echo){// N dices with 6 faces each;
srand( time(NULL) ); // initialize random generator
int* throws = new int[REP]; // save number of throws for each experiment
vector <int> dices; // save dices that came up in one throw inside this, vector just for size(), my way...
for (int k = 0;k<REP;k++){
bool first = true; // is it the first throw?
int AmountOfYourNumber = 0; // how often as our number occured
int yourNumber = -1; // whats your number
int numberOfThrows = 0; // how often have we been throwing in this round
while (AmountOfYourNumber<N){ // finish if our number has occured N times
numberOfThrows++;
dices.clear();
dices = throwDice(N-AmountOfYourNumber); // place random integers between 1 and 6 inside
if (first){
yourNumber = mostFrequent(dices);// choose the most frequent number
AmountOfYourNumber += hasYourNumber(dices,yourNumber); // how often has it your number
first = false;
}else{
AmountOfYourNumber += hasYourNumber(dices,yourNumber);
}
if (echo){ // some output mostly for debugging
printf("Your number is %d and it has occured %d times in throw 1 to %d.\n",
yourNumber, AmountOfYourNumber,numberOfThrows);
printf("\tNumbers in this throw:\n\t");
for (int i=0;i<dices.size();i++) printf("%d\t",dices[i]);
printf("\n \n");
}
}
throws[k] = numberOfThrows; // save number of throws
}
double avg = double(sum(throws,REP))/double(REP); // calculate average
printf("Average number (over %d repetitions) of attempts, when playing with %d dices equals %g\n",REP,N,avg);
ofstream output;
output.open ("out.txt",fstream::app);
output << N << " " << avg<< endl;
output.close();
}
int sum(int* throws,int N){ // = sum_i throws[i]
int s = 0;
for (int i=0;i<N;i++) s+= throws[i];
return s;
}
int hasYourNumber(vector<int> dices,int yourNumber){ // calculates how often yournumber is in dices
int N = 0;
for (int i=0;i<dices.size();i++){
if ( dices[i] == yourNumber) N++;
}
return N;
}
int mostFrequent ( vector<int> dices){ // which is the most frequent number, takes first best
int freq [6] = {0,0,0,0,0,0};
for (int i=0;i<dices.size();i++){
freq[dices[i]-1]++;
}
int yourNumber = -1;
int max = 0;
for (int i=0;i<6;i++){
if (freq[i]>max) {yourNumber = i+1 ; max = freq[i];}
}
return yourNumber;
}
vector <int> throwDice(int M){ // throws M dices
vector <int> dices;
for (int i=0;i<M;i++) dices.push_back(role());
return dices;
}
int role(){ // throws one dice
return rand() % 6 +1;
}