Problem:
写真に写っている景色は?

A 君は会津に観光にやってきました。宿泊したホテルの窓からは会津盆地が一望できます。景色を眺めていると、床に写真の切れ端が落ちているのに気がつきました。どうやら窓から外の景色を撮ったようです。「どの辺りを撮ったのかな」と、A 君は窓の外の景色と写真が同じ大きさになるように写真をかざして、写真と窓の外の景色が一致する場所を探し始めました。

それでは、A 君がやっていることをコンピュータでやってみましょう。窓の外の景色を n × n マスの正方形に分割します (n を景色の大きさと呼びます)。各マスには、そのマスの画像の情報を表す 0 以上の整数が書かれています。マスの位置は座標 (x, y) で表します。各マスの座標は以下の通りになります。

写真の切れ端は、m × m マスの正方形で表されます (m を写真の切れ端の大きさと呼びます) 。この正方形の中で、切れ端の部分のマスには画像の情報が、切れ端に含まれない部分のマスには -1 が書かれています。たとえば、下図では、色が塗られている部分が実際の写真の切れ端の形を表しています。切れ端に穴が開いていることはありますが、必ず 1 つにつながっています。 (0 以上の値をもつマスが頂点だけで接しているときは、つながっていないものとみなします。) また、値 -1 のマスが縦または横 1 列に端から端まで並ぶことはありません。

窓から見える景色の中で、写真の切れ端を 0、90、180、270 度回転させたいずれかと一致する領域を探します。たとえば、景色が下図のように表わせるとき、上図の切れ端を反時計回りに90 度回転させると、色が塗られた領域に一致します。

窓から見える景色と写真の切れ端の情報を入力とし、景色の中で、切れ端を 0、90、180、270 度回転させたいずれかと一致する領域の最も上端に近いマスのうち、最も左端に近いマスの座標を出力するプログラムを作成してください。

一致する領域が複数ある場合は、それらの領域内にあるマスの中で、最も上端に近いマスのうち、最も左端に近いマスの座標を出力してください。一致する領域がないときは、NA と出力します。

Input

複数のデータセットの並びが入力として与えられます。入力の終わりはゼロふたつの行で示されます。各データセットは以下の形式で与えられます。

n m
w11 w12 ... w1n
w21 w22 ... w2n
:
wn1 wn2 ... wnn
p11 p12 ... p1m
p21 p22 ... p2m
:
pm1 pm2 ... pmm

1 行目にn, m (1 ≤ n ≤ 100, 1 ≤ m ≤ 50, m ≤ n) が与えられます。

続く n 行に窓から見える景色の情報 wij (0 ≤ wij ≤ 15)、続く m 行に写真の切れ端のデータの情報 pij (-1 ≤ pij ≤ 15) が与えられます。

データセットの数は 100 を超えません。

Output

入力データセットごとに、マスの位置の座標または NA を１行に出力します。

Sample Input

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

Output for the Sample Input

4 2
NA

Solution in C# (judge verdict: Accepted)



using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("UnitTestProject1")] 
namespace AOJ
{
    public  class Program
    {

        private static bool isMatch(string x, string y)
        {
            if (y == "-1")
            {
                return true;
            }
            return x.Equals(y);
        }

        private static int[] rotate(int n,int x, int y, int d)
        {
            switch (d)
            {
                case 0:
                    return new int[] { x, y };
                    
                case 90:
                    return new int[] { y, n-1-x };
                    
                case 180:
                    return new int[] { n-1-x, n-1-y };

                default:
                    return new int[]{n-1-y,x};

            }
        }

        //private static bool
        private static string solve(int n,int m)
        {
            string[][] tbl = new string[n][];

            for (int i = 0; i < n; i++)
            {
                tbl[i] = Console.ReadLine().Split(new char[] { ' ' });
            }
            
            //切れ端
            string[][] subTbl = new string[m][];

            for (int i = 0; i < m; i++)
            {
                subTbl[i] = Console.ReadLine().Split(new char[] { ' ' });
            }

            int[] r = { 0, 90, 180, 270 };
            for (int i = 0; i <= n - m; i++)
            {
                for (int j = 0; j <= n - m; j++)
                {//比較スタート地点
                 
                    for (int hoge = 0; hoge < 4; hoge++)
                    {
                        bool flg = true;
                        int rsltX=-1,rsltY = -1;
                        for (int mi = 0; mi < m; mi++)
                        {
                            for (int mj = 0; mj < m; mj++)
                            {

                                int[] piyo = rotate(m, mi, mj, r[hoge]);
                                //Console.WriteLine(piyo[0] + " " + piyo[1]);
                                if (!isMatch(tbl[i + mi][j + mj], subTbl[piyo[0]][piyo[1]]))
                                {
                                    flg = false;
                                    break;
                                }
                                else if(rsltX == -1)
                                {
                                    if (subTbl[piyo[0]][piyo[1]] != "-1")
                                    {
                                        rsltX = i + mi+1;
                                        rsltY = j + mj+1;
                                    }
                                }
                            }
                            if (!flg) break;
                        }

                        if (flg)
                        {
                            return  rsltY.ToString() + " " + rsltX.ToString();
                        }
                    }

                    //for (int hoge = 0; hoge < 2; hoge++)
                    //{
                    //    bool flg = true;
                    //    for (int mi = 0; mi < m; mi++)
                    //    {
                    //        for (int mj = 0; mj < m; mj++)
                    //        {

                    //            int mx = ((x2[hoge] < 0) ? m - 1 : 0) + mi * x2[hoge];
                    //            int my = ((y2[hoge] < 0) ? m - 1 : 0) + mj * y2[hoge];
                    //            Console.WriteLine(my.ToString() + " " + mx.ToString());
                    //            if (!isMatch(tbl[i + mi][j + mj], subTbl[my][mx]))
                    //            {
                    //                flg = false;
                    //                break;
                    //            }
                    //        }
                    //        if (!flg) break;
                    //    }

                    //    if (flg)
                    //    {
                    //        return i.ToString() + j.ToString();
                    //    }
                    //}
                }
            }
            return "NA";
        }

        static void Main(string[] args)
        {

            while (true)
            {
                string[] hoge = Console.ReadLine().Split(new char[] { ' ' });
                int n = int.Parse(hoge[0]);
                int m = int.Parse(hoge[1]);
                if (n == 0 && m== 0) break;
                Console.WriteLine(solve(n,m));
            }
        }
    }
}