process.stdin.resume();
process.stdin.setEncoding('utf8');
// your code goes here
(function() {
'use strict';
var Node = function(map_val, visit_flg, cost_val, map_x, map_y, pre_x, pre_y){
this.map_val = map_val;
this.visit_flg = visit_flg;
this.cost_val = cost_val;
this.map_x = map_x;
this.map_y = map_y;
this.pre_x = pre_x;
this.pre_y = pre_y;
};
var matrix_size_str = '';
var matrix = [];
var input_line_check = 0;
require('readline').createInterface({
input: process.stdin,
output: process.stdout
}).on('line', function(line) {
if (input_line_check === 0){
matrix_size_str = line;
input_line_check = 1;
} else {
matrix.push(line);
}
});
process.stdin.on('end', function() {
const ok_area = '.';
const ng_area = '#';
var matrix_size = matrix_size_str.split(' ').map(Number);
const start = [1, 1];
const goal = [matrix_size[0] + 1, matrix_size[1] + 1];
const up = [1, 0];
const right = [0, 1];
const down = [-1, 0];
const left = [0, -1];
const max_cost = 999;
console.log(matrix_size[0] + ' ' + matrix_size[1]);
let horizontal_line = '';
var map = [];
for(let i = 0; i < matrix_size[1]+2; i++){
horizontal_line = horizontal_line + ng_area;
}
map.push(horizontal_line);
for (let matrix_line of matrix){
map.push(ng_area + matrix_line + ng_area);
}
var nodes = [];
map.push(horizontal_line);
for (let i = 0; i < map.length; i++){
let node_line = [];
let map_lines = map[i].split('');
for (let j = 0; j < map_lines.length; j++){
let node = new Node(map_lines[j], false, max_cost, i,j,0,0 );
node_line.push(node);
}
nodes.push(node_line);
}
console.log(nodes.length);
console.log(nodes[0].length);
console.log(nodes[0][0].map_val);
var now_move = [1, 1];
var unsearched_nodes = [];
unsearched_nodes.push(nodes[start[0]][start[1]]);
unsearched_nodes[0].cost_val = 0;
while(true){
let now_cost = max_cost;
let min_cost_index = 0;
// 最小コストのノードを探す
for (let i = 0; i < unsearched_nodes.length; i++){
if(unsearched_nodes[i].cost_val < now_cost){
now_cost = unsearched_nodes[i].cost_val;
min_cost_index = i;
}
}
// 最小コストのノードを取り出し
let node = unsearched_nodes[min_cost_index];
unsearched_nodes.splice(min_cost_index, 1);
node.visit_flg = true;
// 終了判定
if (node.map_x === goal[0] && node.map_y === goal[y]){
console.log(node.cost_val);
break;
}
// up
let next_node = nodes[node.map_x + up[0]][node.map_y + up[1]];
if(next_node.map_val == ok_area || !next_node.visit_flg){
let cost = 0
if((now_move[0] * up[0] + now_move[1] * up[1]) != 0){
cost = node.cost_val;
} else{
cost = node.cost_val + 1;
}
if(cost < next_node.cost_val){
next_node.cost_val = cost;
}
unsearched_nodes.push(next_node);
}
// right
next_node = nodes[node.map_x + right[0]][node.map_y + right[1]];
if(next_node.map_val == ok_area || !next_node.visit_flg){
let cost = 0
if((now_move[0] * right[0] + now_move[1] * right[1]) != 0){
cost = node.cost_val;
} else{
cost = node.cost_val + 1;
}
if(cost < next_node.cost_val){
next_node.cost_val = cost;
}
unsearched_nodes.push(next_node);
}
// down
next_node = nodes[node.map_x + down[0]][node.map_y + down[1]];
if(next_node.map_val == ok_area || !next_node.visit_flg){
let cost = 0
if((now_move[0] * down[0] + now_move[1] * down[1]) != 0){
cost = node.cost_val;
} else{
cost = node.cost_val + 1;
}
if(cost < next_node.cost_val){
next_node.cost_val = cost;
}
unsearched_nodes.push(next_node);
}
// left
next_node = nodes[node.map_x + left[0]][node.map_y + left[1]];
if(next_node.map_val == ok_area || !next_node.visit_flg){
let cost = 0
if((now_move[0] * left[0] + now_move[1] * left[1]) != 0){
cost = node.cost_val;
} else{
cost = node.cost_val + 1;
}
if(cost < next_node.cost_val){
next_node.cost_val = cost;
}
unsearched_nodes.push(next_node);
}
}
});
})();