Skip to content

Instantly share code, notes, and snippets.

@NathanHowell
Forked from arocks/rover.hs
Created November 13, 2010 06:29
Show Gist options
  • Save NathanHowell/675145 to your computer and use it in GitHub Desktop.
Save NathanHowell/675145 to your computer and use it in GitHub Desktop.
import Control.Monad (liftM)
import Data.Complex (Complex(..))
import Data.List (foldl, lookup, words)
import Text.Printf (printf)
data Direction = N | E | S | W deriving (Show,Read,Eq)
data Instruction = R | L | M deriving (Show,Read)
data Vector = Vector (Complex Double) (Complex Double)
-- map directions to Complex numbers
direction = [(N, 0:+1), (E, 1:+0), (S, 0:+(-1)), (W, (-1):+0)]
-- ignore the grid size, start processing on the next line
main :: IO ()
main = getLine >> loop
loop :: IO ()
loop = do
coord <- liftM readVector getLine
prog <- liftM readProgram getLine
putStrLn $ showVector $ foldl invoke coord prog
loop
-- execute one instruction
invoke :: Vector -> Instruction -> Vector
invoke (Vector coord angle) instr = case instr of
R -> Vector coord ((0:+(-1))*angle) -- rotate
L -> Vector coord ((0:+ 1) *angle)
M -> Vector (coord+angle) angle -- move in the current direction
-- fragile formatting function, relies on floating point equality tests
-- either switch to Complex Decimal or do the rotations by hand
showVector :: Vector -> String
showVector (Vector (x :+ y) angle) = printf "%.0f %.0f %s" x y (show dir)
where Just dir = lookup angle $ map swap direction
swap (a,b) = (b,a)
-- turn a string like "1 1 N" into a Vector
readVector str = Vector (read x :+ read y) angle
where x:y:dir:_ = words str
Just angle = lookup (read dir) direction
-- map a string of instruction chars "MMMLMR" into Instructions
readProgram :: String -> [Instruction]
readProgram = map (\ x -> read [x])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment