#include <stdio.h>
#include <limits.h>

int BLOCK_S = 10;
int BLOCK_T = 11;
int BLOCK_X = 12;
int BLOCK_NULL = -1;

/* 足の届く範囲 */
int REACH[2][9][2] = {
	{{-1, -2}, {-1, -1}, {-1, 0}, {-1, 1}, {-1, 2}, {-2, -1}, {-2, 0}, {-2, 1}, {-3, 0}},
	{{1, -2}, {1, -1}, {1, 0}, {1, 1}, {1, 2}, {2, -1}, {2, 0}, {2, 1}, {3, 0}}
};

int w, h, s[60][30]; /* 崖のデータ */

/* 指定された座標のブロックを返す */
int getBlock(int x, int y) {
	if (x < 0 || x >= w || y < 0 || y >= h) return BLOCK_NULL;
	return s[y][x];
}

/* 幅優先探索 */
int memo[60][30][2]; /* 探索のメモ (ブロックに足が掛かるまでの最短時間) */
int UNREACHED = INT_MAX;
typedef struct { int time; int x; int y; int foot; } Log; /* 探索状態 */

/* FIFOキュー */
typedef Log Data;
Data queue[2000]; int queue_size = 2000; int queue_head; int queue_length;
void initqueue() {
	queue_length = 0;
}
void enqueue(Data d) {
	queue[(queue_head + queue_length) % queue_size] = d;
	queue_length++;
}
Data dequeue() {
	Data d = queue[queue_head];
	queue_head = (queue_head + 1) % queue_size;
	queue_length--;
	return d;
}

/* 幅優先探索をする */
int search(Log l) {
	int i;
	/* この試行が現在いるブロックまでの最短経路か確認する */
	if (l.time > memo[l.y][l.x][l.foot]) return UNREACHED;

	/* 次の動作 */
	for (i = 0; i < 9; i++) {
		int x = l.x + REACH[l.foot][i][0];
		int y = l.y + REACH[l.foot][i][1];
		int b = getBlock(x, y);
		if (b == BLOCK_X || b == BLOCK_NULL || b == BLOCK_S) {
			/* 足を置けないブロック */
			continue;
		} else if (b == BLOCK_T) {
			/* 崖登り完了 */
			return l.time;
		} else {
			/* 次のブロック */
			if (l.time + b < memo[y][x][1 - l.foot]) {
				memo[y][x][1 - l.foot] = l.time + b;
				Log m = {l.time + b, x, y, 1 - l.foot};
				enqueue(m);
			}
		}
	}

	return UNREACHED;
}

int main(void) {
	int min, i, j;

	/* データセット毎の処理 */
	while (scanf("%d%d", &w, &h) == 2 && w >= 2 && w <= 30 && h >= 5 && h <= 60) {
		/* 崖を表現する行列データを読み込む */
		for (i = 0; i < h; i++) {
			for (j = 0; j < w; j++) {
				scanf("%1s", &(s[i][j]));
				/* int 型の配列に変換する */
				if (s[i][j] >= '0' && s[i][j] <= '9') s[i][j] -= '0';
				else if (s[i][j] == 'S') s[i][j] = BLOCK_S;
				else if (s[i][j] == 'T') s[i][j] = BLOCK_T;
				else s[i][j] = BLOCK_X;

				/* メモを初期化する */
				memo[i][j][0] = UNREACHED;
				memo[i][j][1] = UNREACHED;
			}
		}

		/* 探索の始点をキューに入れる */
		for (i = 0; i < w; i++) {
			if (s[h - 1][i] == BLOCK_S) {
				Log l0 = {0, i, h - 1, 0}; /* 右足から */
				Log l1 = {0, i, h - 1, 1}; /* 左足から */
				enqueue(l0);
				enqueue(l1);
			}
		}
		/* 幅優先探索する */
		min = UNREACHED;
		while (queue_length > 0) {
			int t = search(dequeue());
			if (t < min) min = t;
		}

		/* 結果を出力する */
		if (min == UNREACHED) printf("-1\n");
		else printf("%d\n", min);

		/* デバッグ */
		/*
		for (i = 0; i < h; i++) {
			for (j = 0; j < w; j++) {
				printf("%2d ", s[i][j]);
			}
			printf("\n");
		}
		printf("\n");
		for (i = 0; i < h; i++) {
			for (j = 0; j < w; j++) {
				if (memo[i][j][0] == UNREACHED) printf("-1 ");
				else printf("%2d ", memo[i][j][0]);
			}
			printf(" | ");
			for (j = 0; j < w; j++) {
				if (memo[i][j][1] == UNREACHED) printf("-1 ");
				else printf("%2d ", memo[i][j][1]);
			}
			printf("\n");
		}
		printf("\n\n");
		*/
	}

    return 0;
}