简体   繁体   English

Haskell的分解警卫

[英]Factorizing guards in Haskell

This code takes a sum of money as Int and returns a list of tuples indicating the smallest amount of necessary bills or coins needed to amount to that sum. 该代码将一笔款项作为Int并返回一个元组列表,该列表表示达到该笔款项所需的最小量必要票据或硬币。

purse :: Int -> [(String, Int)]
purse x
  | x == 0       = [("$0", 0)]
  | div x 200 >= 1  = before x 200 : after x 200
  | div x 100 >= 1  = before x 100 : after x 100
  | div x 50 >= 1   = before x 50 : after x 50
  | div x 20 >= 1   = before x 20 : after x 20
  | div x 10 >= 1   = before x 10 : after x 10
  | div x 5 >= 1    = before x 5 : after x 5
  | div x 2 >= 1    = before x 2 : after x 2
  | div x 1 >= 1    = before x 1 : after x 1
  where before x y = ("$" ++ show x, div x y)
        after x y  = if mod x y > 0
                        then purse (mod x y)
                        else []

For instance, purse 18 would return: 例如, purse 18将返回:

[("$10", 1), ("$5", 1), ("$2", 1), ("$1", 1)]

My question is: could this series of guards be removed/factorized and the function simply work based on a list of bills/coins, like where bills = [200, 100, 50, 20...] ? 我的问题是:可以删除/分解这一系列的防护措施,并且该功能是否可以根据钞票/硬币列表(例如where bills = [200, 100, 50, 20...]简单地工作?

In Python I would do something like (not the exact working solution but you get the idea): 在Python中,我会做类似的事情(不是确切的工作解决方案,但您会明白):

purse(x):
    for bill in [200, 100, 50, 20, 10, 5, 2, 1]:
        if x / bill >= 1:
            return [x // bill] + purse(x % bill)
purse = go [200,100,50,20,10,5,2,1] where
  go (c:cs) x | x < c = go cs x
  go (c:cs) x = ("$" ++ show c, div x c) : go cs (mod x c)
  go [] _ = []

purse x = filter ((>0) . snd) $ snd $ mapAccumL foo x [200,100,50,20,10,5,2,1]
  where foo x c = (mod x c, ("$" ++ show c, div x c))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM