import std.stdio : write, writeln, writefln, stdin;
import std.array;
import std.range;
import std.typecons;
import std.algorithm : max, min;

alias Tuple!(int, int) P;

int[][] m;
bool[][] done;
int x;
int y;

int[int] f;

const P[] ofs = [P(-1, 0), P(1, 0), P(0, 1), P(0, -1)];

P s;
P g;

int XSize(P e){
	m[e[1]][e[0]] = 1;
	int cnt = 1;
	foreach(i; ofs){
		auto neo = e.P2a;
		neo[]+=i.P2a[];
		if(0<=neo[0] && neo[0]<x && 0<=neo[1] && neo[1]<y){
			if(m[neo[1]][neo[0]]==2){
				cnt += XSize(neo.a2P);
			}
		}
	}
	return cnt;
}

void fill(P e, int key){
	m[e[1]][e[0]] = key;
	foreach(i; ofs){
		auto neo = e.P2a;
		neo[]+=i.P2a[];
		if(0<=neo[0] && neo[0]<x && 0<=neo[1] && neo[1]<y){
			if(m[neo[1]][neo[0]]>0 && m[neo[1]][neo[0]]!=key){
				fill(neo.a2P, key);
			}
		}
	}
}


int d(P a, P b){
	import std.math;
	int sum;
	int[] a_ = a.P2a;
	a_[]-=b.P2a[];
	foreach(i; a_){
		sum += cast(int)(sqrt(cast(double)(i*i)));
	}
	return sum;
}

int[P[2]] bfs(P s){
	int[][] foot;
	foreach(i; y.iota){ foot ~= repeat(-1).take(x).array; }
	
	foot[s[1]][s[0]] = 0;
	P[] q = [s];
	while(q.length>0){
		P e = q.front;  q.popFront;
		foreach(i; ofs){
			auto neo_ = e.P2a;
			neo_[]+=i.P2a[];
			auto neo = neo_.a2P;
			if(0<=neo[0] && neo[0]<x && 0<=neo[1] && neo[1]<y){
				if(!done[neo[1]][neo[0]] && m[neo[1]][neo[0]] == 0 && foot[neo[1]][neo[0]]==-1){
					foot[neo[1]][neo[0]] = foot[e[1]][e[0]] + 1;
					q ~= neo;
				}
			}
		}
	}
	debug(1){
		foreach(i; y.iota){
			foot[i].dbg;
		}
		foreach(i; y.iota){
			done[i].dbg;
		}
	}
	
	int[P[2]] req;
	foreach(i; y.iota){
		foreach(j; x.iota){
			if(foot[i][j] >= 0){
				foreach(ite; ofs){
					int[2] v = [j, i];
					v[]+=ite.P2a[];
					auto neo = v.a2P;
					if(0<=neo[0] && neo[0]<x && 0<=neo[1] && neo[1]<y){
						if(!done[neo[1]][neo[0]] && m[neo[1]][neo[0]] > 0){
							/+
							if((neo in req)==null){
								req[neo] = foot[i][j] + 1;
							}else{
								req[neo] = min(req[neo], foot[i][j]+1);
							}
							+/
							req[ [neo, P(j, i)] ] = foot[i][j] + 1;
						}
					}
				}
				
				if(P(j, i)==g){
//					assert((P(j, i) in req)==null);
					req[ [P(j, i), P(j, i)] ] = foot[i][j];
				}
			}
		}
	}
	
	return req;
}

int minist;
int dfs(P e, int cnt){
	if(e==g){
		return cnt;
	}
	if(minist <= cnt+d(e, g)){
		return int.max;
	}
	int sum = 0;
	foreach(i; ofs){
		auto neo = e.P2a;
		neo[]+=i.P2a[];
		if(0<=neo[0] && neo[0]<x && 0<=neo[1] && neo[1]<y){
			if(done[neo[1]][neo[0]]) ++sum;
		}
	}
	if(sum > 1){
		return int.max;
	}
	done[e[1]][e[0]] = true;
	int min_ = int.max;
	int[P[2]] req = bfs(e);
	foreach(P[2] ps, int n; req){
		P p = ps.front;
		P pp = ps.back;
		debug(1){
			dbg(p.P2a, pp.P2a, n);
		}
		if(!done[p[1]][p[0]]){
			done[pp[1]][pp[0]] = true;
			int res = int.max;
			if(m[p[1]][p[0]]==0){
				res = dfs(p, cnt+n);
			}else if(m[p[1]][p[0]] > 1){
				if(f[m[p[1]][p[0]]] > 1){
					--f[m[p[1]][p[0]]];
					res = dfs(p, cnt+n);
					++f[m[p[1]][p[0]]];
				}
			}
			min_ = min(min_, res);
			minist = min(minist, min_);

			done[pp[1]][pp[0]] = false;
		}else{
			debug(1){
				dbg = "done";
			}
		}
	}
	done[e[1]][e[0]] = false;
	return min_;
}

