Bra*_*don 3 algorithm functional-programming clojure
我有一个编程问题,我知道我可以在Ruby中解决,但不知道Clojure中的最佳方法(并且可能有一种优雅的方式来实现这一功能).
因此可以简化问题:
我有一个装满水的3升水桶.铲斗底部有一个洞,即泄漏10 mL/s(即需要300秒/ 5分钟才能清空).我有一杯100毫升的水,我可以用来将新水倒入桶中.
我只能将玻璃杯的全部内容倒入桶中,不会倾倒.倾倒瞬间发生.
计划出一组时间步骤,我可以将水倒入桶中.
我知道有一种非常明显的方法可以使用代数进行此操作,但实际问题涉及随时间变化的"泄漏率",并且"新玻璃体积"并不总是等于100 mL,因此并不简单以封闭的形式解决.
解决这个问题的Ruby方法是使用"Bucket instance"跟踪桶容量,并在多个时间步骤测试以查看桶是否有100 mL的空间.如果是这样,倾倒玻璃,并添加到"桶实例"中的水.继续时间步骤,观察水桶容积.
我希望我所描述的是清楚的.
函数式编程最重要的概念之一是任何没有外部副作用的突变都可以卸载到不可变的函数参数绑定中.
这里模拟的时间和桶的级别是主要的功能参数,并且它们针对每个递归调用进行更新.其他参数被建模为时间函数.我们可以将这些函数中的每一个实际上视为基于时间增量的惰性序列,就像fill-times
函数本身一样.或者使用向量中的查找建模的分段线性方程式,或者是什么.
user>
(defn fill-times
[time level
{:keys [sample-rate calc-bucket-size calc-leak-rate calc-glass-size]
:as params}]
(loop [t time l level]
(let [input-capacity (calc-glass-size time)
bucket-capacity (calc-bucket-size time)
has-room (> (- bucket-capacity l) input-capacity)
leak-delta (* (calc-leak-rate) sample-rate -1)]
(if has-room
(lazy-seq (cons t (fill-times t (+ l input-capacity)
params)))
(recur (+ t sample-rate) (+ l leak-delta))))))
#'user/fill-times
user> (take 50 (fill-times 0 0 {:sample-rate 1
:calc-bucket-size (constantly 3000)
:calc-leak-rate (constantly 10)
:calc-glass-size (constantly 100)}))
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 11 21 31 41 51 61 71 81 91 101 111 121 131 141 151 161 171 181 191 201)
Run Code Online (Sandbox Code Playgroud)
当有足够的空间时,玻璃被倾倒(当然是立即填充),我们记下时间,再次调用该功能以获得以下时间.当没有空间时,我们重复,更新时间和桶级别.结果是(假设无限的)懒惰的玻璃可以排空的时间序列(假设玻璃立即被填充,并立即倾倒).
归档时间: |
|
查看次数: |
265 次 |
最近记录: |