haskell 基础题解(48)

小机器人行走

【题目】小机器人站还原点(0,0)位置,头朝北方。建立直角坐标系,x的正方向为东,y的正方向为北。现在给小机人发指令。指令只有3种:
“L” 左转90度
“R” 右转90度
“数字” 表示在当前方向行走x米
请编程,对一个指令序列,输出小机器人的最终位置。

从haskell 的角度看,当前位置和当前头的朝向就是一个初始状态。从这个初始状态开始,对指令序列进行折叠,得到最终的状态。

上代码:

data HeadDir = D北 | D东 | D南 | D西
type Pos = (Int, Int)

robotWalk :: [String] -> Pos
robotWalk xs = fst $ foldl f ((0,0),D北) xs
    where
    f (p,hd) s = case s of
        "L" -> (p, turnL hd)
        "R" -> (p, turnR hd)
        dis -> (go p hd (read dis), hd)
    turnL D北 = D西
    turnL D西 = D南
    turnL D南 = D东
    turnL D东 = D北
    turnR = turnL . turnL . turnL
    go (x,y) hd dis = case hd of
        D北 -> (x, y+dis)
        D东 -> (x+dis, y)
        D南 -> (x, y-dis)
        D西 -> (x-dis, y)

main :: IO ()
main = do 
    s <- getContents
    print . robotWalk . words $ s

还是老套路。当情况比较少的时候,枚举比分析规律更可靠些。
右转定义为左转 3 次,能偷懒就偷懒…

假设转的度数不是 90 度, 而是任意角度, 怎么办?
这时数学就能发挥作用了。可以用复数表达机器人的位置。
用单位向量表达头的朝向。转向就是对单位向量的乘法。
行走就是对当前位置向量的加法运算…

上个复数版本的

import Data.Complex

robotWalk :: [String] -> Complex Double
robotWalk = f (0 :+ 0) (0 :+ 1)
    where 
    f c位 _ [] = c位
    f c位 c向 (x:xs) = case x of
        "L" -> f c位 (c向 * i1) xs
        "R" -> f c位 (c向 * i2) xs 
        dis -> let k = read dis :+ 0 in f (c位 + c向 * k) c向 xs 
    i1 = 0 :+ 1
    i2 = 0 :+ (-1)

main :: IO ()
main = do 
    s <- getContents
    print . robotWalk . words $ s

这个写法与头脑中的直观感觉更近些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值