use std::{io::{stdin, Read}, collections::LinkedList};

fn main() {
    let mut stdin = stdin();
    let mut buf: Vec<u8> = vec![];
    stdin.read_to_end(&mut buf).unwrap();
    let chars: Vec<Vec<u8>> = buf.split(|n| *n == b'\n').map(|f| f.into()).collect();
    let mut st: (usize, usize) = (0,0);
    let mut fi: (usize, usize) = (0,0);
    for i in 0..chars.len() {
        for j in 0..chars[0].len() {
            if chars[i][j] == b'S' {
                st = (i, j);
            } else if chars[i][j] == b'E' {
                fi = (i, j);
            }
        }
    }

    let elevations: Vec<Vec<i8>> = chars.iter().map(|row| {
        row.iter().map(|c| {
            (match c {
                b'S' => 0,
                b'E' => 25,
                _ => c - b'a'
            }) as i8
        }).collect()
    }).collect();

    let mut visited: Vec<Vec<bool>> = vec![vec![false; elevations[0].len()]; elevations.len()];
    let mut queue: LinkedList<((usize, usize), u32)> = LinkedList::new();
    // visited[st.0][st.1] = true; // part 1
    // queue.push_back((st, 0));
    visited[fi.0][fi.1] = true; // part 2
    queue.push_back((fi, 0));

    while !queue.is_empty() {
        let (p, depth) = queue.pop_front().unwrap();
        let c_el = elevations[p.0][p.1];
        // if p == fi { // part 1
        if c_el == 0 { // part 2
            println!("{}", depth); return;
        }
        for i in [(p.0+1 - 1, p.1+1), (p.0+1 + 1, p.1+1), (p.0+1, p.1+1 - 1), (p.0+1, p.1+1 + 1)] {
            if i.0 == 0 || i.1 == 0 { continue; }
            let j = (i.0-1, i.1-1);
            if j.0 >= elevations.len() || j.1 >= elevations[0].len() { continue; }
            // if elevations[j.0][j.1] - c_el <= 1 && !visited[j.0][j.1] { // part 1
            if c_el - elevations[j.0][j.1] <= 1 && !visited[j.0][j.1] { // part 2
                visited[j.0][j.1] = true;
                queue.push_back((j, depth + 1));
            }
        }
    }
}