Skip to content

Instantly share code, notes, and snippets.

@allenyllee
Last active July 13, 2016 02:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save allenyllee/acdf5af563018e46fe9a to your computer and use it in GitHub Desktop.
Save allenyllee/acdf5af563018e46fe9a to your computer and use it in GitHub Desktop.
There are some simple C function

#There are some simple C function

/**
問題:假設記憶遊戲使用12張牌,6對(112233445566)
    規則為每次翻兩張,相同就保留,不同就蓋回背面
    給六次機會,請問用程式算翻出6對~1對的機率為何?
**/
/**
不記牌的抽中機率
m:總共的牌組數(兩張一組)
n:可以翻牌的次數(一次兩張)
j:必須翻中同組的次數
example: P1(6,5,4)= 牌面上有6組牌,可以抽5次,抽中4組的機率(每次翻完不記牌)
**/
double P1(int m, int n, int j){
double A=0,B=0, a1=0, a2=0;
/*
1. 總牌組數為負的機率是0 (m<0)
2. 可翻牌次數為負的機率是0 (n<0)
3. 翻中次數為負的機率是0 (j<0)
4. 翻中次數大於總牌組數的機率是0 (j>m)
5. 翻中次數大於可翻次數的機率是0 (j>n)
*/
if( m<0 || n<0 || j<0 || j>m || j>n ) return 0;
//可翻次數為0時,翻中0次的機率為1 (j<=n=0)
if(j==0 && n==0) return 1;
a1 = 1/(2*m-1); //目前的牌面上,隨機翻中一組的機率
a2 = 1-a1; //目前的牌面上,隨機翻不中的機率
//A. 這一次有翻中,牌面剩下m-1組,可以翻的次數剩下n-1,翻中的次數剩下j-1
//B. 這一次沒翻中,牌面剩下m組,可以翻的次數剩下n-1,翻中的次數剩下j
A = a1*P1(m-1,n-1,j-1);
B = a2*P1(m,n-1,j);
return A+B;
}
/**
有記牌的抽中機率
m:總共的牌組數(兩張一組)
n:可以翻牌的次數(一次兩張)
j:必須翻中同組的次數
k:已翻開不成對的張數(每次翻牌,成對的就拿走,不成對的就記下)
example: P2(6,5,4,3)= 牌面上有6組牌,已翻開3張不成對,可以抽5次,抽中4組的機率
**/
double P2(int m, int n, int j, int k){
double A=0, B=0, C=0, D=0, a1=0, a2=0, b1=0, b2=0, b3=0;
/*
1. 總牌組數為負的機率是0 (m<0)
2. 可翻牌次數為負的機率是0 (n<0)
3. 翻中次數為負的機率是0 (j<0)
4. 翻中次數大於總牌組數的機率是0 (j>m)
5. 翻中次數大於可翻次數的機率是0 (j>n)
6. 不成對張數大於總牌組數的機率是0 (k>m)
7. 不成對張數為負的機率是0 (k<0)
*/
if( m<0 || n<0 || j<0 || j>m || j>n || k>m || k<0 ) return 0;
//不成對張數與總牌組數相同(剩下的隨便翻都可配成一對),剩下n次翻中n次的機率為1 (k=m and j=n)
if(k==m && j==n && n<=m) return 1;
a1 = k/(2*m-k); //牌面上已知有k張不成對,從剩下的牌中翻開一張與這k張中某一張成對的機率
a2 = 1-a1; //牌面上已知有k張不成對,從剩下的牌中翻開一張與這k張都不成對的機率
b1 = 1/(2*m-k-1); //接續a2,再翻開一張與a2翻出來成對的機率
b2 = k/(2*m-k-1); //接續a2,再翻開一張與前面k張成對的機率
b3 = 1-b1-b2; //接續a2,再翻開一張與前面k張和a2翻出來的都不成對的機率
/*
A. 已知牌面上有k張不成對,從其他牌中翻開一張,剛好與那k張中的某一張成對,
牌面剩下m-1組,可以翻的次數剩下n-1,翻中的次數剩下j-1,已知不成對的張數剩下k-1
B. 已知牌面上有k張不成對,從其他牌中翻開一張,與那k張皆不成對,
再翻開一張與剛才翻出來的成對,
牌面剩下m-1組,可以翻的次數剩下n-1,翻中的次數剩下j-1,已知不成對的張數剩下k(沒變)
C. 已知牌面上有k張不成對,從其他牌中翻開一張,與那k張皆不成對,
再翻開一張與前面k張成對,因此到下一輪就可將翻到成對的兩張拿走,
牌面剩下m-1組,可以翻的次數剩下n-2(多花一次),翻中的次數剩下j-1,已知不成對的張數剩下k(沒變)
D. 已知牌面上有k張不成對,從其他牌中翻開一張,與那k張皆不成對,
再翻開一張與前面k張和剛才翻出的都不成對,
牌面剩下m組,可以翻的次數剩下n-1,翻中的次數剩下j,已知不成對的張數變成k+2
*/
A = a1*P2(m-1,n-1,j-1,k-1);
B = a2*b1*P2(m-1,n-1,j-1,k);
C = a2*b2*1*P2(m-1,n-2,j-1,k);
D = a2*b3*P2(m,n-1,j,k+2);
return A+B+C+D;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment