public static int solve(int[][] solution, int i, int j, int path) {
	
        if (j == 0)
            return path + (i + 1) * (int) Math.pow(10, solution.length - (i + 1));
    
		// find best of up, mid, and down
		int up;
		int upIndex;
        if (i - 1 >= 0) {
            up = solution[i - 1][j - 1];
			upIndex = i - 1;
        }
        else {
			up = solution[solution.length - 1][j - 1];
			upIndex = solution.length - 1;
		}
		int mid = solution[i][j - 1];
		int down;
		int downIndex;
		if (i + 1 < solution.length) {
			down = solution[i + 1][j - 1];
			downIndex = i + 1;
		}
		else {
			down = solution[0][j - 1];
			downIndex = 0;
		}
		
		int min = Math.min(up, Math.min(mid, down));
		if (path == -1)
			path = (i + 1);
		else
			path += (i + 1) * Math.pow(10, solution.length - (i + 1));
		
        int bestpath = Integer.MAX_VALUE;
		// go up, mid, and down
		if (solution[upIndex][j - 1] == min)
			bestpath = Math.min(bestpath, solve(solution, upIndex, j - 1, path));
		if (solution[i][j - 1] == min)
			bestpath = Math.min(bestpath, solve(solution, i, j - 1, path));
		if (solution[downIndex][j - 1] == min)
			bestpath = Math.min(bestpath, solve(solution, downIndex, j - 1, path));
		
		return bestpath;
	
	}