-- {-# LANGUAGE BangPatterns #-}
-- {-# LANGUAGE ScopedTypeVariables #-}
-- {-# LANGUAGE FlexibleContexts #-}
-- {-# LANGUAGE ViewPatterns #-}
-- {-# LANGUAGE OverloadedStrings #-}

import qualified Data.Vector as V
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
-- import qualified Data.Vector.Algorithms.Merge as VAM
-- import qualified Data.Heap as HP
import qualified Data.ByteString.Char8 as BC
import qualified Data.Map as MP
import qualified Data.Set as ST
import qualified Data.Sequence as SQ
import Data.Array
import Data.Array.Unboxed
import Data.Array.ST
import Data.Array.IO
import Data.Maybe
import Data.Ratio
import Data.Char
import Data.Bits
import Data.List
import Data.Tuple
import Data.Functor
import Data.IORef
import Data.STRef
import Control.Applicative
import Control.Monad
import Control.Monad.ST
import Debug.Trace

--------------------------------------------------------------------------
solve mp
    | cond1 && cond2 =  "Yes"
    | otherwise = "No"
    where
        cond1 = (n > 0 && s > 0) || (n == 0 && s == 0)
        cond2 = (e > 0 && w > 0) || (e == 0 && w == 0)
        Just e = MP.lookup 'E' mp
        Just w = MP.lookup 'W' mp
        Just n = MP.lookup 'N' mp
        Just s = MP.lookup 'S' mp

main = do
    mp <- foldl' (\m l -> MP.insertWith (+) l 1 m) (MP.fromList [('E',0),('W',0),('N',0),('S',0)]) <$> str
    putStrLn $ solve mp
--------------------------------------------------------------------------

-- Input Util
int :: IO Int
int = readLn 

double :: IO Double
double = readLn 

str :: IO String
str = getLine

strBC :: IO BC.ByteString
strBC = BC.getLine

sLineToIntL :: IO [Int]
sLineToIntL = getLine >>= return . map read . words

sLineToDoubleL :: IO [Double]
sLineToDoubleL = getLine >>= return . map read . words

sLineToIntV :: Int -> IO (VU.Vector Int)
sLineToIntV n = BC.getLine >>= return . VU.unfoldrN n (BC.readInt . BC.dropWhile isSpace)

sLineToDoubleV :: Int -> IO (VU.Vector Double)
sLineToDoubleV n = BC.getLine >>= return . VU.fromList . map (read . BC.unpack) . BC.words

mLinesToIntL :: Int -> IO [Int]
mLinesToIntL n = replicateM n readLn

mLinesToDoubleL :: Int -> IO [Double]
mLinesToDoubleL n = replicateM n readLn

mLinesToIntV :: Int -> IO (VU.Vector Int)
mLinesToIntV n = VU.replicateM n readLn

mLinesToDoubleV :: Int -> IO (VU.Vector Double)
mLinesToDoubleV n = VU.replicateM n (BC.getLine >>= return . read . BC.unpack)

mLinesToTupleL :: Int -> IO [(Int, Int)]
mLinesToTupleL n = replicateM n (getLine >>= return . (\[a,b] -> (a,b)) . map read . words)

mLinesToTupleV :: Int -> IO (VU.Vector (Int, Int))
mLinesToTupleV n = VU.replicateM n $ do
    bs <- strBC
    let
        Just (a, bs') = BC.readInt $ BC.dropWhile isSpace bs
        Just (b, _) = BC.readInt $ BC.dropWhile isSpace bs'
    return (a,b)
    
mLinesToTripleV :: Int -> IO (VU.Vector (Int, Int, Int))
mLinesToTripleV n = VU.replicateM n $ do
    bs <- strBC
    let
        Just (a, bs') = BC.readInt $ BC.dropWhile isSpace bs
        Just (b, bs'') = BC.readInt $ BC.dropWhile isSpace bs'
        Just (c, _) = BC.readInt $ BC.dropWhile isSpace bs''
    return (a,b,c)

-- others
strToChr :: String -> Char
strToChr [x] = x

chrToStr :: Char -> String
chrToStr x = [x]

m1 :: Int -> Int
m1 x = subtract 1 x

toDouble :: Int -> Double
toDouble x = fromIntegral x

toInt :: Double -> Int
toInt x = floor x

Measured memory_bytes: 764