組合せ生成プログラムの応用として、Javaで確率の問題を解いてみました。(^_^;
xy平面上の16個の点の集合{(x、y)|x=0、1、2、3 y=0、1、2、3}を考える。
この集合から異なる3点を無作為に選ぶ試行において、事象「選んだ3点が三角形の頂点となり、その三角形の面積は9/2である」の起こる確率を求めよ。
点は、n=0〜15の整数値で与えて、n/4でy座標、n%4でx座標を得ています。三角形の面積の2倍というのは、整数のまま扱いたかったからで、参考URLの行列式を使った公式で面積を求めています。
JavaScriptの組合せ生成プログラムをJavaに翻訳しておきました。(^_^;
ちなみに、next_combメソッドは、毎回、初期設定し直しているので、クラスを作って、コンストラクタではじめに1回だけ初期設定するようにすると、倍速ぐらいになります。(^_^;
●Probability.java
import java.util.Arrays; public class Probability { // 三角形の面積の2倍を求める static int biAreaOfTriangle(int[] p){ int x1=p[0]%4, x2=p[1]%4, x3=p[2]%4; int y1=p[0]/4, y2=p[1]/4, y3=p[2]/4; return (Math.abs((x2-x1)*(y3-y1)-(x3-x1)*(y2-y1))); } // 最大公約数 static int gcd(int a, int b){ return( b == 0 ? a : gcd(b, a % b) ); } static void swap(int[] s, int i, int j) { int t = s[i]; s[i] = s[j]; s[j] = t; } // 順列生成 static boolean next_perm(int[] p, int n, int r) { int i, j, k; if(r <= 0 || n < r) return(false); for(i = r + 1; i <= n-1; i++) for(j = i; j >= r + 1 && p[j-1] < p[j]; j--) swap(p,j,j-1); for(i = n - 1; i > 0 && p[i-1] >= p[i]; i--); if(i==0) return(false); for(j = n - 1; j > i && p[i-1] >= p[j]; j--); swap(p,j,i-1); for(k = 0; k <= (n-i-1)/2; k++) swap(p,i+k,n-k-1); return(true); } // xがa[]の何番目にあるか調べる関数 static int get_pos(int[] a, int x) { for(int i=0; i< a.length; i++) if(a[i]==x) return(i); // あるときは、0〜a.length-1を返す. return(-1); // ないときは、-1を返す. } // 組合せ生成 static boolean next_comb(int[] c, int n, int r) { int i, j, k; if(r<= 0 || n< r) return(false); int[] o=new int[n]; int[] p=new int[n]; o=Arrays.copyOf(c,c.length); Arrays.sort(o); for(i=0; i< n; i++) p[i]=1; for(i=0; i< r; i++) p[get_pos(o,c[i])]=0; boolean res=next_perm(p, n, n); if(!res) n=0; for(i=j=0, k=r; i< n; i++) if(p[i]==0) c[j++]=o[i]; else c[k++]=o[i]; //delete o,p; // Javaでは不要 return(res); } public static void main(String[] args) { final int N=16; final int R= 3; int[] p=new int[N]; for(int i=0; i< N; i++) p[i]=i; int count=0, total=0; long tm=System.currentTimeMillis(); // Timer Start do{ //System.out.println(Arrays.toString(p)); total++; // すべての場合をカウント int s=biAreaOfTriangle(p); if(s==9) count++; // 題意を満たす場合のみをカウント }while(next_comb(p,N,R)); int g; if(count!=0) g=gcd(count, total); else g=1; System.out.println("p="+(count/g)+"/"+(total/g)); tm=System.currentTimeMillis()-tm; // Timer Stop System.out.printf("Runtime : %.3f [sec]\n",(double)tm/1000.0); } }
●実行結果
p=3/140 Runtime : 0.006 [sec]
P.S.
ちなみに、組合せ生成 next_comb メソッドを次のように書き換えると、get_pos メソッドが不用になります。o(^-^)o
● Probability1.java
/* * Probability1.java */ public class Probability1 { // 順列生成 static boolean nextPerm(int[] p, int n, int r) { int i, j; int t; if(r <= 0 || n < r) return(false); for(i = r + 1; i <= n-1; i++) for(j = i; j >= r + 1 && p[j-1] < p[j]; j--){ t = p[j]; p[j] = p[j-1]; p[j-1] = t; // swap(p,j,j-1); } for(i = n - 1; i > 0 && p[i-1] >= p[i]; i--); if(i==0) return(false); for(j = n - 1; j > i && p[i-1] >= p[j]; j--); t = p[j]; p[j] = p[i-1]; p[i-1] = t; // swap(p,j,i-1); for(j = n - 1; i < j; i++, j--){ t = p[i]; p[i] = p[j]; p[j] = t; // swap(p,i,j); } return(true); } // 組合せ生成 static boolean nextComb(int[] p, int n, int r) { int i; do{ if(!nextPerm(p,n,r)) return(false); for(i = 0; i< r-1; i++) if(p[i]> p[i+1]) break; } while (i< r-1); return(true); } // 三角形の面積の2倍を求める static int biAreaOfTriangle(int[] p){ int x1 = p[0]%4, x2 = p[1]%4, x3 = p[2]%4; int y1 = p[0]/4, y2 = p[1]/4, y3 = p[2]/4; return Math.abs((x2-x1)*(y3-y1)-(x3-x1)*(y2-y1)); } // 最大公約数 static int gcd(int a, int b){ return (b==0) ? a : gcd(b, a % b); } public static void main(String[] args) { final int N = 16, R = 3; int[] p = new int[N]; // 組合せ生成用 for(int i = 0; i< N; i++) p[i]=i; int count = 0, total = 0; long tm = System.nanoTime(); // Timer Start do{ if(biAreaOfTriangle(p)==9) count++; total++; }while(nextComb(p,N,R)); int g = (count!=0) ? gcd(count,total) : 1; System.out.println("p = "+(count/g)+"/"+(total/g)); tm = System.nanoTime()-tm; // Timer Stop System.out.printf("Runtime : %.3f [sec]\n",(double)tm/1e9); } }
※参考URL
●行列式は美しい
●お気楽 Java プログラミング入門 第 4 回 再帰定義
- 作者: (株)アンク
- 出版社/メーカー: 翔泳社
- 発売日: 2005/02/16
- メディア: 単行本
- 購入: 3人 クリック: 73回
- この商品を含むブログ (26件) を見る
- 作者: 柴田望洋
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2007/08/08
- メディア: 単行本
- 購入: 16人 クリック: 271回
- この商品を含むブログ (55件) を見る
- 作者: 柴田望洋,由梨かおる
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2008/05/24
- メディア: 単行本
- 購入: 8人 クリック: 72回
- この商品を含むブログ (9件) を見る
パーフェクトJava (PERFECT SERIES) (PERFECT SERIES 2)
- 作者: アリエル・ネットワーク株式会社,井上誠一郎,永井雅人,松山智大
- 出版社/メーカー: 技術評論社
- 発売日: 2009/09/24
- メディア: 大型本
- 購入: 26人 クリック: 360回
- この商品を含むブログ (35件) を見る
- 作者: クロノス・クラウン,柳井政和
- 出版社/メーカー: 秀和システム
- 発売日: 2012/03/14
- メディア: 単行本
- クリック: 6回
- この商品を含むブログ (3件) を見る