关于haskell:查找数字A的所有运算符组合,以使结果表达式等于数字B

Finding all combinations of operators in number A so that the result expression equals some number B

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

1
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 * +"。

1
2
3
4
5
6
7
8
9
10
11
12
13
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
2
3
4
5
6
7
8
9
10
11
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]]

使用此方法的一种简单方法是list monad。

1
2
3
4
5
6
7
8
9
10
11
12
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将选择返回由Plus, Sub, Mult组成的长度为length ns - 1的所有可能列表的列表。 然后我们只是测试它们,看它们是否真正等于正确的值。 这并不是很快,但是很容易理解。

因此,我们将分别生成此运算符列表。 现在使用它很容易生成RPN,因为这看起来像是作业,我将把这一部分留给您:)