import System.IO import Control.Monad import Data.Function import Data.List main :: IO () main = do hSetBuffering stdout NoBuffering -- DO NOT REMOVE n <- liftM read getLine :: IO Int -- the number of points used to draw the surface of Mars. pts <- replicateM n $ do -- land_x - X coordinate of a surface point. (0 to 6999) -- land_y - Y coordinate of a surface point. -- By linking all the points together in a sequential fashion, you form the surface of Mars. (land_x:land_y:_) <- liftM (map read . words) getLine :: IO [Double] return (land_x, land_y) let flats = [ ((x0, x1), y0) | ((x0,y0),(x1,y1)) <- zip pts (tail pts), y1 == y0 ] let ((lzX0, lzX1), lzY) = maximumBy (compare `on` (uncurry (-) . fst)) flats interact $ unlines . map (unwords . map show) . calculateOutput (lzX0, lzX1, lzY) . map (map read . words) . lines calculateOutput :: (Double, Double, Double) -> [[Double]] -> [[Int]] calculateOutput (lzX0, lzX1, lzY) = snd . refoldl step (0, 0) where targetX = (lzX0 + lzX1) / 2.0 targetY = lzY + 50 step :: (Double, Double) -> [Double] -> ((Double, Double), Maybe [Int]) step (lostX, lostY) (x:y:hs:vs:f:r:p:_) = ((lostX', lostY'), Just [r', p']) -- x - the current horizontal position (0 to 6999). -- y - the current vertical position. -- hs - the horizontal speed (in m/s), can be negative. -- vs - the vertical speed (in m/s), can be negative. -- f - the quantity of remaining fuel in liters. -- r - the rotation angle in degrees (-90 to 90). -- p - the thrust power (0 to 4). where angle = (r + 90) * (pi/180) (accelX, accelY) = fromPolar (p, angle) targetVS = (-38) accelY' = max 0 $ if y < targetY then 4 else if abs (targetX - x) > (y - targetY) then 3.711 - 0.2*vs else if vs > targetVS then 3 else 3.711 + 0.5*(targetVS^2 - vs^2)/(targetY - y) rangeX = if accelY' >= 4 then 0 else sqrt (4^2 - accelY'^2) decelTimeX = (abs hs + 0.0001) / rangeX projectedX = x + hs * decelTimeX - 0.5 * (signum hs * rangeX) * decelTimeX^2 accelX' = max (-rangeX) $ min rangeX $ 0.2 * (-hs) + 0.02 * (targetX - projectedX) (power', angle') = toPolar (accelX' + lostX, accelY' + lostY) landing = (x >= lzX0 && x <= lzX1) && (y <= lzY + 100) rightDirection = max 0 $ cos (angle - angle') p' = max 0 $ min 4 $ round (rightDirection * power') r' = if landing then 0 else max (-90) $ min 90 $ truncate $ ((angle' * (180/pi)) - 90) (accelX'', accelY'') = fromPolar (fromIntegral p', fromIntegral (r'+90) * (pi/180)) lostX' = 0.8*(accelX'-accelX'') lostY' = 0.8*(accelY'-accelY'') fromPolar :: Floating a => (a, a) -> (a, a) fromPolar (r, th) = (r * cos th, r * sin th) toPolar :: RealFloat a => (a, a) -> (a, a) toPolar (x, y) = (sqrt (x^2 + y^2), atan2 y x) -- Like `unfoldl` combined with `foldl`, or a stateful `map`. refoldl :: (a -> b -> (a, Maybe c)) -> a -> [b] -> (a, [c]) refoldl _ a [] = (a, []) refoldl f a (b:bs) = case f a b of (a', Nothing) -> (a', []) (a', Just c ) -> let ~(a'', cs) = refoldl f a' bs in (a'', c:cs)