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;
int[][] f;
bool[][] done;
int x;
int y;

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

P s;
P g;

int XSize(P e, int cnt){
	m[e[1]][e[0]] = 1;
	int max_ = cnt;
	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){
				max_ = max(max_, XSize(neo.a2P, cnt+1));
			}
		}
	}
	return max_;
}

void fill(P e, int num){
	m[e[1]][e[0]] = num;
	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]]!=num){
				fill(neo.a2P, num);
			}
		}
	}
}

int minist;
int dfs(P e, int cnt){
	if(e==g){return cnt;}
	if(minist < cnt){
		return cnt;
	}
	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;
	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]]){
				int res = int.max;
				if(m[neo[1]][neo[0]]==0){
					res = dfs(neo.a2P, cnt+1);
				}else if(m[neo[1]][neo[0]] > 1){
					fill(neo.a2P, m[neo[1]][neo[0]]-1);
					res = dfs(neo.a2P, cnt+1);
					fill(neo.a2P, m[neo[1]][neo[0]]+1);
				}
				min_ = min(min_, res);
				minist = min(minist, min_);
			}
		}
	}
	done[e[1]][e[0]] = false;
	
	return min_;
}

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;
		f = f.init;
		done = done.init;
		minist = int.max;
		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;
		}
		
		
		foreach(i; y.iota){
			foreach(j; x.iota){
				if(m[i][j] == l['X']){
					fill(P(j, i), cast(int)(cast(double)(XSize(P(j, i), 1))/2.)+1);
				}
			}
		}
		
		dfs(s, 0).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_;
}