Problem:
平面上の図形

縦 8、横 8 のマスからなる図 1 のような平面があります。

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

図１

この平面上に、以下の A から G の図形のどれかが一つだけ置かれています。

A

■

■

■

■

B

■

■

■

■

C

■

■

■

■

D

■

■

■

■

E

■

■

■

■

F

■

■

■

■

G

■

■

■

■

たとえば、次の図 2 の例では E の図形が置かれています。

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

■

■

□

□

□

□

□

□

□

■

■

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

□

図２

平面の中で図形が占めているマスを 1、占めていないマスを 0 で表現した数字の列を読み込んで、置かれている図形の種類（A〜G）を出力するプログラムを作成してください。

ただし、ひとつの平面に置かれている図形は必ず１つで、複数の図形が置かれていることはありません。また、A〜G で表される図形以外のものが置かれていることはありません。

Input

入力は複数のデータセットからなります。

１つのデータセットとして、平面の中で図形が占めているマスを 1、占めていないマスを 0 で表現した 8 文字からなる 8 つの文字列が与えられます。例えば、図 2 に対応する文字列の並びは次のようになります。

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

1

1

0

0

0

0

0

0

0

1

1

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

データセットの間は１つの空行で区切られています。データセットの数は 50 を超えません。

Output

各データセットごとに、平面に与えられた図形の種類（A〜G のいずれか）を１行に出力してください。

Sample Input

00000000
00000000
01100000
00110000
00000000
00000000
00000000
00000000

00011110
00000000
00000000
00000000
00000000
00000000
00000000
00000000

00000000
00000000
00110000
00110000
00000000
00000000
00000000
00000000

Output for the Sample Input

E
C
A

Solution in C# (judge verdict: Wrong Answer)

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

namespace _0036
{
    public class Program

    {
        public static void Main(string[] args)
        {

            Dictionary<string, char[,]> patterns = new Dictionary<string, char[,]>();
            patterns.Add("A", new char[2, 2] { { '1', '1' }, { '1', '1' } });
            patterns.Add("B", new char[4, 1] { { '1' }, { '1' }, { '1' }, { '1' } });
            patterns.Add("C", new char[1, 4] { { '1', '1', '1', '1' } });
            patterns.Add("D", new char[3, 2] { { '0', '1' }, { '1', '1' }, { '1', '0' } });
            patterns.Add("E", new char[2, 3] { { '1', '1', '0' }, { '0', '1', '1' } });
            patterns.Add("F", new char[3, 2] { { '1', '0' }, { '1', '1' }, { '0', '1' } });
            patterns.Add("G", new char[2, 3] { { '0', '1', '1' }, { '1', '1', '0' } });

            while (true)
            {
                char[,] map = new char[8, 8];
                for (int i = 0 ; i < 8 ; i++)
                {
                    string item = RSt();
                    for (int j = 0 ; j < 8 ; j++)
                    {
                        map[i, j] = item[j];
                    }
                }

                foreach (var item in patterns)
                {
                    StringBuilder sb = new StringBuilder();
                    PatternMatch(map, item.Value, sb);
                    if (sb.Length > 0)
                    {
                        Console.Write(item.Key);
                        break;
                    }
                }

                string line = RSt();
                if (line == null) break;

            }
        }

        public static void PatternMatch(char[,] target, char[,] pattern, StringBuilder sb)
        {

            const long B1 = 100000007;
            const long B2 = 100000009;

            int tRowCnt = target.GetLength(0);
            int pRowCnt = pattern.GetLength(0);
            int tColCnt = target.GetLength(1);
            int pColCnt = pattern.GetLength(1);

            if (pRowCnt > tRowCnt || pColCnt > tColCnt) return;

            //パターンのハッシュ値
            long pHash = 0;
            long[] tmp = new long[pRowCnt];

            for (int i = 0 ; i < pRowCnt ; i++)
            {
                for (int j = 0 ; j < pColCnt ; j++)
                {
                    tmp[i] = tmp[i] * B1 + pattern[i, j];
                }
            }

            for (int i = 0 ; i < pRowCnt ; i++) pHash = pHash * B2 + tmp[i];

            //ターゲットのハッシュ値

            long t1 = 1;
            for (int i = 0 ; i < pColCnt ; i++) t1 *= B1;

            long t2 = 1;
            for (int i = 0 ; i < pRowCnt ; i++) t2 *= B2;

            long[,] tmp2 = new long[tRowCnt, tColCnt - pColCnt + 1];
            bool[,] matchTbl = new bool[tRowCnt - pRowCnt + 1, tColCnt - pColCnt + 1];
            for (int i = 0 ; i < tRowCnt ; i++)
            {
                long e = 0;
                for (int j = 0 ; j < pColCnt ; j++) e = e * B1 + target[i, j];

                for (int j = 0 ; j + pColCnt <= tColCnt ; j++)
                {
                    tmp2[i, j] = e;
                    if (j + pColCnt < tColCnt) e = e * B1 - t1 * target[i, j] + target[i, j + pColCnt];
                }

            }

            for (int j = 0 ; j + pColCnt <= tColCnt ; j++)
            {
                long e = 0;
                for (int i = 0 ; i < pRowCnt ; i++) e = e * B2 + tmp2[i, j];

                for (int i = 0 ; i + pRowCnt <= tRowCnt ; i++)
                {
                    if (e == pHash) matchTbl[i, j] = true;
                    if (i + pRowCnt < tRowCnt) e = e * B2 - t2 * tmp2[i, j] + tmp2[i + pRowCnt, j];
                }
            }

            for (int i = 0 ; i < matchTbl.GetLength(0) ; i++)
            {
                for (int j = 0 ; j < matchTbl.GetLength(1) ; j++)
                {
                    if (matchTbl[i, j]) sb.AppendLine(i.ToString() + " " + j.ToString());
                }
            }

        }


        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()); }
    }

}