use std::str::FromStr;

#[derive(Clone, Copy, PartialEq, Eq)]
enum Cardinal {
    N,
    S,
    E,
    W,
}

#[derive(Clone, Copy, PartialEq, Eq)]
enum Direction {
    C(Cardinal, u16),
    T(i8),
    F(u16),
}

#[derive(Debug)]
enum ParseDirectionError {
    I(std::num::ParseIntError),
    D(char),
    Z,
}

impl From<std::num::ParseIntError> for ParseDirectionError {
    fn from(src: std::num::ParseIntError) -> Self {
        Self::I(src)
    }
}

impl std::fmt::Display for ParseDirectionError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ParseDirectionError::I(e) => e.fmt(f),
            ParseDirectionError::D(c) => write!(f, "Unrecognised direction code: {}", c),
            ParseDirectionError::Z => write!(f, "Empty string"),
        }
    }
}

impl FromStr for Direction {
    type Err = ParseDirectionError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.len() == 0 {
            Err(Self::Err::Z)?;
        };
        let (c, ns) = s.split_at(1);
        match c {
            "N" => {
                let d = ns.parse::<u16>()?;
                Ok(Direction::C(Cardinal::N, d))
            }
            "S" => {
                let d = ns.parse::<u16>()?;
                Ok(Direction::C(Cardinal::S, d))
            }
            "E" => {
                let d = ns.parse::<u16>()?;
                Ok(Direction::C(Cardinal::E, d))
            }
            "W" => {
                let d = ns.parse::<u16>()?;
                Ok(Direction::C(Cardinal::W, d))
            }
            "L" => {
                let d = ns.parse::<i16>()?;
                Ok(Direction::T(((4 - (d / 90)) % 4) as i8))
            }
            "R" => {
                let d = ns.parse::<i16>()?;
                Ok(Direction::T(((d / 90) % 4) as i8))
            }
            "F" => {
                let d = ns.parse::<u16>()?;
                Ok(Direction::F(d))
            }
            _ => Err(ParseDirectionError::D(c.chars().next().unwrap())),
        }
    }
}

#[derive(Clone, Copy, PartialEq, Eq)]
struct Ship {
    x: i32,
    y: i32,
    bearing: Cardinal,
    waypoint_x: i32,
    waypoint_y: i32,
}

impl Ship {
    fn new() -> Self {
        Ship {
            x: 0,
            y: 0,
            bearing: Cardinal::E,
            waypoint_x: 10,
            waypoint_y: -1,
        }
    }

    fn step(&mut self, dir: Direction, revised: bool) {
        if revised {
            match dir {
                Direction::C(c, d) => match c {
                    Cardinal::N => {
                        self.waypoint_y -= d as i32;
                    }
                    Cardinal::S => {
                        self.waypoint_y += d as i32;
                    }
                    Cardinal::E => {
                        self.waypoint_x += d as i32;
                    }
                    Cardinal::W => {
                        self.waypoint_x -= d as i32;
                    }
                },
                Direction::T(qt) => match qt % 4 {
                    0 => {}
                    1 => {
                        let (x, y) = (self.waypoint_x, self.waypoint_y);
                        self.waypoint_x = -y;
                        self.waypoint_y = x;
                    }
                    2 => {
                        let (x, y) = (self.waypoint_x, self.waypoint_y);
                        self.waypoint_x = -x;
                        self.waypoint_y = -y;
                    }
                    3 => {
                        let (x, y) = (self.waypoint_x, self.waypoint_y);
                        self.waypoint_x = y;
                        self.waypoint_y = -x;
                    }
                    _ => panic!("_ % 4 >= 4 !???"),
                },
                Direction::F(d) => {
                    self.x += self.waypoint_x * d as i32;
                    self.y += self.waypoint_y * d as i32;
                }
            }
        } else {
            match dir {
                Direction::C(c, d) => match c {
                    Cardinal::N => {
                        self.y -= d as i32;
                    }
                    Cardinal::S => {
                        self.y += d as i32;
                    }
                    Cardinal::E => {
                        self.x += d as i32;
                    }
                    Cardinal::W => {
                        self.x -= d as i32;
                    }
                },
                Direction::T(qt) => {
                    let sqt: i8 = match self.bearing {
                        Cardinal::N => 8,
                        Cardinal::S => 10,
                        Cardinal::E => 9,
                        Cardinal::W => 11,
                    };
                    self.bearing = match (sqt + qt) % 4 {
                        0 => Cardinal::N,
                        1 => Cardinal::E,
                        2 => Cardinal::S,
                        3 => Cardinal::W,
                        _ => panic!("_ % 4 >= 4 !???"),
                    };
                }
                Direction::F(d) => self.step(Direction::C(self.bearing, d), false),
            }
        }
    }
}

fn main() {
    use std::io::BufRead;
    let args: Vec<_> = std::env::args().collect();
    let mut ship = Ship::new();
    let file = std::io::BufReader::new(
        std::fs::File::open(<String as AsRef<std::path::Path>>::as_ref(&args[1])).unwrap(),
    );
    let revised = match args[2].as_ref() {
        "1" => false,
        "2" => true,
        _ => panic!("Version number (1 or 2) expected"),
    };
    for line in file.lines() {
        ship.step(line.unwrap().parse().unwrap(), revised);
    }
    println!("{}", ship.x.abs() + ship.y.abs());
}