Problem:
Score : 300 points

Problem Statement

Dolphin resides in two-dimensional Cartesian plane, with the positive x-axis pointing right and the positive y-axis pointing up.

Currently, he is located at the point (sx,sy). In each second, he can move up, down, left or right by a distance of 1.

Here, both the x- and y-coordinates before and after each movement must be integers.

He will first visit the point (tx,ty) where sx < tx and sy < ty, then go back to the point (sx,sy), then visit the point (tx,ty) again, and lastly go back to the point (sx,sy).

Here, during the whole travel, he is not allowed to pass through the same point more than once, except the points (sx,sy) and (tx,ty).

Under this condition, find a shortest path for him.

Constraints

-1000 ≤ sx < tx ≤ 1000

-1000 ≤ sy < ty ≤ 1000

sx,sy,tx and ty are integers.

Input

The input is given from Standard Input in the following format:

sx sy tx ty

Output

Print a string S that represents a shortest path for Dolphin.

The i-th character in S should correspond to his i-th movement.

The directions of the movements should be indicated by the following characters:

U: Up

D: Down

L: Left

R: Right

If there exist multiple shortest paths under the condition, print any of them.

Sample Input 1

0 0 1 2

Sample Output 1

UURDDLLUUURRDRDDDLLU

One possible shortest path is:

Going from (sx,sy) to (tx,ty) for the first time: (0,0) → (0,1) → (0,2) → (1,2)

Going from (tx,ty) to (sx,sy) for the first time: (1,2) → (1,1) → (1,0) → (0,0)

Going from (sx,sy) to (tx,ty) for the second time: (0,0) → (-1,0) → (-1,1) → (-1,2) → (-1,3) → (0,3) → (1,3) → (1,2)

Going from (tx,ty) to (sx,sy) for the second time: (1,2) → (2,2) → (2,1) → (2,0) → (2,-1) → (1,-1) → (0,-1) → (0,0)

Sample Input 2

-2 -2 1 1

Sample Output 2

UURRURRDDDLLDLLULUUURRURRDDDLLDL

Solution in Rust (1.15.1) (judge verdict: Accepted)

use std::io::*;
use std::str::FromStr;
use std::collections::HashMap;
use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::collections::HashSet;
use std::cmp;
use std::f64::consts;
use std::cmp::Ordering;
use std::collections::VecDeque; //push_back, pop_front

const MOD: i64 = 1000000007;

fn main() {
    let x0: i32 = read();
    let y0: i32 = read();
    let x1: i32 = read();
    let y1: i32 = read();

    let diffy = (y1-y0).abs();
    let diffx = (x1-x0).abs();

    let mut ans: String = "".to_string();

    for i in 0..diffy {
        ans = format!("{}{}", ans, "U".to_string());
    }

    for i in 0..diffx {
        ans = format!("{}{}", ans, "R".to_string());
    }

    for i in 0..diffy {
        ans = format!("{}{}", ans, "D".to_string());
    }

    for i in 0..diffx {
        ans = format!("{}{}", ans, "L".to_string());
    }

    ans = format!("{}{}", ans, "L".to_string());

    for i in 0..diffy+1 {
        ans = format!("{}{}", ans, "U".to_string());
    }

    for i in 0..diffx+1 {
        ans = format!("{}{}", ans, "R".to_string());
    }

    ans = format!("{}{}", ans, "DR".to_string());

    for i in 0..diffy+1 {
        ans = format!("{}{}", ans, "D".to_string());
    }

    for i in 0..diffx+1 {
        ans = format!("{}{}", ans, "L".to_string());
    }

    ans = format!("{}{}", ans, "U".to_string());

    println!("{}", ans);
}

// 素因数分解
fn prime_factorization(number: u64) -> Vec<u64> {
    let mut result = number;
    for i in 2..((number as f64).sqrt() as u64)+1 {
        if number % i == 0 {
            result = i;
            break;
        }
    }

    if result == number {
        return vec![number];
    } else {
        let mut v1 = vec![result];
        let mut v2 = prime_factorization(number / result);

        v1.append(&mut v2);

        return v1;
    }
}

