#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cctype>
#include <complex>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <functional>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <bitset>
#include <numeric>
#define INF 1<<30
#define EPS 1e-15
const int dx[] = {1,0,-1,0,1,-1,-1,1};
const int dy[] = {0,1,0,-1,1,1,-1,-1};
#define PB push_back
#define fi first
#define se second
#define rep(i,j) for(int  i = 0; i < (j); i++)
#define reps(i,j,k) for(int i = j; i < k; i++)
#define MOD 1000000007
using namespace std;
typedef long long ll;
typedef pair<int,int> Pii;
typedef vector < int > vi;
typedef vector < vi > vvi;
class edge{
	public:
	int cost;
	int to;
	int ini;
	edge(){}
	edge(int _cost,int _to,int _ini){
		cost = _cost;
		to = _to;
		ini = _ini;
	}
	bool operator<(const edge &a)const{
		return cost >= a.cost;
	}
};
char stage[1010][1010];
vector < edge > G[1024];
int node[10]={0};
int sz;
int dijkstra(int _s){
	int d[128000];
	int s = _s+1==6?1:_s+1;
	int g = _s-1==0?5:_s-1;
	fill(d,d+128000,INF);
	priority_queue < edge > Q;
	reps(i,node[_s],node[_s+1]){
		Q.push(edge(G[i][0].ini,i,G[i][0].ini));
	}	
	int ret = -1;	
	while(!Q.empty()){
		edge e = Q.top();Q.pop();
		if(d[e.to] != INF)continue;
		d[e.to] = e.cost;
		if(e.to == sz)break;
		rep(i,G[e.to].size()){
			if(e.to != g && G[e.to][i].to != sz)Q.push(edge(G[e.to][i].cost+e.cost,G[e.to][i].to,0));
			else if(e.to == g && G[e.to][i].to == sz)Q.push(edge(G[e.to][i].cost+e.cost,G[e.to][i].to,0));
		}
	}
	return d[sz];
}	
int main(){
	int w,h;
	while(scanf("%d%d",&w,&h),(w|h)){
		memset(stage,0,sizeof(stage));
		Pii start,goal;
		vector < Pii > monster[10];
		rep(i,h){
			scanf("%s",stage[i]);
			rep(j,w){
				if(stage[i][j] == 'S'){
					start = Pii(i,j);
				}
				else if(stage[i][j] == 'G'){
					goal = Pii(i,j);
				}
				else if(stage[i][j] != '.'){
					monster[stage[i][j]-'0'].PB(Pii(i,j));
				}
			}
		}
		
		reps(i,1,6){
			node[i] = monster[i].size();
		}
		rep(i,5){
			node[i+1] += node[i];
		}
		sz = node[5];

		reps(i,1,5){
			rep(j,monster[i].size()){
				int dist_s = abs(start.fi-monster[i][j].fi)+abs(start.se-monster[i][j].se);
				int dist_g = abs(goal.fi-monster[i][j].fi)+abs(goal.se-monster[i][j].se);
				rep(k,monster[i+1].size()){
					G[node[i-1]+j].PB(edge(abs(monster[i][j].fi-monster[i+1][k].fi)+abs(monster[i][j].se-monster[i+1][k].se),node[i]+k,dist_s));
					G[node[i-1]+j].PB(edge(dist_g,sz,dist_s));

				}
			}
			if(i == 4){
				rep(j,monster[5].size()){
					int dist_s = abs(start.fi-monster[5][j].fi)+abs(start.se-monster[5][j].se);
					int dist_g = abs(goal.fi-monster[5][j].fi)+abs(goal.se-monster[5][j].se);
					rep(k,monster[1].size()){
						G[node[4]+j].PB(edge(abs(monster[i][j].fi-monster[i+1][k].fi)+abs(monster[i][j].se-monster[i+1][k].se),k,dist_s));
						G[node[4]+j].PB(edge(dist_g,sz,dist_s));
					}
				}
			}
		}
		int ans[2] = {INF,INF};
		reps(i,1,6){
			int t = dijkstra(i);
			if(ans[1] > t){
				ans[0] = i-1==0?5:i-1;
				ans[1] = t;
			}
		}
		if(ans[1] == INF)puts("NA");
		else printf("%d %d\n",ans[0],ans[1]);
	}
	return 0;
}