bool dfs(P e, int cnt, int n){
	if(cnt==n){
		return e==g;
	}
	if(cnt+d(e, g) > n){
		return false;
	}
	int sum = 0;
	foreach(i; ofs){
		auto neo = e.P2a;
		neo[]+=i.P2a[];
		if(0<=neo[0] && neo[0]<x && 0<=neo[1] && neo[1]<y){
			if(done[neo[1]][neo[0]]) ++sum;
		}
	}
	if(sum > 1){
		return false;
	}
	/+
	foreach(i; ofs){
		bool res = false;
		auto neo = e.P2a;
		neo[]+=i.P2a[];
		if(0<=neo[0] && neo[0]<x && 0<=neo[1] && neo[1]<y){
			if(!done[neo[1]][neo[0]]){
				if(m[neo[1]][neo[0]]==0){
					done[neo[1]][neo[0]] = true;
					res |= dfs(neo.a2P, cnt+1, n);
					done[neo[1]][neo[0]] = false;
				}else if(m[neo[1]][neo[0]] > 1){
					if(f[m[neo[1]][neo[0]]] > 1){
						--f[m[neo[1]][neo[0]]];
						done[neo[1]][neo[0]] = true;
						res |= dfs(neo.a2P, cnt+1, n);
						done[neo[1]][neo[0]] = false;
						++f[m[neo[1]][neo[0]]];
					}
				}
			}
		}
		if(res)return true;
	}
	+/
	int[P[2]] req = bfs(e);
	foreach(P[2] ps, int num; req){
		P p = ps.front;
		P pp = ps.back;
		debug(1){
			dbg(p.P2a, pp.P2a, n);
		}
		if(!done[p[1]][p[0]]){
			done[pp[1]][pp[0]] = true;
			if(m[p[1]][p[0]]==0){
				done[p[1]][p[0]] = true;
				if(dfs(p, cnt+num, n)){ return true; }
				done[p[1]][p[0]] = false;
			}else if(m[p[1]][p[0]] > 1){
				if(f[m[p[1]][p[0]]] > 1){
					--f[m[p[1]][p[0]]];
					done[p[1]][p[0]] = true;
					if(dfs(p, cnt+num, n)){ return true; }
					done[p[1]][p[0]] = false;
					++f[m[p[1]][p[0]]];
				}
			}
			done[pp[1]][pp[0]] = false;
		}else{
			debug(1){
				dbg = "done";
			}
		}
	}

	
	return false;
}

int iddfs(){
	int n = d(s, g);
	done[s[1]][s[0]] = true;
	while(!dfs(s, 0, n)){++n;}
	return n;
}

int[2] P2a(P a){
	return [a[0], a[1]];
}
P a2P(int[2] a){
	return P(a[0], a[1]);
}

void main(){
	int[char] l = [
		'.':0,
		'#':-1,
		'X':2,
	];


	while(true){
		m = m.init;
		done = done.init;
		minist = int.max;
		f = f.init;
		x.next;
		y.next;
		if((x|y)==0x00){ break; }
		
		foreach(i; y.iota){
			string str = next!string();
			int[] d;
			foreach(j, c; str){
				if((c in l)!=null){
					d ~= l[c];
				}else{
					d ~= l['.'];
					if(c=='S'){
						s = P(cast(int)j, i);
					}else{
						g = P(cast(int)j, i);
						assert(c=='G');
					}
				}
			}
			m ~= d;
			
			done ~= repeat(false).take(x).array;
		}
		
		
		int key = l['X'];
		foreach(i; y.iota){
			foreach(j; x.iota){
				if(m[i][j] == l['X']){
					++key;
					f[key] = (XSize(P(j, i))/2)+1;
					fill(P(j, i), key);
				}
			}
		}
		
//		dfs(s, 0).writeln;
		iddfs().writeln;
	}
}


import std.stdio : readln, chomp;
import std.conv : to;
import std.string : split;
shared string[] input;
shared string delim = " ";
T next(T)()
in
{
	assert(hasNext());
}
out
{
	input.popFront;
}
body
{
	return input.front.to!T;
}

void next(T)(ref T v){
	v = next!T();
}

bool hasNext(){
	if(input.length > 0){
		return true;
	}
	
	string str = readln;
	if(str.length > 0){
		input ~= str.chomp.split(delim);
		return true;
	}else{
		return false;
	}
}


void dbg(T...)(T vs)
{
	import std.stdio : stderr;
	foreach(v; vs)
		stderr.write(v.to!string ~ " ");
	stderr.write("\n");
}

T clone(T)(T v){
	T v_;
	static if(isInputRange!(T)){
		foreach(ite; v){
			v_ ~= ite.clone;
		}
	}else{
		v_ = v;
	}
	
	return v_;
}