#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

enum DIR{
	North,
	East,
	South,
	West,
};

enum MIGITE{
	Mae,
	Migi_Mae,
	Migi,
	Migi_Ushiro,
};

int H,W,min_Time[50][50][4][4];
char map[50][51];

struct Info{
	Info(){
		row = col = count = 0;
		dir = North;
		migite_loc = Mae;
		migite_row = migite_col = 0;
		visit_count = 0;
	}

	Info(int arg_row,int arg_col,DIR arg_dir,MIGITE arg_migite_loc,int arg_count,int arg_migite_row,int arg_migite_col,int arg_visit_count){
		row = arg_row;
		col = arg_col;
		dir = arg_dir;
		migite_loc = arg_migite_loc;
		count = arg_count;
		migite_row = arg_migite_row;
		migite_col = arg_migite_col;
		visit_count = arg_visit_count;
	}
	void copy(bool arg_visited[50][50]){
		for(int a = 0; a < H; a++){
			for(int b = 0; b < W; b++){
				visited[a][b] = arg_visited[a][b];
			}
		}
	}

	int row,col,count,migite_row,migite_col,visit_count;
	DIR dir;
	MIGITE migite_loc;
	bool visited[50][50];
};

int diff_row_migite_N[4] = {-1,-1,0,1},diff_col_migite_N[4] = {0,1,1,1};
int diff_row_migite_E[4] = {0,1,1,1},diff_col_migite_E[4] = {1,1,0,-1};
int diff_row_migite_S[4] = {1,1,0,-1},diff_col_migite_S[4] = {0,-1,-1,-1};
int diff_row_migite_W[4] = {0,-1,-1,-1},diff_col_migite_W[4] = {-1,-1,0,1};
int diff_row_wall[8] = {-1,-1,-1,0,0,1,1,1},diff_col_wall[8] = {-1,0,1,-1,1,-1,0,1};



struct Data{
	int row,col;
};

bool rangeCheck(int row,int col){
	if(row >= 0 && row <= H-1 && col >= 0 && col <= W-1)return true;
	else{
		return false;
	}
}

DIR turn_right(DIR dir){
	switch(dir){
	case North:
		return East;
	case East:
		return South;
	case South:
		return West;
	case West:
		return North;
	}
	return North; //must not reach here
}

DIR turn_left(DIR dir){
	switch(dir){
	case North:
		return West;
	case East:
		return North;
	case South:
		return East;
	case West:
		return South;
	}
	return North; //must not reach here
}

bool isMigiteLeave(DIR next_dir,int next_row,int next_col,int migite_row,int migite_col){

	int tmp_diff_row[4],tmp_diff_col[4];

	switch(next_dir){
	case North:
		for(int i = 0; i < 4; i++){
			tmp_diff_row[i] = diff_row_migite_N[i];
			tmp_diff_col[i] = diff_col_migite_N[i];
		}
		break;
	case East:
		for(int i = 0; i < 4; i++){
			tmp_diff_row[i] = diff_row_migite_E[i];
			tmp_diff_col[i] = diff_col_migite_E[i];
		}
		break;
	case South:
		for(int i = 0; i < 4; i++){
			tmp_diff_row[i] = diff_row_migite_S[i];
			tmp_diff_col[i] = diff_col_migite_S[i];
		}
		break;
	case West:
		for(int i = 0; i < 4; i++){
			tmp_diff_row[i] = diff_row_migite_W[i];
			tmp_diff_col[i] = diff_col_migite_W[i];
		}
		break;
	}

	for(int i = 0; i < 4; i++){
		if(migite_row == next_row + tmp_diff_row[i] && migite_col == next_col + tmp_diff_col[i]){ //next_row,next_col?????????????±???????????????????????????????
			return false;
		}
	}

	return true;
}


