查找数字A中运算符的所有组合,以便结果表达式等于某个数字B.

时间:2013-11-11 14:53:27

标签: haskell combinatorics

任务是在 n - 数字A中找到(n-1)运算符(+, - ,*)的所有可能组合,以便表达式的重新分配等于数字B.表达式从左到右计算。例如:

We have number A=123 and B=5 : 1*2+3=5

我猜这个任务可能与波兰表示法和解析器的一些用法有关。 所以它像是: 我得到数字123,使它成为字符串“3 2 1”,然后尝试所有可能的运算符组合,如:“3 2 1 + +”“3 2 1 - - ”“3 2 1 * *”“3 2 1 * - “等等,检查它是否等于5.但问题是我真的不明白如何正确找到所有组合。 我也写了一个函数,它使数字中的字符串成为一个计算表达式的函数“3 2 1 * +”。

exprCounting :: String -> Integer
exprCounting = head . foldl stackAnalyzing [] . words 
  where
    stackAnalyzing (x:y:ss) "+" = (x+y):ss
    stackAnalyzing (x:y:ss) "-" = (y-x):ss
    stackAnalyzing (x:y:ss) "*" = (x*y):ss
    stackAnalyzing   ss  number = read number : ss

toWordString :: Integer -> String               
toWordString = addSpace . show
  where
    addSpace [] = []
    addSpace (x:xs) = [x] ++ " " ++ addSpace xs

所以任何人都可以给我关于解决此任务的方法或我应该使用什么工具的建议。

1 个答案:

答案 0 :(得分:2)

所以你想要这样的东西

import Control.Monad
data Op = Plus
        | Sub
        | Mult
   deriving(Eq, Show)
denote :: Op -> (Integer -> Integer -> Integer)
denote Plus = (+)
denote Sub  = (-)
denote Mult = (*)

combos :: [Integer] -> Integer -> [[Op]]

所以combos [1, 2, 3] 5 == [[Mult, Plus]]

使用它的一个简单方法是列表monad。

eval :: [Integer] -> [Op] -> Integer
eval (n1:n2:ns) (o:os) = eval (denote o n1 n2 : ns) os
eval [n1]       []     = n1
eval  _         _      = error "eval: Length mismatch"
-- Or, with folds
eval' ns os = case foldl step ns os of
  [n] -> n
  _ -> error "eval: Length mismatch"
  where step (n1 : n2 : ns) o  = denote o n1 n2 : ns

combos ns target = filter ( (==target) . eval nums) os
  where os = replicateM (length ns -1) [Plus, Sub, Mult]

replicateM会选择返回由length ns - 1组成的所有可能长度为Plus, Sub, Mult的列表的列表。然后我们测试它们以确定它们是否实际上等于正确的值。这不是非常快,但理解起来非常简单。

所以我们分别生成这个运算符列表。现在使用它可以很容易地生成RPN,因为这看起来像家庭作业,我会把那部分留给你:)