use std::{io::{stdin, Read}, collections::HashSet};
fn main() {
let mut stdin = stdin();
let mut buf: String = String::new();
stdin.read_to_string(&mut buf).unwrap();
let mut visited: HashSet<Point> = HashSet::new();
let mut head: Point = Point::new(0, 0);
// let mut tail: Point = head;
let mut tails: [Point; 9] = [head; 9];
for line in buf.split("\n") {
let dir = match line.chars().next().unwrap() {
'U' => Point::new(0, 1),
'D' => Point::new(0, -1),
'L' => Point::new(-1, 0),
'R' => Point::new(1, 0),
_ => Point::new(0, 0)
};
let num = line[2..].parse::<i32>().unwrap();
for _ in 0..num {
// visited.insert(tail);
// let (h, t) = mov(head, tail, dir);
// head = h; tail = t;
visited.insert(tails[8]);
let (h, ts) = mov2(head, tails, dir);
head = h; tails = ts;
}
}
// visited.insert(tail);
visited.insert(tails[8]);
println!("{}", visited.len());
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
struct Point {
x: i32,
y: i32
}
impl Point {
fn new(x: i32, y: i32) -> Self {
Self { x, y }
}
}
// fn mov(head: Point, tail: Point, by: Point) -> (Point, Point) { // update tail (p1)
// let new_head = Point::new(head.x + by.x, head.y + by.y);
// let new_tail = if (new_head.x - tail.x).pow(2) > 1 || (new_head.y - tail.y).pow(2) > 1 {
// head
// } else { tail };
// return (new_head, new_tail);
// }
fn mov2(head: Point, tails: [Point; 9], by: Point) -> (Point, [Point; 9]) { // update tails (p2)
let new_head = Point::new(head.x + by.x, head.y + by.y);
let mut new_tails: [Point; 9] = [Point::new(0, 0); 9];
for i in 0..9 {
let last_tail = tails[i];
let h = if i == 0 { new_head } else { new_tails[i-1] };
let diff = Point::new(h.x - last_tail.x, h.y - last_tail.y);
new_tails[i] = if diff.x.pow(2) > 1 || diff.y.pow(2) > 1 { // this is clearly the best way to go about things
Point::new(last_tail.x + diff.x.signum(), last_tail.y + diff.y.signum()) // seems to work ok enough
} else { last_tail };
}
(new_head, new_tails)
}