Haskell 学习笔记-12:过程的函数式描述——开灯问题

有一种说法,说是函数式编程不擅长解决过程式问题,我特地找一个过程性问题试一试。

问题:
开灯 问题。 有 n 盏灯, 编号 为 1 ~ n。 第 1 个人 把 所有 灯 打开, 第 2 个人 按下 所有 编号 为 2 的 倍数 的 开关( 这些 灯 将被 关掉), 第 3 个人 按下 所有 编号 为 3 的 倍数 的 开关( 其中 关掉 的 灯 将被 打开, 开着 的 灯 将被 关闭), 依此类推。 一 共有 k 个人, 问 最后 有 哪些 灯 开着? 输入 n 和 k, 输出 开着 的 灯 的 编号。 k ≤ n ≤ 1000。

样 例 输入: 7 3
样 例 输出: 1 5 6 7

openLights n 0 = []
openLights n k = 
    let
        lightOn = openLights n (k - 1)
        lightOff = [ x | x <- [1.. n], not (elem x lightOn)]
        a = [ x | x <- lightOff, mod x k == 0]
        b = [ x | x <- lightOn, mod x k /= 0]
    in
        [x | x <- [1.. n], elem x (a ++ b)]


--------------------------------------------------------------
//run it ...
>> openLights 7 0
[]
>> openLights 7 1
[1,2,3,4,5,6,7]
>> openLights 7 2
[1,3,5,7]
>> openLights 7 3
[1,5,6,7]
>> openLights 7 4
[1,4,5,6,7]
>> openLights 7 5
[1,4,6,7]
>> openLights 7 6
[1,4,7]
>> openLights 7 7
[1,4]
>> openLights 7 8
[1,4]

>> openLights 20 1
[1,4,9,16,18,19,20]

其实并不难,感觉函数式编程对于过程描述也很方便。通过练习,Haskell 神秘感逐渐消失,越来越顺手了。

猜你喜欢

转载自blog.csdn.net/quicmous/article/details/80754992