#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <climits>
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
#include <utility>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <functional>

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef vector<pii> vpii;

#define fst first
#define scd second
#define PB push_back
#define MP make_pair
#define rep(i,x) for(int i=0;i<(x);++i)
#define rep1(i,x) for(int i=1;i<=(x);++i)
#define rrep(i,x) for(int i=(x)-1;i>=0;--i)
#define rrep1(i,x) for(int i=(x);i>=1;--i)
#define FOR(i,a,x) for(int i=(a);i<(x);++i)
#define all(a) a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()

#define omajinai ios::sync_with_stdio(false);cin.tie(0)

template<typename T>T& max(T&a,T&b){if(a>=b)return a;return b;}
template<typename T>T& min(T&a,T&b){if(a<b)return a;return b;}
template<typename T>bool chmax(T&a,T b){if(a<b){a=b;return true;}return false;}
template<typename T>bool chmin(T&a,T b){if(a>b){a=b;return true;}return false;}
template<typename T>T get(){T a;cin>>a;return a;}
template<typename T>T rev(T a){reverse(all(a));return a;}
template<typename T>istream&operator>>(istream&is,vector<T>&vec){rep(i,vec.size())is>>vec[i];return is;}
template<typename T>vector<T>&sort(vector<T>&a){sort(all(a));return a;}

const int inf = 1e9;
const ll linf = 3e18;
const double eps = 1e-9;

struct edge { int to, cost; edge(int to, int cost) : to(to), cost(cost) {} };
typedef vector<edge> edges;

vector<edge> G[5011];
int d[5011];

vector<pii> vs[5];
pii start, goal;

int calc(pii &a, pii &b)
{
    return abs(a.fst - b.fst) + abs(a.scd - b.scd);
}

void build(int num)
{
    rep(i, 5011) G[i].clear();

    // start -> num
    rep1(i, vs[num].size()) {
        int iidx = i - 1;
        pii v = vs[num][iidx];
        G[0].PB(edge(i + num * 1000, calc(start, v)));
    }

    int now = num, last_num = (num + 3) % 5;

    // s -> 0, 0 -> 1, 1 -> 2, 2 -> 3, 3 -> 4, 4 -> g

    while (now != last_num) {
        int nx = (now + 1) % 5;

        for (int i = 1; i <= vs[now].size(); ++i) {
            int iidx = i - 1;
            pii v = vs[now][iidx];

            for (int j = 1; j <= vs[nx].size(); ++j) {
                int jidx = j - 1;
                pii u = vs[nx][jidx];

                G[i + now * 1000].PB(edge(j + nx * 1000, calc(v, u)));
            }
        }

        now += 1;
        now %= 5;
    }

    rep1(i, vs[now].size()) {
        int iidx = i - 1;
        pii v = vs[now][iidx];
        G[i + now * 1000].PB(edge(5010, calc(v, goal)));
    }
}

int dijkstra(int s)
{
    priority_queue<pii, vector<pii>, greater<pii> > q;
    fill(d, d + 5011, inf);

    d[s] = 0;

    q.push(pii(0, s));

    while (q.size()) {
        pii p = q.top(); q.pop();

        int v = p.scd;

        if (d[v] < p.fst) continue;

        rep(i, G[v].size()) {
            edge e = G[v][i];

            if (d[e.to] > d[v] + e.cost) {
                d[e.to] = d[v] + e.cost;
                q.push(pii(d[e.to], e.to));
            }
        }
    }

    return d[5010];
}

signed main()
{
    int x, y;
    while (scanf("%d%d", &x, &y), x || y) {
        rep(i, 5) vs[i].clear();

        rep(i, y) {
            rep(j, x) {
                char c; scanf("\n%c", &c);
                if ('1' <= c && c <= '5') {
                    vs[c - '1'].PB(pii(i, j));
                } else if (c == 'S') {
                    start = pii(i, j);
                } else if (c == 'G') {
                    goal = pii(i, j);
                }
            }
        }

        int mi = inf, attr;

        rep(i, 5) {
            int num = (i + 1) % 5;
            build(num);
            if (chmin(mi, dijkstra(0))) {
                attr = i + 1;
            }
        }

        if (mi == inf) cout << "NA\n";
        else cout << attr << ' ' << mi << endl;
    }
}

Measured memory_bytes: 41652