問題
袋に9つのボールが入っていてそのひとつひとつに1〜9の番号がついている。ちょうどビリヤードの球が9つ入っている様子を想像してもらえればよい。
その袋から3つ取り出してその番号の合計が10になる組み合わせを列挙せよ。


数学的には「組み合わせ」と呼ばれている分野だ。今回の場合だと9個の中から3個を取り出す組み合わせなので9C3で84通り。
すべて列挙すると以下となる。

123 124 125 126 127 128 129 134 135 136 137 138 139 145 146 147 148 149 156 157 158 159 167 168 169 178 179 189 
234 235 236 237 238 239 245 246 247 248 249 256 257 258 259 267 268 269 278 279 289 
345 346 347 348 349 356 357 358 359 367 368 369 378 379 389 
456 457 458 459 467 468 469 478 479 489 
567 568 569 578 579 589 
678 679 689 
789 

この問題をJavaで解いてみよう。
3桁の数字をつくるので3重forを作成する。
最初のループでは1つ目(百の位)なので1~7まで回せばよさそうだ。この際、8、9まで回さなくてよいことに注意する。(789が最大)
2桁目のループでは1桁目でとりだした値+1から8まで回せば良い。
3桁目のループでは2桁目でとりだした値+1から9まで回せば良い。

[解答例]

public static void main(String[] args) {
			
		for(int i=1;i<=7;i++){
			System.out.println();
			for(int j=i+1;j<=8;j++){
				for(int k=j+1;k<=9;k++){
					System.out.print(""+i+j+k+" ");				
				}
			}
		}
		
	}

これで上記の組み合わせがすべて得られる。見やすくするため最初のforのあとで改行処理をいれた。

今回の問題ではこの中から桁の合計が10になるものをピックアップすればよいので以下のように変更する。

public static void main(String[] args) {		
		for(int i=1;i<=7;i++){
			for(int j=i+1;j<=8;j++){
				for(int k=j+1;k<=9;k++){
					if(i+j+k==10){
						System.out.printf("[%d,%d,%d]%n",i,j,k);	
					}				
				}
			}
		}
	}

[結果]

[1,2,7]
[1,3,6]
[1,4,5]
[2,3,5]

答えが得られた。

最後に汎用性を持たせるためにマジックナンバーを定数化しよう。

public static void main(String[] args) {	
		final int MIN=1,MAX=9,TOTAL=10;
		for(int i=MIN;i<=MAX-2;i++){
			for(int j=i+1;j<=MAX-1;j++){
				for(int k=j+1;k<=MAX;k++){
					if(i+j+k==TOTAL){
						System.out.printf("[%d,%d,%d]%n",i,j,k);	
					}				
				}
			}
		}
	}

以上で終了だ。組み合わせや順列はアルゴリズムや解法をしっていないと解けないものが多い。まずは今回の多重forによる組み合わせ問題を理解しよう。