Problem:
パズル

1 〜 9 の数字を 14 個組み合わせて完成させるパズルがあります。与えられた 13 個の数字にもうひとつ数字を付け加えて完成させます。

パズルの完成条件は

同じ数字を２つ組み合わせたものが必ずひとつ必要です。

残りの12 個の数字は、３個の数字の組み合わせ４つです。

３個の数字の組み合わせ方は、同じ数字を３つ組み合わせたものか、または３つの連続する数字を組み合わせたものです。ただし、9 1 2 のような並びは連続する数字とは認められません。

同じ数字は4 回まで使えます。

13 個の数字からなる文字列を読み込んで、パズルを完成することができる数字を昇順に全て出力するプログラムを作成してください。なお、1〜9 のどの数字を付け加えてもパズルを完成させることができないときは 0 を出力してください。

例えば与えられた文字列が 3456666777999 の場合

「2」があれば、　234 567 666 77 999

「3」があれば、　33 456 666 777 999

「5」があれば、　345 567 666 77 999

「8」があれば、　345 666 678 77 999

というふうに、2 3 5 8 のいずれかの数字が付け加えられるとパズルは完成します。「6」でも整いますが、5 回目の使用になるので、この例では使えないことに注意してください。

Input

入力は複数のデータセットからなります。各データセットとして、13 個の数字が１行に与えられます。データセットの数は 50 を超えません。

Output

データセットごとに、パズルを完成させることができる数字を昇順に空白区切りで１行に出力します。

Sample Input

3649596966777
6358665788577
9118992346175
9643871425498
7755542764533
1133557799246

Output for the Sample Input

2 3 5 8
3 4
1 2 3 4 5 6 7 8 9
7 8 9
1 2 3 4 6 7 8
0

Solution in JAVA (judge verdict: Accepted)

import java.util.*;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		while(sc.hasNext()){
			char[] d = sc.nextLine().toCharArray();
			
			//配列のindexとカードの番号を一致させた．datacount[0]は空けておく．
			int[] datacount = new int[9 + 1];
			datacount[0] = 0;
			
			//カードの枚数を調べる
			for(int i = 0; i < d.length; i++){
				datacount[new Integer(d[i] - '0')] ++;
			}
			
			StringBuffer output = new StringBuffer();
			for(int i = 1; i <= 9; i++){
				//カードiをつけ加えて，整うかどうか調べる．
				
				//カードiが既に4枚以上あるなら飛ばす
				if(datacount[i] == 4){continue;}
				
				//データを複製し，カードiを1枚つけ加える．
				int[] s = datacount.clone();
				s[i] ++;
				
				boolean res = search(s, false, 4);
				if(res){
					output.append(" ");
					output.append(i);
				}
			}
			
			if(output.length() == 0){output.append(" 0");}
			output.delete(0, 1);
			System.out.println(output);
		}
	}
	
	static boolean search(int[] data, boolean is2searched, int paircount){
		boolean res = false;
		if(!is2searched){
			//はじめは2枚ペアを探す
			
			for(int i = 1; i <= 9; i++){
				if(data[i] >= 2){
					int[] d = data.clone();
					d[i] = d[i] - 2;
					
					//残りのグループを探す
					boolean r = search(d, true, paircount);
					if(r){
						//成功例が1つでも存在すればOK．それ以上は調べない．
						res = true;
						break;
					}
				}
			}
		}else{
			//2枚ペアを探したあと，グループを探す
			
			if(paircount == 0){
				//グループを探し尽くしたあと
				
				//カードが1枚も残っていないか確認する
				for(int i : data){
					boolean flag = true;
					if (i != 0){
						flag = false;
						break;
					}
					
					//1枚も残ってないなら，flagはtrueなのでOK．
					//1枚でも残っていると，flagはfalseにされる．
					res = flag;
				}
			}else{
				//グループ探し中
				
				for(int i = 1; i <= 9; i++){
					boolean res1 = false;
					boolean res2 = false;
					
					//いま対象にしているカードiについて，3枚同一グループがあるか
					if(data[i] >= 3){
						int[] d = data.clone();
						
						d[i] = d[i] - 3;
						res1 = search(d, true, paircount - 1);
					}
					
					//カードiについて，そこから起点とする連続グループがあるか
					//i = 8, 9 はしらべなくてもいい
					if(i < 8 && data[i] >= 1 && data[i + 1] >= 1 && data[i + 2] >= 1){
						int[] d = data.clone();
						
						d[i] --;
						d[i + 1] --;
						d[i + 2] --;
						
						res2 = search(d, true, paircount -1);
					}
					
					//成功例が1つでもあればOK．それ以上は調べない．
					if(res1 || res2){
						res = true;
						break;
					}
				}
			}
		}
		
		return res;
	}
}