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 C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace _0043
{
    public class Program

    {
        public static void Main(string[] args)
        {
            while (true)
            {
                string line = Console.ReadLine();
                if (string.IsNullOrEmpty(line)) return;

                List<int> res = new List<int>();
                for (int i = 1 ; i < 10 ; i++) if (IsCompleteHand(line + i)) res.Add(i);
                Console.WriteLine(res.Count > 0 ? WAr(res) : "0");
            }

        }

        private static bool IsCompleteHand(string line)
        {
            int[] numsCnt = new int[9];
            for (int i = 0 ; i < line.Length ; i++) numsCnt[int.Parse(line[i].ToString()) - 1]++;

            if (numsCnt.Max() > 4) return false; //牌が4枚を超えるとNG

            int sum = numsCnt.Select((x, i) => (i + 1) * x).Sum(); //牌の合計値
            int remOfSum = sum % 3;

            //remOfsum:0 ⇒ 雀頭候補：3,6,9⇒i:2,5,8
            //remOfsum:1 ⇒ 雀頭候補：2,5,8⇒i:1,4,7
            //remOfsum:2 ⇒ 雀頭候補：1,4,7⇒i:0,3,6

            for (int i = (2 - remOfSum) ; i < 9 ; i += 3)
            {
                if (numsCnt[i] < 2) continue;
                int[] numsCntClone = (int[])numsCnt.Clone();
                numsCntClone[i] -= 2;
                if (CanCreate4Set(numsCntClone)) return true;
            }

            return false;
        }

        private static bool CanCreate4Set(int[] numsCnt)
        {
            for (int i = 0 ; i < 7 ; i++)
            {
                int r = numsCnt[i] % 3;
                if (numsCnt[i + 1] >= r && numsCnt[i + 2] >= r)
                {
                    numsCnt[i] -= r; numsCnt[i + 1] -= r; numsCnt[i + 2] -= r;
                }
                else return false;
            }

            if (numsCnt.All(x => x == 0 || x == 3)) return true;
            else return false;
        }

        static string RSt() { return Console.ReadLine(); }
        static int RInt() { return int.Parse(Console.ReadLine().Trim()); }
        static long RLong() { return long.Parse(Console.ReadLine().Trim()); }
        static double RDouble() { return double.Parse(Console.ReadLine()); }
        static string[] RStAr(char sep = ' ') { return Console.ReadLine().Trim().Split(sep); }
        static int[] RIntAr(char sep = ' ') { return Array.ConvertAll(Console.ReadLine().Trim().Split(sep), e => int.Parse(e)); }
        static long[] RLongAr(char sep = ' ') { return Array.ConvertAll(Console.ReadLine().Trim().Split(sep), e => long.Parse(e)); }
        static double[] RDoubleAr(char sep = ' ') { return Array.ConvertAll(Console.ReadLine().Trim().Split(sep), e => double.Parse(e)); }
        static string WAr<T>(IEnumerable<T> array, string sep = " ") { return string.Join(sep, array.Select(x => x.ToString()).ToArray()); }
    }

}