#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <numeric>
#include <random>
#include <vector>
#include <array>
#include <bitset>
#include <queue>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>

using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
template<class T> using V = vector<T>;
template<class T> using VV = V<V<T>>;
constexpr ll TEN(int n) { return (n==0) ? 1 : 10*TEN(n-1); }
int bsr(int x) { return 31 - __builtin_clz(x); }
int bsr(ll x) { return 63 - __builtin_clzll(x); }
int bsf(int x) { return __builtin_ctz(x); }
int bsf(ll x) { return __builtin_ctzll(x); }

template<class N>
struct SegTree {
    int lg, sz;
    vector<N> n;
    SegTree(int sz) {
        lg = bsr(2*sz-1);
        sz = 1<<lg;
        this->sz = sz;
        n = vector<N>(2*sz);
        for (int i = 2*sz-1; i >= sz; i--) {
            n[i] = N();
        }
        for (int i = sz-1; i >= 1; i--) {
            n[i] = N(n[2*i], n[2*i+1]);
        }
    }
    template<class Q>
    Q single(int idx, Q q) {
        if (idx < 0 || sz <= idx) return q;
        idx += sz;
        for (int i = lg; i >= 1; i--) {
            int k = idx>>i;
            n[k].push(n[2*k], n[2*k+1]);
        }
        q += n[idx];
        if (q.update()) {
            for (int i = 1; i <= lg; i++) {
                int k = idx>>i;
                n[k].update(n[2*k], n[2*k+1]);
            }
        }
        return q;
    }
    template<class Q>
    void query(int a, int b, Q &q, int k, int sz) {
        if (a <= 0 && sz <= b) {
            q += n[k];
            return;
        }
        n[k].push(n[2*k], n[2*k+1]);
        if (a < sz/2) query(a, b, q, 2*k, sz/2);
        if (sz/2 < b) query(a-sz/2, b-sz/2, q, 2*k+1, sz/2);
        if (q.update()) n[k].update(n[2*k], n[2*k+1]);
    }
    template<class Q>
    Q query(int a, int b, Q q) {
        if (a < sz && 0 < b) query(a, b, q, 1, sz);
        return q;
    }
};

struct Node {
    int mi;
    void init() {
        mi = TEN(9);
    }
    Node() { init(); } // leaf
    Node(Node &l, Node &r) { init(); update(l, r); }
    void update(const Node &l, const Node &r) {
        mi = min(l.mi, r.mi);
    }
    void push(Node &l, Node &r) {
    }
    // query
    struct MinQuery {
        int mi = TEN(9);
        static constexpr bool update() { return false; }
        void operator+=(Node &r) { mi = min(mi, r.mi); }
    };
    struct AddQuery {
        int x;
        static constexpr bool update() { return true; }
        void operator+=(Node &n) { n.mi = min(n.mi, x); }
    };
};

struct Solver {
    using P = pair<int, int>;
    int w, h;
    VV<P> monster[7];
    void send(int a, int b) {
        for (int y = 0; y < h; y++) {
            for (auto &q: monster[b][y]) {
                q.second = TEN(9);
            }
        }
        // y(0) => y(h-1)
        {
            SegTree<Node> left(w), right(w);
            for (int y = 0; y < h; y++) {
                // add
                for (auto q: monster[a][y]) {
                    left.single(q.first, Node::AddQuery{q.second-q.first-y});
                    right.single(q.first, Node::AddQuery{q.second+q.first-y});
                }
                // get
                for (auto &q: monster[b][y]) {
                    int x = TEN(9);
                    x = min(x, left.query(0, q.first+1, Node::MinQuery{}).mi + q.first + y);
                    x = min(x, right.query(q.first, w, Node::MinQuery{}).mi - q.first + y);
                    q.second = min(q.second, x);
                }
            }
        }
        // h-1 => 0
        {
            SegTree<Node> left(w), right(w);
            for (int y = h-1; y >= 0; y--) {
                // add
                for (auto q: monster[a][y]) {
                    left.single(q.first, Node::AddQuery{q.second-q.first+y});
                    right.single(q.first, Node::AddQuery{q.second+q.first+y});
                }
                // get
                for (auto &q: monster[b][y]) {
                    int x = TEN(9);
                    x = min(x, left.query(0, q.first+1, Node::MinQuery{}).mi + q.first - y);
                    x = min(x, right.query(q.first, w, Node::MinQuery{}).mi - q.first - y);
                    q.second = min(q.second, x);
                }
            }
        }
    }
    void solve() {
        scanf("%d %d", &w, &h);
        if (w == 0 && h == 0) {
            exit(0);
        }
        for (int i = 0; i < 7; i++) {
            monster[i].resize(h);
        }
        int sy, gy;
        for (int y = 0; y < h; y++) {
            char s[1010];
            scanf("%s", s);
            for (int x = 0; x < w; x++) {
                char c = s[x];
                if (c == '.') continue;
                if (c == 'S') {
                    monster[5][y].push_back(P(x, 0));
                    sy = y;
                } else if (c == 'G') {
                    monster[6][y].push_back(P(x, 0));
                    gy = y;
                } else {
                    monster[c-'0'-1][y].push_back(P(x, 0));
                }
            }
        }

        int mx = TEN(8), mst = -1;
        for (int st = 0; st < 5; st++) {
            // 5, st, st+1, .., 6

            monster[5][sy][0].second = 0;
            send(5, st);
            for (int i = 0; i < 3; i++) {
                send((st+i)%5, (st+i+1)%5);
            }
            send((st+3)%5, 6);
            int ans = monster[6][gy][0].second;
            if (ans < mx) {
                mx = ans;
                mst = (st+4)%5+1;
            } else if (ans == mx) {
                mst = min(mst, (st+4)%5+1);
            }
        }
        if (mst == -1) {
            printf("NA\n");
        } else {
            printf("%d %d\n", mst, mx);
        }
    }
};

int main() {
    while (true) {
        Solver s;
        s.solve();
    }
    return 0;
}

Measured memory_bytes: 3336