我想在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索引的一定数量的变量。
答案 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
左(第三种情况):
x
(maxN
)选择的最大数量,请记住x * d^2
应为<= n
,因此上限为n / d^2
但我们只对整数感兴趣(所以它是floor
)x
到0
maxN
全部尝试
x
与剩余的ds
一起使用并选择其中一个xs
x
与xs
合并,为当前子问题提供解决方案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]]
答案 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