MIGITE findMigitePos(DIR dir,int row,int col,int migite_row,int migite_col){

	int tmp_diff_row[4],tmp_diff_col[4];

	switch(dir){
	case North:
		for(int i = 0; i < 4; i++){
			tmp_diff_row[i] = diff_row_migite_N[i];
			tmp_diff_col[i] = diff_col_migite_N[i];
		}
		break;
	case East:
		for(int i = 0; i < 4; i++){
			tmp_diff_row[i] = diff_row_migite_E[i];
			tmp_diff_col[i] = diff_col_migite_E[i];
		}
		break;
	case South:
		for(int i = 0; i < 4; i++){
			tmp_diff_row[i] = diff_row_migite_S[i];
			tmp_diff_col[i] = diff_col_migite_S[i];
		}
		break;
	case West:
		for(int i = 0; i < 4; i++){
			tmp_diff_row[i] = diff_row_migite_W[i];
			tmp_diff_col[i] = diff_col_migite_W[i];
		}
		break;
	}

	for(int i = 0; i < 4; i++){
		if(migite_row == row + tmp_diff_row[i] && migite_col == col + tmp_diff_col[i]){
			switch(i){
			case 0:return Mae;
			case 1:return Migi_Mae;
			case 2:return Migi;
			case 3:return Migi_Ushiro;
			}
		}
	}
	return Mae; //Must not reach here
}

