#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <functional>
#include <cassert>

typedef long long ll;
using namespace std;

#define mod 1000000007
#define INF 1000000000
#define LLINF 2000000000000000000LL

#define SIZE 100000

int main(){
    int r,c,sr,sc,gr,gc;
    char a[30][31];
    bool visit[31][31]={0};
    
    scanf("%d%d",&r,&c);
    
    for(int i=0;i<r;i++){
        scanf("%s",a[i]);
    }
    
    for(int i=0;i<r;i++){
        for(int j=0;j<c;j++){
            if(a[i][j]=='S'){
                sr = i;
                sc = j;
            }
            if(a[i][j]=='G'){
                gr = i;
                gc = j;
            }
        }
    }
    
    priority_queue<pair<int,pair<int,int> > > pq;
    
    pq.push({0,{sr,sc}});
    
    while(1){
        pair<int,pair<int,int> > p = pq.top();
        pq.pop();
        
        int nowcost = p.first;
        int nowr = p.second.first;
        int nowc = p.second.second;
        
        if(visit[nowr][nowc]) continue;
        visit[nowr][nowc] = true;
        
        if(nowr==gr && nowc==gc){
            cout << -nowcost << endl;
            break;
        }
        
        int addcost;
        
        //up
        addcost = 0;
        for(int i=1;i<=3;i++){
            if(a[nowr-i][nowc]=='#' || nowr-i<0) break;
            
            if(a[nowr-i][nowc]=='o'){
                addcost+=1;
            }else if(a[nowr-i][nowc]=='x'){
                addcost+=100000;
            }else{
                addcost+=2;
            }
            
            pq.push({nowcost-min(addcost,2+i),{nowr-i,nowc}});
        }
        
        //down
        addcost = 0;
        for(int i=1;i<=3;i++){
            if(a[nowr+i][nowc]=='#' || nowr+i>=r) break;
            
            if(a[nowr+i][nowc]=='o'){
                addcost+=1;
            }else if(a[nowr+i][nowc]=='x'){
                addcost+=100000;
            }else{
                addcost+=2;
            }
            
            pq.push({nowcost-min(addcost,2+i),{nowr+i,nowc}});
        }
        
        //left
        addcost = 0;
        for(int i=1;i<=3;i++){
            if(a[nowr][nowc-i]=='#' || nowc-i<0) break;
            
            if(a[nowr][nowc-i]=='o'){
                addcost+=1;
            }else if(a[nowr][nowc-i]=='x'){
                addcost+=100000;
            }else{
                addcost+=2;
            }
            
            pq.push({nowcost-min(addcost,2+i),{nowr,nowc-i}});
        }
        
        //right
        addcost = 0;
        for(int i=1;i<=3;i++){
            if(a[nowr][nowc+i]=='#' || nowc+i>=c) break;
            
            if(a[nowr][nowc+i]=='o'){
                addcost+=1;
            }else if(a[nowr][nowc+i]=='x'){
                addcost+=100000;
            }else{
                addcost+=2;
            }
            
            pq.push({nowcost-min(addcost,2+i),{nowr,nowc+i}});
        }
        
    }
    
    return 0;
}


//number of permutation
#define MAX_DATASIZE 7
/*
 int encode(int *data,int size){
 bool used[MAX_DATASIZE+1]={0};
 int num = 0;
 int t = 1;
 
 for(int i=1;i<=size;i++) t*=i;
 
 for(int i=size;i>=1;i--){
 t/=i;
 
 int s = 0;
 for(int j=1;j<data[size-i];j++){
 if(used[j]) s++;
 }
 
 used[data[size-i]] = true;
 
 num += s*t;
 }
 
 return num;
 }
 
 void decode(int num,int *data,int size){
 bool used[MAX_DATASIZE+1]={0};
 int t=1;
 
 for(int i=1;i<=size;i++) t*=i;
 
 for(int i=size;i>=1;i--){
 t/=i;
 
 int s = num/t;
 
 for(int j=1;;j++){
 if(used[j]==false){
 if(s==0){
 
 data[size-i] = j;
 used[j] = true;
 break;
 }
 s--;
 }
 }
 num %= t;
 }
 }
 */

Measured memory_bytes: 1216