Advertisement
FractalFusion

Randil's math problem revisited (C++ code)

Jan 21st, 2016
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.72 KB | None | 0 0
  1. //this version updates by bayesian probability instead of using maximum likelihood
  2. #include <iostream>
  3. #include <iomanip>
  4. #include <ctime>
  5. #include <random>
  6. #include <cmath>
  7.  
  8. #define TRIES 5000
  9.  
  10. using namespace std;
  11.  
  12. int main()
  13. {
  14.     mt19937 mersenne(static_cast<unsigned int>(time(0)));
  15.  
  16.     for(int lo=1; lo<=18; lo++)
  17.         for(int hi=lo+1;hi<=19;hi++){
  18.    
  19.             double pr=0.05*hi, pw=0.05*lo;
  20.             double qr=1-pr, qw=1-pw;
  21.  
  22.             double bgreen=pr/pw; //should be greater than 1
  23.             double bred=qr/qw; //should be less than 1
  24.            
  25.             int countsum=0;
  26.             for(int temp=1;temp<=TRIES;temp++){
  27.            
  28.                 unsigned int thenum=mersenne()%10000;
  29.                 unsigned int num[]={thenum/1000, (thenum/100)%10, (thenum/10)%10, thenum%10};
  30.                
  31.                 int flags[10000]{};
  32.                 double digitprobs[40]{};
  33.                
  34.                 double bayesprobs[10000]{};
  35.                 int countsgreen[40]{};
  36.                 int countsred[40]{};
  37.                
  38.                 //first guess
  39.                
  40.                 unsigned int theguess=mersenne()%10000;
  41.                 unsigned int guess[]={theguess/1000, (theguess/100)%10, (theguess/10)%10, theguess%10};
  42.                
  43.                
  44.                 int count=1;
  45.                 while(true){
  46.                     //check if guess matches num
  47.                     int check=1;
  48.                     for(int i=0;i<4;i++)
  49.                         if(guess[i]!=num[i]) {check=0; break;}
  50.                     if(check==1) //match
  51.                         break;
  52.                    
  53.                     //no match
  54.                    
  55.                     //add occurrences
  56.                     for(int i=0;i<4;i++){
  57.                         if(guess[i]==num[i]){
  58.                             //green with prob pr, red with prob qr
  59.                             if(((double) mersenne())/mersenne.max() < pr) //green
  60.                                 countsgreen[10*i+guess[i]]++;
  61.                             else
  62.                                 countsred[10*i+guess[i]]++;
  63.                         }
  64.                         else{
  65.                             //green with prob pw, red with prob qw
  66.                             if(((double) mersenne())/mersenne.max() < pw) //green
  67.                                 countsgreen[10*i+guess[i]]++;
  68.                             else
  69.                                 countsred[10*i+guess[i]]++;
  70.                         }
  71.                     }
  72.                    
  73.                     //set flag so as to not guess it again
  74.                     flags[theguess]=1;
  75.                    
  76.                     //calculate normalized likelihood for each digit
  77.                     for(int i=0;i<40;i++)
  78.                         digitprobs[i]=pow(bgreen,countsgreen[i])*pow(bred,countsred[i]);
  79.                        
  80.                    
  81.                     //calculate normalized likelihood for each 4-digit number
  82.                     //bayesprobs will store the cumulative sum (likelihood function is proportional to bayesian probability function)
  83.                     double cumulative=0;
  84.                     for(int i1=0;i1<10;i1++)
  85.                         for(int i2=0;i2<10;i2++)
  86.                             for(int i3=0;i3<10;i3++)
  87.                                 for(int i4=0;i4<10;i4++){
  88.                                     double s=0;
  89.                                     int fourdigitval=1000*i1+100*i2+10*i3+i4;
  90.                                     if(!flags[fourdigitval]){
  91.                                         s=digitprobs[i1]*digitprobs[10+i2]*digitprobs[20+i3]*digitprobs[30+i4];
  92.                                     }
  93.                                     cumulative+=s;
  94.                                     bayesprobs[fourdigitval]=cumulative;
  95.                                 }
  96.                            
  97.                     //now take a new random number (uniform distribution from 0 to bayesprobs[9999]) and use bayesprobs to determine which number to guess
  98.                     //use halving strategy to find the first number larger than rndnum or equal to bayesprobs[9999]
  99.                     double rndnum=(((double) mersenne())/mersenne.max())*bayesprobs[9999];
  100.                     int min=-1, max=9999;
  101.                     while(max>min+1){
  102.                        
  103.                    
  104.                         int mid=floor((max+min)/2);
  105.                         if(bayesprobs[mid]>rndnum || bayesprobs[mid]==bayesprobs[9999])
  106.                             max=mid;
  107.                         else
  108.                             min=mid;
  109.                     }
  110.                    
  111.                     //set guess to value of max (first number larger than rndnum or equal to bayesprobs[9999])
  112.                    
  113.                     theguess=max;
  114.                     guess[0]=max/1000;
  115.                     guess[1]=(max/100)%10;
  116.                     guess[2]=(max/10)%10;
  117.                     guess[3]=max%10;                   
  118.                
  119.                     count++;
  120.                    
  121.                     if(count>=10002){
  122.                         cout << "failed";
  123.                         exit(1);
  124.                     }
  125.                    
  126.                    
  127.                 }
  128.                
  129.                 countsum+=count;
  130.             }
  131.            
  132.             cout << fixed << setprecision(2) << "Average tries for pr=" << pr << " , pw=" << pw << ": " << ((double) countsum)/TRIES << endl;
  133.         }
  134.     return 0;
  135. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement