函数式编程解百鸡问题

2022-06-07  本文已影响0人  redexpress

问题

百鸡问题来自《张邱建算经》,原文:今有鸡翁一直钱五,鸡母一直前三,鸡雏三直钱一,凡百钱买百鸡。问:鸡翁、母、雏各几何?

这个问题有三个未知数,但却只能列两个方程。属于不确定方程问题。如果直接推算比较复杂,可以参考“百鸡问题”史话,而用编程实现比较直接。

命令式编程

用命令式编程有两种解法,下面是Python程序

方法一:多重循环

for x in range(0, 21):
    for y in range(0, 34):
        z = 100 - x - y
        if x * 5 + y * 3 + z / 3 == 100:
            print(x, y, z)

方法二:列表演算

思路同方法一,Python 等编程语言支持列表演算,可以用一行代码写完

[print(x, y, 100 - x - y) for x in range(21) for y in range(34) if x*5+y*3+(100-x-y)/3 == 100]

方法三:单循环加逻辑推理

只循环公鸡,剩下的钱买小鸡,鸡的总量超过100的,每超过8只就把9只小鸡换成1只母鸡,这样总量就是100。

for x in range(21):
    z = (20 - x) * 15
    y = (x + z - 100) // 8
    if (x + z - 100) % 8 == 0 and (x + z >= 100):
        print(x, y, 100-x-y)

函数式编程

函数式编程语言没有for/while循环语句,可以通过递归实现,下面是Scheme代码:

(define (chicken)
  (chicken-iter 0 0))

(define (chicken-iter a b)
  (cond [(eq? 100 (+ (* a 5) (* b 3) (/ (- 100 a b) 3)))
         (printf "~s ~s ~s\n" a b (- 100 a b))])
  (cond [(and (eq? a (truncate 100/5)) (eq? b (truncate 100/3)))
         (display "")]
        [else (if (eq? b (truncate 100/3))
          (chicken-iter (+ a 1) 0)
          (chicken-iter a (+ b 1)))]))

(chicken)

而Haskell支持列表演算,代码可以很简短:

[(x, y, 100-x-y) | x <- [0..20], y<-[0..33], x*5+y*3+(100-x-y) `div` 3 == 100, (100-x-y) `mod` 3==0]

即使你不了解Haskell,代码也不难理解。第三种方法的函数式编程感兴趣读者可以自行完成。

上一篇下一篇

猜你喜欢

热点阅读