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

本文探讨使用函数式编程解决一个典型的过程性问题——开灯问题,并通过Haskell实现了一个简洁优雅的解决方案。

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

问题:
开灯 问题。 有 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 神秘感逐渐消失,越来越顺手了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

许野平

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值