void func(){

	Info first;
	first.count = 0;

	for(int i = 0; i < H; i++){
		for(int k = 0; k < W; k++)first.visited[i][k] = false;
	}

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			for(int a = 0; a < 4; a++){
				for(int b = 0; b < 4; b++)min_Time[row][col][a][b] = BIG_NUM;
			}
		}
	}


	for(int i = 0; i < H; i++){
		scanf("%s",map[i]);
		for(int k = 0; k < W; k++){
			switch(map[i][k]){
			case '^':
				first.row = i;
				first.col = k;
				first.migite_loc = Migi;
				first.dir = North;
				first.migite_row = i;
				first.migite_col = k+1;
				break;
			case 'v':
				first.row = i;
				first.col = k;
				first.migite_loc = Migi;
				first.dir = South;
				first.migite_row = i;
				first.migite_col = k-1;
				break;
			case '<':
				first.row = i;
				first.col = k;
				first.migite_loc = Migi;
				first.dir = West;
				first.migite_row = i-1;
				first.migite_col = k;
				break;
			case '>':
				first.row = i;
				first.col = k;
				first.migite_loc = Migi;
				first.dir = East;
				first.migite_row = i+1;
				first.migite_col = k;
				break;
			}
		}
	}

	min_Time[first.row][first.col][first.dir][first.migite_loc] = 0;
	first.visited[first.row][first.col] = true;
	first.visit_count++;

	int next_row,next_col,tmp_row,tmp_col;
	DIR next_dir;
	MIGITE tmp_migite_loc;

	int tmp_diff_row[4],tmp_diff_col[4];

	queue<Info> Q;
	int ans = BIG_NUM;

	Q.push(first);

	while(!Q.empty()){

		if(map[Q.front().row][Q.front().col] == 'G'){
			ans = min(ans,Q.front().visit_count);
			Q.pop();
		}else if(Q.front().count > min_Time[Q.front().row][Q.front().col][Q.front().dir][Q.front().migite_loc]){
			Q.pop();
		}else{

			switch(Q.front().dir){
			case North:
				next_row = Q.front().row-1;
				next_col = Q.front().col;
				break;
			case East:
				next_row = Q.front().row;
				next_col = Q.front().col+1;
				break;
			case South:
				next_row = Q.front().row+1;
				next_col = Q.front().col;
				break;
			case West:
				next_row = Q.front().row;
				next_col = Q.front().col-1;
				break;
			}

			next_dir = turn_right(Q.front().dir);

			if(isMigiteLeave(next_dir,Q.front().row,Q.front().col,Q.front().migite_row,Q.front().migite_col) == false){

				Info new_info;
				new_info.migite_loc = findMigitePos(next_dir,Q.front().row,Q.front().col,Q.front().migite_row,Q.front().migite_col);
				new_info.row = Q.front().row;
				new_info.col = Q.front().col;
				new_info.count = Q.front().count;
				new_info.dir = next_dir;
				new_info.migite_row = Q.front().migite_row;
				new_info.migite_col = Q.front().migite_col;
				new_info.copy(Q.front().visited);
				new_info.visit_count = Q.front().visit_count;
				if(min_Time[new_info.row][new_info.col][new_info.dir][new_info.migite_loc] > new_info.count){
					min_Time[new_info.row][new_info.col][new_info.dir][new_info.migite_loc] = new_info.count;
					Q.push(new_info);
				}
			}else{

				switch(Q.front().dir){
				case North:
					for(int i = 0; i < 4; i++){
						tmp_diff_row[i] = diff_row_migite_N[i];
						tmp_diff_col[i] = diff_col_migite_N[i];
					}
					break;
				case East:
					for(int i = 0; i < 4; i++){
						tmp_diff_row[i] = diff_row_migite_E[i];
						tmp_diff_col[i] = diff_col_migite_E[i];
					}
					break;
				case South:
					for(int i = 0; i < 4; i++){
						tmp_diff_row[i] = diff_row_migite_S[i];
						tmp_diff_col[i] = diff_col_migite_S[i];
					}
					break;
				case West:
					for(int i = 0; i < 4; i++){
						tmp_diff_row[i] = diff_row_migite_W[i];
						tmp_diff_col[i] = diff_col_migite_W[i];
					}
					break;
				}

				for(int i = 0; i < 4; i++){
					tmp_row = Q.front().row + tmp_diff_row[i];
					tmp_col = Q.front().col + tmp_diff_col[i];

					if(rangeCheck(tmp_row,tmp_col) == false || map[tmp_row][tmp_col] == '#'){
						for(int k = 0; k < 8; k++){
							if(Q.front().migite_row+diff_row_wall[k] == tmp_row && Q.front().migite_col+diff_col_wall[k] == tmp_col){

								tmp_migite_loc = findMigitePos(Q.front().dir,Q.front().row,Q.front().col,tmp_row,tmp_col);
								if(min_Time[Q.front().row][Q.front().col][Q.front().dir][tmp_migite_loc] > Q.front().count){
									min_Time[Q.front().row][Q.front().col][Q.front().dir][tmp_migite_loc] = Q.front().count;

									Info new_info;
									new_info.migite_loc = tmp_migite_loc;
									new_info.row = Q.front().row;
									new_info.col = Q.front().col;
									new_info.count = Q.front().count;
									new_info.dir = next_dir;
									new_info.migite_row = tmp_row;
									new_info.migite_col = tmp_col;
									new_info.copy(Q.front().visited);
									new_info.visit_count = Q.front().visit_count;

									Q.push(new_info);
								}
								break;
							}
						}
					}
				}

			}

			next_dir = turn_left(Q.front().dir);

			if(isMigiteLeave(next_dir,Q.front().row,Q.front().col,Q.front().migite_row,Q.front().migite_col) == false){

				Info new_info;
				new_info.migite_loc = findMigitePos(next_dir,Q.front().row,Q.front().col,Q.front().migite_row,Q.front().migite_col);
				new_info.row = Q.front().row;
				new_info.col = Q.front().col;
				new_info.count = Q.front().count;
				new_info.dir = next_dir;
				new_info.migite_row = Q.front().migite_row;
				new_info.migite_col = Q.front().migite_col;
				new_info.copy(Q.front().visited);
				new_info.visit_count = Q.front().visit_count;
				if(min_Time[new_info.row][new_info.col][new_info.dir][new_info.migite_loc] > new_info.count){
					min_Time[new_info.row][new_info.col][new_info.dir][new_info.migite_loc] = new_info.count;
					Q.push(new_info);
				}
			}else{

				switch(Q.front().dir){
				case North:
					for(int i = 0; i < 4; i++){
						tmp_diff_row[i] = diff_row_migite_N[i];
						tmp_diff_col[i] = diff_col_migite_N[i];
					}
					break;
				case East:
					for(int i = 0; i < 4; i++){
						tmp_diff_row[i] = diff_row_migite_E[i];
						tmp_diff_col[i] = diff_col_migite_E[i];
					}
					break;
				case South:
					for(int i = 0; i < 4; i++){
						tmp_diff_row[i] = diff_row_migite_S[i];
						tmp_diff_col[i] = diff_col_migite_S[i];
					}
					break;
				case West:
					for(int i = 0; i < 4; i++){
						tmp_diff_row[i] = diff_row_migite_W[i];
						tmp_diff_col[i] = diff_col_migite_W[i];
					}
					break;
				}

				for(int i = 0; i < 4; i++){
					tmp_row = Q.front().row + tmp_diff_row[i];
					tmp_col = Q.front().col + tmp_diff_col[i];

					if(rangeCheck(tmp_row,tmp_col) == false || map[tmp_row][tmp_col] == '#'){
						for(int k = 0; k < 8; k++){
							if(Q.front().migite_row+diff_row_wall[k] == tmp_row && Q.front().migite_col+diff_col_wall[k] == tmp_col){

								tmp_migite_loc = findMigitePos(Q.front().dir,Q.front().row,Q.front().col,tmp_row,tmp_col);
								if(min_Time[Q.front().row][Q.front().col][Q.front().dir][tmp_migite_loc] > Q.front().count){
									min_Time[Q.front().row][Q.front().col][Q.front().dir][tmp_migite_loc] = Q.front().count;
									Info new_info;
									new_info.migite_loc = tmp_migite_loc;
									new_info.row = Q.front().row;
									new_info.col = Q.front().col;
									new_info.count = Q.front().count;
									new_info.dir = Q.front().dir;
									new_info.migite_row = tmp_row;
									new_info.migite_col = tmp_col;
									new_info.copy(Q.front().visited);
									new_info.visit_count = Q.front().visit_count;

									Q.push(new_info);
								}
								break;
							}
						}
					}
				}

			}


			if(rangeCheck(next_row,next_col) == false || map[next_row][next_col] == '#'){
				//Do nothing
			}else{

				next_dir = Q.front().dir;

				if(isMigiteLeave(next_dir,next_row,next_col,Q.front().migite_row,Q.front().migite_col) == false){

					Info new_info;
					new_info.migite_loc = findMigitePos(next_dir,next_row,next_col,Q.front().migite_row,Q.front().migite_col);
					new_info.row = next_row;
					new_info.col = next_col;
					new_info.count = Q.front().count+1;
					new_info.dir = next_dir;
					new_info.migite_row = Q.front().migite_row;
					new_info.migite_col = Q.front().migite_col;
					new_info.copy(Q.front().visited);
					if(new_info.visited[next_row][next_col]){
						new_info.visit_count = Q.front().visit_count;
					}else{
						new_info.visited[next_row][next_col] = true;
						new_info.visit_count = Q.front().visit_count+1;
					}

					if(min_Time[new_info.row][new_info.col][new_info.dir][new_info.migite_loc] > new_info.count){
						min_Time[new_info.row][new_info.col][new_info.dir][new_info.migite_loc] = new_info.count;
						Q.push(new_info);
					}
				}else{

					switch(Q.front().dir){
					case North:
						for(int i = 0; i < 4; i++){
							tmp_diff_row[i] = diff_row_migite_N[i];
							tmp_diff_col[i] = diff_col_migite_N[i];
						}
						break;
					case East:
						for(int i = 0; i < 4; i++){
							tmp_diff_row[i] = diff_row_migite_E[i];
							tmp_diff_col[i] = diff_col_migite_E[i];
						}
						break;
					case South:
						for(int i = 0; i < 4; i++){
							tmp_diff_row[i] = diff_row_migite_S[i];
							tmp_diff_col[i] = diff_col_migite_S[i];
						}
						break;
					case West:
						for(int i = 0; i < 4; i++){
							tmp_diff_row[i] = diff_row_migite_W[i];
							tmp_diff_col[i] = diff_col_migite_W[i];
						}
						break;
					}

					for(int i = 0; i < 4; i++){
						tmp_row = Q.front().row + tmp_diff_row[i];
						tmp_col = Q.front().col + tmp_diff_col[i];

						if(rangeCheck(tmp_row,tmp_col) == false || map[tmp_row][tmp_col] == '#'){
							for(int k = 0; k < 8; k++){
								if(Q.front().migite_row+diff_row_wall[k] == tmp_row && Q.front().migite_col+diff_col_wall[k] == tmp_col){
									//??????????°?????????????
									tmp_migite_loc = findMigitePos(Q.front().dir,Q.front().row,Q.front().col,tmp_row,tmp_col);
									if(min_Time[Q.front().row][Q.front().col][next_dir][tmp_migite_loc] > Q.front().count){
										min_Time[Q.front().row][Q.front().col][next_dir][tmp_migite_loc] = Q.front().count;

										Info new_info;
										new_info.migite_loc = tmp_migite_loc;
										new_info.row = Q.front().row;
										new_info.col = Q.front().col;
										new_info.count = Q.front().count;
										new_info.dir = Q.front().dir;
										new_info.migite_row = tmp_row;
										new_info.migite_col = tmp_col;
										new_info.copy(Q.front().visited);
										new_info.visit_count = Q.front().visit_count;

										Q.push(new_info);
									}
									break;
								}
							}
						}
					}

				}
			}
			Q.pop();
		}
	}

	if(ans != BIG_NUM){
		printf("%d\n",ans);
	}else{
		printf("-1\n");
	}

}

int main(){

	scanf("%d %d",&H,&W);
	func();

	return 0;
}

Measured memory_bytes: 3000