fn calc_distance(xa: f64, ya: f64, xb: f64, yb: f64)->f64 {
    (f64::powf(xb-xa, 2.0) + f64::powf(yb-ya, 2.0)).sqrt()
}

fn calc_triangle_area(x1: f64, y1: f64, x2: f64, y2: f64, x3: f64, y3: f64) -> f64 {
    1.0/2.0 * ((x1-x3)*(y2-y3)-(x2-x3)*(y1-y3)).abs()
}

fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

// 最大公約数
fn gcd(a: i64, b: i64) -> i64 {
    match b {
        0 => a,
        _ => gcd(b, a % b)
    }
}

// 最小公倍数
fn lcm(a: i64, b: i64) -> i64 {
    let g = gcd(a ,b);
    a / g * b
}

// 階乗-dp (overflow回避で1000000007の余りを使って計算)
fn kaijou_dp(n: i64) -> i64 {
    let mut dp: Vec<i64> = vec![0; n as usize+1];
    dp[0] = 1;
    dp[1] = 1;

    for i in 1..n {
        dp[i as usize+1] = dp[i as usize] % 1000000007 * (i+1)  % 1000000007;
    }
    return dp[n as usize];
}

// 階乗
fn kaijou(n: i64)->i64 {
    if n == 1 {
        return n;
    }
    return n * kaijou(n-1);
}

// 順列全列挙
pub trait LexicalPermutation {
    /// Return `true` if the slice was permuted, `false` if it is already
    /// at the last ordered permutation.
    fn next_permutation(&mut self) -> bool;
}

impl<T> LexicalPermutation for [T] where T: Ord {
    /// Original author in Rust: Thomas Backman <serenity@exscape.org>
    /// let mut data = [1, 2, 3];
    //    let mut permutations = Vec::new();
    //
    //    loop {
    //        permutations.push(data.to_vec());
    //        if !data.next_permutation() {
    //            break;
    //        }
    //    }
    //
    //    println!("{:?}", permutations);
    //    // [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
    fn next_permutation(&mut self) -> bool {
        // These cases only have 1 permutation each, so we can't do anything.
        if self.len() < 2 { return false; }

        // Step 1: Identify the longest, rightmost weakly decreasing part of the vector
        let mut i = self.len() - 1;
        while i > 0 && self[i-1] >= self[i] {
            i -= 1;
        }

        // If that is the entire vector, this is the last-ordered permutation.
        if i == 0 {
            return false;
        }

        // Step 2: Find the rightmost element larger than the pivot (i-1)
        let mut j = self.len() - 1;
        while j >= i && self[j] <= self[i-1]  {
            j -= 1;
        }

        // Step 3: Swap that element with the pivot
        self.swap(j, i-1);

        // Step 4: Reverse the (previously) weakly decreasing part
        self[i..].reverse();

        true
    }
}

//iより小さい数字の数 = lower_bound(&a, i) as i64;
//iより大きい数字の数 = n - upper_bound(&c, i) as i64;
fn lower_bound<T: Ord>(vec: &Vec<T>, x: T) -> usize {
    let (mut left, mut right): (i64, i64) = (-1, vec.len() as i64);

    while (right - left) > 1 {
        let mid = (right + left) / 2;

        if x <= vec[mid as usize] {
            right = mid;
        } else {
            left = mid;
        }
    }

    return right as usize;
}

fn upper_bound<T: Ord>(vec: &Vec<T>, x: T) -> usize {
    let (mut left, mut right): (i64, i64) = (-1, vec.len() as i64);

    while (right - left) > 1 {
        let mid = (right + left) / 2;

        if x < vec[mid as usize] {
            right = mid;
        } else {
            left = mid;
        }
    }

    return right as usize;
}