/*
 * D.cpp
 *
 *  Created on: 2017/07/09
 *      Author: aihara
 */
#include <bits/stdc++.h>
//#define MYDEBUG
#ifdef MYDEBUG
#define dbp(a) cout<<#a<<": "<<a<<endl
#define dbp2(a,b) cout<<#a<<","<<#b<<": "<<a<<","<<b<<endl
#define dbp3(a,b,c) cout<<#a<<","<<#b<<","<<#c<<": "<<a<<","<<b<<","<<c<<endl
#define dbp4(a,b,c,d) cout<<#a<<","<<#b<<","<<#c<<","<<#d<<": "<<a<<","<<b<<","<<c<<","<<d<<endl
#else
#define dbp(a)
#define dbp2(a,b)
#define dbp3(a,b,c)
#define dbp4(a,b,c,d)
#endif
#define ll long long
#define ull unsigned long long
#define all(x) x.begin(), x.end()
#define rep(i,from,to) for(ll i=from; i<to; ++i)
#define REP(i,from,to) for(ll i=from; i<=to; ++i)
using namespace std;
typedef pair<int, int> P;
typedef pair<P, P> PP;
template<typename T>
ostream& operator<<(ostream& out, const vector<vector<T> >& v) {
	for (size_t i = 0; i < v.size(); ++i) {
		out << v[i] << endl;
	}
	return out;
}
template<typename T>
ostream& operator<<(ostream& out, const vector<T>& v) {
	out << "[";
	size_t last = v.size() - 1;
	for (size_t i = 0; i < v.size(); ++i) {
		out << v[i];
		if (i != last) {
			out << ",";
		}
	}
	out << "]";
	return out;
}
template<typename T>
ostream& operator<<(ostream& out, const pair<T, T>& p) {
	cout << "(" << p.first << ", " << p.second << ")";
	return out;
}

struct edge {
	int from, to, cost;
	edge(int f, int t, int c) {
		from = f;
		to = t;
		cost = c;
	}
	edge() {
		from = -1;
		to = -1;
		cost = -1;
	}
	bool operator<(const edge& e) const {
		return cost < e.cost;
	}
};

struct vertex {
	int id, w, h, foot, cost; //foot: 0(left), 1(right)
	vertex(int id_, int w_, int h_, int foot_, int cost_) {
		id = id_;
		w = w_;
		h = h_;
		foot = foot_;
		cost = cost_;
	}
	vertex() {
		id = 0;
		w = 0;
		h = 0;
		foot = 0;
		cost = 0;
	}
};

typedef struct edge edge;
typedef struct vertex vertex;

ostream& operator<<(ostream& out, const edge& e) {
	cout << "(" << e.from << "->" << e.to << ": " << e.cost << ")";
	return out;
}
ostream& operator<<(ostream& out, const vertex& v) {
	cout << "<" << v.id << "," << v.w << "," << v.h << "," << v.foot << ","
			<< v.cost << ">";
	return out;
}
static const int MAX_W = 32;
static const int MAX_H = 62;
static const int MAX_V = MAX_W * MAX_H * 2; //Left, Right
static const int INF = 1e9 + 10000;
static const int LEFT = 0;
static const int RIGHT = 1;
vector<edge> g[MAX_V];
vector<vector<vertex> > v[2];
int d[MAX_V];
int w, h;
int id;
int Ldi[9] = { -2, -1, 0, 1, 2, -1, 0, 1, 0 };
int Ldj[9] = { -1, -1, -1, -1, -1, -2, -2, -2, -3 };
int Rdi[9] = { -2, -1, 0, 1, 2, -1, 0, 1, 0 };
int Rdj[9] = { 1, 1, 1, 1, 1, 2, 2, 2, 3 };
int di[2][9] = { { -2, -1, 0, 1, 2, -1, 0, 1, 0 }, { -2, -1, 0, 1, 2, -1, 0, 1,
		0 } };
int dj[2][9] = { { -1, -1, -1, -1, -1, -2, -2, -2, -3 }, { 1, 1, 1, 1, 1, 2, 2,
		2, 3 } };
