Brydżowe tablice prawdopodobieństwa/kod
Z Wikiźródeł, repozytorium wolnych materiałów źródłowych
| ←Brydżowe tablice prawdopodobieństwa | Brydżowe tablice prawdopodobieństwa Kod źródłowy |
||
| Poniższy program w języku C++ posłużył do wygenerowania tablic w tekście Brydżowe tablice prawdopodobieństwa. |
#include <stdio.h> #include <string.h> #include <stdlib.h> //Liczba prób w metodzie Monte Carlo const IL_PROB=1000000; //Klasa opisująca rozkład ręki class rozklad { protected: int wart[4]; int poziom; int licznik; public: rozklad(int *wart,int poziom); virtual void inkrementuj(int *wart); double prawdopodobienstwo(int il_prob); char* wez_kod(); virtual void dopisz_HTML(int il_prob); virtual ~rozklad(); }; //Klasa opisująca węzeł drzewa (np. rozkład 5-4-x-x) class wezel: public rozklad { rozklad *dzieci[14]; public: wezel(int *wart,int poziom); virtual void inkrementuj(int *wart); virtual void dopisz_HTML(int il_prob); virtual ~wezel(); }; //Klasa rozklad rozklad::rozklad(int *wart,int poziom): poziom(poziom), licznik(0) { memcpy(this->wart,wart,sizeof(this->wart)); } void rozklad::inkrementuj(int *) { licznik++; } double rozklad::prawdopodobienstwo(int il_prob) { return double(licznik)/il_prob; } char* rozklad::wez_kod() { static char kod[13]; kod[0]=0; for (int n=0;n<=3;n++) if (n<=poziom) sprintf(kod+strlen(kod),"-%d",wart[n]); else strcat(kod,"-x"); return kod+1; } void rozklad::dopisz_HTML(int il_prob) { double p=prawdopodobienstwo(il_prob)*100; if (p<0.01) return; int poz=poziom==3 ? 2 : poziom; printf( "\t\t<tr>\n" ); if (poz>0) if (poz>1) printf("\t\t\t<td colspan=\"%d\" width=\"%d%%\"> </td>\n", poz,poz*10); else printf("\t\t\t<td width=\"10%%\"> </td>\n"); if (poz<2) printf("\t\t\t<td colspan=\"%d\" width=\"%d%%\" align=\"left\">%s</td>\n", 3-poz,(3-poz)*10,wez_kod()); else printf("\t\t\t<td width=\"10%%\" align=\"left\">%s</td>\n",wez_kod()); int ip=int(p*2+0.5); printf( "\t\t\t<td align=\"center\">%2.2f%%</td>\n" "\t\t\t<td align=\"left\"><table border=\"0\" width=\"100%%\"><tr>\n" "\t\t\t\t<td width=\"%d%%\" bgcolor=\"#FF0000\"> </td>\n" "\t\t\t\t<td> </td>\n" "\t\t\t</tr></table></td>\n" "\t\t</tr>\n", p, ip ? ip : 1 ); } rozklad::~rozklad() { } //Klasa wezel wezel::wezel(int *wart,int poziom): rozklad(wart,poziom) { int suma=0; for (int k=0;k<=poziom;k++) suma+=wart[k]; for (int n=0;n<=13;n++) { wart[poziom+1]=n; dzieci[n]=poziom==2 ? suma+n==13 ? new rozklad(wart,poziom+1) : NULL : suma+n<=13 ? (rozklad*)new wezel(wart,poziom+1) : NULL; } } void wezel::inkrementuj(int *wart) { rozklad::inkrementuj(wart); dzieci[wart[poziom+1]]->inkrementuj(wart); } void wezel::dopisz_HTML(int il_prob) { int il_dzieci=0; for (int n=0;n<=13;n++) if (dzieci[n]!=NULL && dzieci[n]->prawdopodobienstwo(il_prob)>0) il_dzieci++; if (il_dzieci!=1) rozklad::dopisz_HTML(il_prob); for (int n=0;n<=13;n++) if (dzieci[n]!=NULL) dzieci[n]->dopisz_HTML(il_prob); } wezel::~wezel() { for (int n=0;n<=13;n++) if (dzieci[n]!=NULL) delete dzieci[n]; } //Dla qsort int por(const void *a,const void *b) { return *(const int *)b-*(const int *)a; } wezel *drzewa[14]; //Wypisywanie na ekran tabelki punktów Miltona void pisz_miltona(char *tekst,int *MP,int min,int max,int il_prob) { printf( "<div align=\"left\">\n" "\t<table width=\"100%%\" border=\"1\">\n" "\t\t<tr>\n" "\t\t\t<th width=\"10%%\" align=\"center\">Ilość punktów Miltona %s</th>\n" "\t\t\t<th width=\"25%%\" align=\"center\">Prawdopodobieństwo zdobycia dokładnie takiej liczby punktów</th>\n" "\t\t\t<th width=\"20%%\" align=\"center\">Wykres prawdopodobieństwa</th>\n" "\t\t\t<th width=\"25%%\" align=\"center\">Prawdopodobieństwo zdobycia co najmniej takiej liczby punktów</th>\n" "\t\t\t<th width=\"20%%\" align=\"center\">Wykres prawdopodobieństwa</th>\n" "\t\t</tr>\n",tekst ); for (int n=min;n<=max;n++) { int suma=0; for (int m=n;m<=40;m++) suma+=MP[m]; double p1=double(MP[n])/il_prob*100; int ip1=int(p1*10+0.5); double p2=double(suma)/il_prob*100; int ip2=int(p2+0.4999); printf( "\t\t<tr>\n" "\t\t\t<td width=\"34%%\" align=\"center\">%d</td>\n" "\t\t\t<td width=\"33%%\" align=\"center\">%2.2lf%%</td>\n" "\t\t\t<td align=\"left\"><table border=\"0\" width=\"100%%\"><tr>\n" "\t\t\t\t<td width=\"%d%%\" bgcolor=\"#FF0000\"> </td>\n" "\t\t\t\t<td> </td>\n" "\t\t\t</tr></table></td>\n" "\t\t\t<td width=\"33%%\" align=\"center\">%2.2lf%%</td>\n" "\t\t\t<td align=\"left\"><table border=\"0\" width=\"100%%\"><tr>\n" "\t\t\t\t<td width=\"%d%%\" bgcolor=\"#FF0000\"> </td>\n" "\t\t\t\t<td> </td>\n" "\t\t\t</tr></table></td>\n" "\t\t</tr>\n", n, p1,ip1 ? ip1 : 1, p2,ip2 ? ip2 : 1 ); } printf( "\t</table>\n" "</div>\n" ); } //Symulacja miliona rozdań metodą Monte Carlo void reka() { int n; for (n=0;n<=13;n++) { int wart[4]; wart[0]=n; drzewa[n]=new wezel(wart,0); } int MP[41]; memset(MP,0,sizeof(MP)); int MP_pary[41]; memset(MP_pary,0,sizeof(MP_pary)); int renons=0; int cztery_pasy=0; int mozemy_grac=0; int obydwie_moga_grac=0; int zatrzymania[5]; memset(zatrzymania,0,sizeof(zatrzymania)); //Symulacja for (n=0;n<IL_PROB;n++) { int wart[4][4]; memset(wart,0,sizeof(wart)); int punkty[4]; memset(punkty,0,sizeof(punkty)); //Rozdawanie unsigned char karty[52]; memset(karty,255,sizeof(karty)); for (int m=0;m<52;m++) { int k; do { k=rand()%52; } while (karty[k]!=255); karty[k]=(unsigned char)(m&3); wart[m&3][k&3]++; static int pkt[13]={4,3,2,1,0,0,0,0,0,0,0,0,0}; punkty[m&3]+=pkt[k>>2]; } //Sytuacje if (punkty[0]<12 && punkty[1]<12 && punkty[2]<12 && punkty[3]<12) cztery_pasy++; int moga_grac[2]={0,0}; MP_pary[punkty[0]+punkty[2]]++; MP_pary[punkty[1]+punkty[3]]++; for (int r=0;r<4;r++) { MP[punkty[r]]++; if (punkty[r]>=12 && punkty[(r+2)%4]>=7) { mozemy_grac++; moga_grac[r&1]=1; } int zatrzyman=0; for (int kol=0;kol<=3;kol++) if (karty[kol]==r) //ma asa zatrzyman++; else if (karty[kol+4]==r && wart[r][kol]>=2) //ma zatrzymanie na królu zatrzyman++; else if (karty[kol+8]==r && wart[r][kol]>=3) //ma zatrzymanie na damie zatrzyman++; zatrzymania[zatrzyman]++; qsort(wart+r,4,sizeof(wart[0][0]),por); if (wart[r][3]==0) renons++; drzewa[wart[r][0]]->inkrementuj(wart[r]); } if (moga_grac[0] && moga_grac[1]) obydwie_moga_grac++; } //Wyświetlanie wyników printf( "<div align=\"left\">\n" "\t<table width=\"100%%\" border=\"1\">\n" "\t\t<tr>\n" "\t\t\t<th width=\"30%%\" colspan=\"3\" align=\"center\">Rozkład ręki</th>\n" "\t\t\t<th width=\"20%%\" align=\"center\">Prawdopodobieństwo</th>\n" "\t\t\t<th width=\"50%%\" align=\"center\">Wykres prawdopodobieństwa</th>\n" "\t\t</tr>\n" ); for (n=0;n<=13;n++) { drzewa[n]->dopisz_HTML(IL_PROB*4); delete drzewa[n]; } printf( "\t</table>\n" "</div>\n" ); printf("Prawdopodobieństwo braku zatrzymań (na asie, królu lub damie) w jakimkolwiek kolorze = %2.2lf%%<br>\n", double(zatrzymania[0])/(IL_PROB*4)*100 ); printf("Prawdopodobieństwo zatrzymania w tylko jednym kolorze = %2.2lf%%<br>\n", double(zatrzymania[1])/(IL_PROB*4)*100 ); printf("Prawdopodobieństwo zatrzymania w dwóch kolorach = %2.2lf%%<br>\n", double(zatrzymania[2])/(IL_PROB*4)*100 ); printf("Prawdopodobieństwo zatrzymania w trzech kolorach = %2.2lf%%<br>\n", double(zatrzymania[3])/(IL_PROB*4)*100 ); printf("Prawdopodobieństwo zatrzymania we wszystkich kolorach = %2.2lf%%<br>\n", double(zatrzymania[4])/(IL_PROB*4)*100 ); printf("Prawdopodobieństwo posiadania renonsu = %2.2lf%%<br>\n", double(renons)/(IL_PROB*4)*100 ); printf("Prawdopodobieństwo że nikt nie ma 12 punktów = %2.2lf%%<br>\n", double(cztery_pasy)/IL_PROB*100 ); printf("Prawdopodobieństwo że ma się co najmniej 12 MP, a partner co najmniej 7 MP = %2.2lf%%<br>\n", double(mozemy_grac)/(IL_PROB*4)*100 ); printf("Prawdopodobieństwo że sytuacja taka ma miejsce u obydwu par = %2.2lf%%<br>\n", double(obydwie_moga_grac)/IL_PROB*100 ); pisz_miltona("na ręku",MP,0,27,IL_PROB*4); pisz_miltona("w sumie w parze",MP_pary,3,37,IL_PROB*2); } //Rozkład kart w jednym kolorze u przeciwników void rozklady() { printf( "<div align=\"left\">\n" "\t<table width=\"100%%\" border=\"1\">\n" "\t\t<tr>\n" "\t\t\t<th width=\"10%%\" align=\"center\">Liczba kart</th>\n" "\t\t\t<th width=\"10%%\" align=\"center\">Rozkład</th>\n" "\t\t\t<th width=\"10%%\" align=\"center\">Prawdopodobieństwo</th>\n" "\t\t\t<th width=\"70%%\" align=\"center\">Wykres prawdopodobieństwa</th>\n" "\t\t</tr>\n" ); int rozklad[14]; for (int il=1;il<=13;il++) { memset(rozklad,0,sizeof(rozklad)); for (int n=(1<<il)-1;n>=0;n--) { int lewy=0; for (int m=0;m<il;m++) lewy+=(n>>m)&1; rozklad[lewy]++; } printf( "\t\t<tr>\n" "\t\t\t<td align=\"center\" rowspan=\"%d\">%d</td>\n", il+1, il ); for (int k=0;k<=il;k++) { double p=double(rozklad[k])/(1<<il)*100; int ip=int(p*2+0.5); char *kolor=(il & 1) ? "#000080" : "#008000"; if (k) printf("\t\t<tr>\n"); printf( "\t\t\t<td align=\"center\">%d-%d</td>\n" "\t\t\t<td align=\"center\">%2.2f%%</td>\n" "\t\t\t<td align=\"left\"><table border=\"0\" width=\"100%%\"><tr>\n" "\t\t\t\t<td width=\"%d%%\" bgcolor=\"%s\"> </td>\n" "\t\t\t\t<td> </td>\n" "\t\t\t</tr></table></td>\n" "\t\t</tr>\n", k,il-k, p, ip ? ip : 1, kolor ); } } printf( "\t</table>\n" "</div>\n" ); } //Główna procedura void main() { reka(); rozklady(); }

