pub trait FromFragment: Sized {
    fn from_fragment(s: &str) -> Result<Self, String>;
}
impl FromFragment for String {
    fn from_fragment(s: &str) -> Result<String, String> {
        Ok(s.to_owned())
    }
}
macro_rules ! impl_from_fragment { ( $ ( $ t : ty ) * ) => { $ ( impl FromFragment for $ t { fn from_fragment ( s : & str ) -> Result <$ t , String > { use std :: str :: FromStr ; <$ t >:: from_str ( s ) . map_err ( | _ | { format ! ( "cannot parse \"{}\" as {}" , s , stringify ! ( $ t ) ) } ) } } ) * } ; }
impl_from_fragment ! ( isize usize i8 u8 i16 u16 i32 u32 i64 u64 f64 ) ;
pub trait FromLine: Sized {
    fn from_line(line: &str) -> Result<Self, String>;
}
impl<T: FromFragment> FromLine for T {
    fn from_line(line: &str) -> Result<T, String> {
        T::from_fragment(line.trim_right_matches('\n'))
    }
}
impl<T: FromFragment> FromLine for Vec<T> {
    #[doc = " Reads arbitrary number of `T`s."]
    fn from_line(line: &str) -> Result<Vec<T>, String> {
        let mut result = Vec::new();
        for fragment in line.trim_right_matches('\n').split_whitespace() {
            match T::from_fragment(fragment) {
                Ok(v) => result.push(v),
                Err(msg) => {
                    return Err(format!(
                        "fragment {} of line \"{}\": {}",
                        result.len() + 1,
                        line,
                        msg
                    ))
                }
            }
        }
        Ok(result)
    }
}
macro_rules ! impl_from_line_for_tuples { ( $ t : ident $ var : ident $ count : expr ) => ( ) ; ( $ t : ident $ var : ident $ count : expr ; $ ( $ inner_t : ident $ inner_var : ident $ inner_count : expr ) ;* ) => { impl_from_line_for_tuples ! ( $ ( $ inner_t $ inner_var $ inner_count ) ;* ) ; impl <$ t : FromFragment , $ ( $ inner_t : FromFragment ) ,*> FromLine for ( $ t , $ ( $ inner_t ) ,* ) { # [ allow ( unused_assignments ) ] fn from_line ( line : & str ) -> Result < ( $ t , $ ( $ inner_t ) ,* ) , String > { let fragments : Vec <& str > = line . trim_right_matches ( '\n' ) . split_whitespace ( ) . collect ( ) ; if fragments . len ( ) != $ count { return Err ( format ! ( "line \"{}\" has {} fragments, expected {}" , line , fragments . len ( ) , $ count ) ) ; } let mut iter = fragments . iter ( ) ; let mut n = 1 ; let $ var = <$ t >:: from_fragment ( iter . next ( ) . unwrap ( ) ) . map_err ( | msg | { format ! ( "fragment {} of line \"{}\": {}" , n , line , msg ) } ) ?; n += 1 ; $ ( let $ inner_var = <$ inner_t >:: from_fragment ( iter . next ( ) . unwrap ( ) ) . map_err ( | msg | { format ! ( "fragment {} of line \"{}\": {}" , n , line , msg ) } ) ?; n += 1 ; ) * Ok ( ( $ var , $ ( $ inner_var ) ,* ) ) } } } }
impl_from_line_for_tuples ! ( T4 x4 4 ; T3 x3 3 ; T2 x2 2 ; T1 x1 1 ) ;
#[macro_export]
macro_rules ! read { ( ) => { let mut line = String :: new ( ) ; std :: io :: stdin ( ) . read_line ( & mut line ) . unwrap ( ) ; } ; ( $ pat : pat = $ t : ty ) => { let mut line = String :: new ( ) ; std :: io :: stdin ( ) . read_line ( & mut line ) . unwrap ( ) ; let $ pat = <$ t >:: from_line ( & line ) . unwrap ( ) ; } ; ( $ ( $ pat : pat = $ t : ty ) ,+ ) => { read ! ( ( $ ( $ pat ) ,* ) = ( $ ( $ t ) ,* ) ) ; } ; }
#[macro_export]
macro_rules ! readls { ( $ ( $ pat : pat = $ t : ty ) ,+ ) => { $ ( read ! ( $ pat = $ t ) ; ) * } }
#[macro_export]
macro_rules ! read_loop { ( $ pat : pat = $ t : ty ; $ block : block ) => { use std :: io :: BufRead ; let stdin = std :: io :: stdin ( ) ; for line in stdin . lock ( ) . lines ( ) { let line = line . expect ( "read from stdin failed" ) ; let $ pat = <$ t >:: from_line ( & line ) . unwrap ( ) ; $ block } } ; ( $ ( $ pat : pat = $ t : ty ) ,* ; $ block : block ) => { read_loop ! ( ( $ ( $ pat ) ,* ) = ( $ ( $ t ) ,* ) ; $ block ) ; } }
#[macro_export]
macro_rules ! readn_loop { ( $ n : expr ; $ pat : pat = $ t : ty ; $ block : block ) => { use std :: io :: BufRead ; let stdin = std :: io :: stdin ( ) ; { let lock = stdin . lock ( ) ; for _ in 0 ..$ n { let line = String :: new ( ) ; lock . read_line ( & mut line ) . expect ( "read from stdin failed" ) ; let $ pat = <$ t >:: from_line ( & line ) . unwrap ( ) ; $ block } } } ; ( $ n : expr ; $ ( $ pat : pat = $ t : ty ) ,* ; $ block : block ) => { read_times_loop ! ( $ n ; ( $ ( $ pat ) ,* ) = ( $ ( $ t ) ,* ) ; $ block ) ; } }
use std::fmt::{self, Display, Formatter};
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
#[derive(Clone, Copy, Debug, PartialEq)]
struct Vec2<T> {
    x: T,
    y: T,
}
impl<T> Vec2<T> {
    fn new(x: T, y: T) -> Vec2<T> {
        Vec2 { x: x, y: y }
    }
}
impl<T: Display> Display for Vec2<T> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{} {}", self.x, self.y)
    }
}
impl<T: Add> Add for Vec2<T> {
    type Output = Vec2<T::Output>;
    fn add(self, rhs: Vec2<T>) -> Self::Output {
        Vec2::new(self.x + rhs.x, self.y + rhs.y)
    }
}
impl<T: AddAssign> AddAssign for Vec2<T> {
    fn add_assign(&mut self, rhs: Vec2<T>) {
        self.x += rhs.x;
        self.y += rhs.y;
    }
}
impl<T: Sub> Sub for Vec2<T> {
    type Output = Vec2<T::Output>;
    fn sub(self, rhs: Vec2<T>) -> Self::Output {
        Vec2::new(self.x - rhs.x, self.y - rhs.y)
    }
}
impl<T: SubAssign> SubAssign for Vec2<T> {
    fn sub_assign(&mut self, rhs: Vec2<T>) {
        self.x -= rhs.x;
        self.y -= rhs.y;
    }
}
impl<T: Neg> Neg for Vec2<T> {
    type Output = Vec2<T::Output>;
    fn neg(self) -> Self::Output {
        Vec2::new(-self.x, -self.y)
    }
}
macro_rules ! impl_mul_vec2 { ( $ ( $ t : ty ) * ) => { $ ( impl Mul < Vec2 <$ t >> for $ t { type Output = Vec2 <<$ t as Mul >:: Output >; fn mul ( self , rhs : Vec2 <$ t > ) -> Self :: Output { Vec2 :: new ( self * rhs . x , self * rhs . y ) } } ) * } }
impl_mul_vec2 ! ( i8 u8 i16 u16 i32 u32 i64 u64 f32 f64 ) ;
impl<T: Copy + Mul> Mul<T> for Vec2<T> {
    type Output = Vec2<T::Output>;
    fn mul(self, rhs: T) -> Self::Output {
        Vec2::new(self.x * rhs, self.y * rhs)
    }
}
impl<T: Copy + MulAssign> MulAssign<T> for Vec2<T> {
    fn mul_assign(&mut self, rhs: T) {
        self.x *= rhs;
        self.y *= rhs;
    }
}
impl<T: Copy + Div> Div<T> for Vec2<T> {
    type Output = Vec2<T::Output>;
    fn div(self, rhs: T) -> Self::Output {
        Vec2::new(self.x / rhs, self.y / rhs)
    }
}
impl<T: Copy + DivAssign> DivAssign<T> for Vec2<T> {
    fn div_assign(&mut self, rhs: T) {
        self.x /= rhs;
        self.y /= rhs;
    }
}

fn main() {
    read!(x1 = i16, y1 = i16, x2 = i16, y2 = i16);
    let p1 = Vec2::new(x1, y1);
    let p2 = Vec2::new(x2, y2);

    let delta = p2 - p1;
    let delta_rot = Vec2::new(-delta.y, delta.x);

    println!("{} {}", p2 + delta_rot, p1 + delta_rot);
}


Measured memory_bytes: 4352