vector<vertex> start;
vector<vertex> goal;
void init() {
	id = 0;
	rep(i, 0, MAX_V)
	{
		g[i] = vector<edge>();
	}
	v[0] = vector<vector<vertex> >();
	v[1] = vector<vector<vertex> >();
	start = vector<vertex>();
	goal = vector<vertex>();
}

int swapfoot(int foot) {
	if (foot == LEFT) {
		return RIGHT;
	} else {
		return LEFT;
	}
}

bool ok(int ni, int nj, int nfoot) {
	if (0 <= ni && ni < h && 0 <= nj && nj < w) {
		if (v[nfoot][ni][nj].cost != -1) {
			return true;
		} else {
			return false;
		}
	} else {
		return false;
	}
}

void enumerate(vertex &vx, int i, int j) {
	int nfoot = swapfoot(vx.foot);
	rep(k,0,9)
	{
		int ni = i + di[nfoot][k];
		int nj = j + dj[nfoot][k];
		if (ok(ni, nj, nfoot)) {
			vertex &nv = v[nfoot][ni][nj];
			edge e(vx.id, nv.id, nv.cost);
			dbp(e);
			g[vx.id].push_back(e);
		}
	}
}

void dijkstra(int r) {
	priority_queue<P, vector<P>, greater<P> > que;
	d[r] = 0;
	que.push(P(0, r));
	while (!que.empty()) {
		P p = que.top();
		que.pop();
		int v = p.second;
		for (size_t i = 0; i < g[v].size(); ++i) {
			edge e = g[v][i];
			if (d[e.to] > d[e.from] + e.cost) {
				d[e.to] = d[e.from] + e.cost;
				que.push(P(d[e.to], e.to));
			}
		}
	}
}

void solve() {
	while (cin >> w >> h, w || h) {
		init();
		v[0] = vector<vector<vertex> >(h);
		v[1] = vector<vector<vertex> >(h);
		rep(i,0,h)
		{
			v[0][i] = vector<vertex>(w);
			v[1][i] = vector<vertex>(w);
			rep(j,0,w)
			{
				char c;
				cin >> c;
				int cost = c - '0';
				if (c == 'X') {
					cost = -1;
				}
				if (c == 'S' || c == 'T') {
					cost = 0;

				}

//			dbp2(c, cost);
				vertex vl(id, i, j, LEFT, cost);
				id++;
				vertex vr(id, i, j, RIGHT, cost);
				id++;
				v[LEFT][i][j] = vl;
				v[RIGHT][i][j] = vr;
				if (c == 'S') {
					start.push_back(vl);
					start.push_back(vr);
				}
				if (c == 'T') {
					goal.push_back(vl);
					goal.push_back(vr);
				}
			}
		}

		//debug v
//	REP(foot, 0, 1)
//	{
//		rep(i,0,h)
//		{
//			rep(j,0,w)
//			{
//				dbp4(foot, i, j, v[foot][i][j]);
//			}
//		}
//	}
		//enumerate
//	while (true) {
//		int f, i, j;
//		cin >> f >> i >> j;
//		enumerate(v[f][i][j], i, j);
//	}
		rep(i,0,h)
		{
			rep(j,0,w)
			{
				enumerate(v[LEFT][i][j], i, j);
				enumerate(v[RIGHT][i][j], i, j);
			}
		}
		rep(i,0,id)
		{
			dbp2(i, g[i]);
		}
		fill(d, d + MAX_V, INF);
		rep(i,0, (int)start.size())
		{
			vertex &r = start[i];
			dbp(r);
			dijkstra(r.id);
		}
		int ans = INF;
		rep(i, 0, (int)goal.size())
		{
			vertex &gg = goal[i];
			dbp2(gg, d[gg.id]);
			ans = min(ans, d[gg.id]);
		}
		if (ans == INF) {
			ans = -1;
		}
		cout << ans << endl;
	}
}

int main() {
	solve();
}

Measured memory_bytes: 3636