import Data.Function (on)
import Data.List (sortBy)
import Control.Monad (replicateM, liftM)

data Direction = LEFT | RIGHT | STRAIGHT
               deriving (Show, Eq)

data Pt = Pt (Double, Double)
        deriving (Show, Eq, Ord)

isTurned :: Pt -> Pt -> Pt -> Direction
isTurned (Pt (ax, ay)) (Pt (bx, by)) (Pt (cx, cy)) = case sign of
                                                        EQ -> STRAIGHT
                                                        LT -> RIGHT
                                                        GT -> LEFT
    where sign = compare ((bx - ax) * (cy - ay)) ((by - ay) * (cx - ax))

gScan :: [Pt] -> [Pt]
gScan pts
    | length pts >= 3 = scan [pt0] rests
    | otherwise       = pts
    where
        pt0 = foldr bottomLeft (Pt (1/0,1/0)) pts where
            bottomLeft pa pb = case ord of
                                    LT -> pa
                                    GT -> pb
                                    EQ -> pa
                       where ord = (compare `on` (\ (Pt (x,y)) -> (y,x))) pa pb

        rests = tail (sortBy (compare `on` compkey pt0) pts) where
              compkey (Pt (x0,y0)) (Pt (x,y)) = (atan2 (y - y0) (x - x0),
                                                abs (x - x0))

        scan [p0] (p1:ps)
            | isTurned pz p0 p1 == STRAIGHT = [pz, p0]
            where pz = last ps

        scan (x:xs) (y:z:rsts) = case isTurned x y z of
            RIGHT    -> scan xs (x:z:rsts)
            LEFT     -> scan (y:x:xs) (z:rsts)
            STRAIGHT -> scan (x:xs) (z:rsts)

        scan xs [z] = z : xs

getInput :: IO [Pt]
getInput = do
    n <- readLn
    replicateM n (liftM ((\(a:b:_) -> Pt (read a :: Double, read b :: Double)) . words) getLine)

main = do
    input <- getInput
    let output = gScan input
    print $ length output
    mapM (putStrLn . (\(Pt (x,y)) -> show (round x) ++ " " ++ show (round y))) output