用给定集合索引的变量求解和生成和方程(Haskell)

时间:2016-05-03 22:16:07

标签: variables haskell indexing linear-equation

我想在Haskell中解决以下问题:

设n为自然数,让A = [d_1 , ..., d_r]为一组正数。

我想找到以下等式的所有正解:

n = Sum d_i^2 x_i

例如,如果n= 12和集合A= [1,2,3]。我想在自然数上解决以下等式:

x+4y+9z=12.

足以使用以下代码:

[(x,y,z) | x<-[0..12], y<-[0..12], z<-[0..12], x+4*y+9*z==12]

我的问题是如果n没有修复,并且集合A也没有修复。我不知道如何生产&#34;由集合A索引的一定数量的变量。

2 个答案:

答案 0 :(得分:3)

您可以使用带do的递归调用代替列表推导,而不是list-monad。

由于你必须正确处理边缘情况,这有点棘手,我允许自己优化一点:

solve :: Integer -> [Integer] -> [[Integer]]
solve 0 ds = [replicate (length ds) 0]
solve _ [] = []
solve n (d:ds) = do
  let maxN = floor $ fromIntegral n / fromIntegral (d^2)
  x <- [0..maxN]
  xs <- solve (n - x * d^2) ds
  return (x:xs)

它的工作原理如下:

  • 跟踪第一个参数中的剩余总和
  • 当这个总和为0时,显然已经完成并且只需要返回0(第一种情况) - 它将返回一个0的列表,其长度与ds相同
  • 如果剩余的金额不是0但是没有d,我们就麻烦了,因为没有解决方案(第二种情况) - 请注意,没有解决方案只是空列表
  • 在其他所有情况下,我们都有一个非零n(余额)和一些ds左(第三种情况):
    • 现在查找您可以为xmaxN)选择的最大数量,请记住x * d^2应为<= n,因此上限为n / d^2但我们只对整数感兴趣(所以它是floor
    • x0
    • maxN全部尝试
    • 在将x与剩余的ds一起使用并选择其中一个xs
    • 时查找剩余总和的所有解
    • xxs合并,为当前子问题提供解决方案

list-monad的绑定将为你处理其余部分;)

实施例

λ> solve 12 [1,2,3]
[[0,3,0],[3,0,1],[4,2,0],[8,1,0],[12,0,0]]

λ> solve 37 [2,3,4,6]
[[3,1,1,0],[7,1,0,0]]

备注

在处理负数时,这会失败 - 如果你需要那些你需要介绍更多的情况 - 我确定你已经弄明白了(在这一点上,它比Haskell真的更重要)

答案 1 :(得分:1)

一些提示:

最终你想要用这个签名写一个函数:

solutions :: Int -> [Int] -> [ [Int] ]

示例:

solutions 4 [1,2]  == [ [4,0], [0,1] ]
  -- two solutions: 4 = 4*1^2 + 0*2^2,  4 = 0*1^2 + 1*2^2

solutions 22 [2,3]  == [ [1,2] ]
  -- just one solution: 22 = 1*2^2 + 2*3^2

solutions 10 [2,3]  == [ ]
  -- no solutions

步骤2.根据列表的结构递归定义{{​​1}}:

solutions