// 2014/09/12 Tazoe

#include <iostream>
#include <queue>
#include <string>
#include <map>
using namespace std;

struct state{
	string G;
	int N;
};

bool is_over(string G)
{
	bool flg = true;

	for(int i=1; i<G.size(); i++){
		if(G[i]!=G[0]){
			flg = false;
			break;
		}
	}

	return flg;
}

void DFS(char g[12][12], char F, char T, int x, int y)
{
	if(g[y][x]!=F)
		return;

	g[y][x] = T;

	DFS(g, F, T, x-1, y);
	DFS(g, F, T, x+1, y);
	DFS(g, F, T, x, y-1);
	DFS(g, F, T, x, y+1);
}

string fill(string G, char C, int X, int Y)
{
	char g[12][12];
	for(int y=0; y<Y+2; y++){
		for(int x=0; x<X+2; x++){
			g[y][x] = 'N';
		}
	}

	// 文字列から2次元配列へ
	for(int y=0; y<Y; y++){
		for(int x=0; x<X; x++){
			g[y+1][x+1] = G[y*X+x];
		}
	}

	DFS(g, G[0], C, 1, 1);

	// 2次元配列から文字列へ
	for(int y=0; y<Y; y++){
		for(int x=0; x<X; x++){
			G[y*X+x] = g[y+1][x+1];
		}
	}

	return G;
}

int main()
{
	while(true){
		int X, Y;
		cin >> X >> Y;

		if(X==0 && Y==0)
			break;

		string G = "";
		for(int y=0; y<Y; y++){
			for(int x=0; x<X; x++){
				string c;
				cin >> c;

				G += c;
			}
		}

		queue<struct state> que;
		map<string, bool> memo;

		struct state now;
		now.G = G;
		now.N = 0;
		que.push(now);
		memo[now.G] = true;

		while(!que.empty()){
			now = que.front();
			que.pop();

			if(is_over(now.G)){
				cout << now.N << endl;
				break;
			}

			struct state nex1, nex2;

			if(now.G[0]=='R'){
				nex1.G = fill(now.G, 'G', X, Y);
				nex2.G = fill(now.G, 'B', X, Y);
				nex1.N = nex2.N = now.N+1;
			}
			else if(now.G[0]=='G'){
				nex1.G = fill(now.G, 'R', X, Y);
				nex2.G = fill(now.G, 'B', X, Y);
				nex1.N = nex2.N = now.N+1;
			}
			else if(now.G[0]=='B'){
				nex1.G = fill(now.G, 'R', X, Y);
				nex2.G = fill(now.G, 'G', X, Y);
				nex1.N = nex2.N = now.N+1;
			}

			if(memo.find(nex1.G)==memo.end()){
				que.push(nex1);
				memo[nex1.G] = true;
			}
			if(memo.find(nex2.G)==memo.end()){
				que.push(nex2);
				memo[nex2.G] = true;
			}
		}
	}

	return 0;
}