Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 解方程a*b=c,其中a、b和c是自然数_Haskell_Equation_Brute Force - Fatal编程技术网

Haskell 解方程a*b=c,其中a、b和c是自然数

Haskell 解方程a*b=c,其中a、b和c是自然数,haskell,equation,brute-force,Haskell,Equation,Brute Force,我有一些自然数c。我想找到所有自然数对a和b,其中a

我有一些自然数
c
。我想找到所有自然数对
a和b
,其中
a
,例如
a*b=c

我有一个解决办法:

solve c = do solveHelper [1..c] c where
                   solveHelper xs c = do
                       x <- xs
                       (division, modulo ) <- return (c `divMod` x)
                       True <- return (modulo  == 0)
                       True <- return (x <= division)
                       return (x, division)

有什么方法可以加速我的代码,或者我应该使用更好的算法吗?

有一种优化方法你不用使用:你不必尝试从
0
c
的每一个值

a
a*b=c
,因此
a*a
,这意味着您只需尝试从
0
sqrt c
的数字。或者,如果不想计算
c
的平方根,可以在
a*a>=c
时立即停止


为此,您可以将
[1..c]
替换为
(takeWhile(\x->x*x
您可以做得更好。其基本思想是:首先,将数字分解;然后枚举分解的分区。每个分区的乘积就是一个解决方案。有很多快速的因子分解算法,但即使是最简单的算法,也会对代码有很大的改进;因此:

factorize :: Integer -> [Integer]
factorize n
    | n < 1 = error "no. =("
    | otherwise = go 2 n
    where
    go p n | p * p > n = [n]
    go p n = case quotRem n p of
        (q, 0) -> p:go p q
        _      -> go (p+1) n
对于不公平的时间安排,我们可以在ghci中进行比较:

*Main> :set +s
*Main> length $ solve (product [1..10])
135
(3.55 secs, 2,884,836,952 bytes)
*Main> length $ divisors (product [1..10])
135
(0.00 secs, 4,612,104 bytes)
*Main> length $ solve (product [1..15])
^CInterrupted. [after several minutes, I gave up]
*Main> length $ divisors (product [1..15])
2016
(0.03 secs, 33,823,168 bytes)
这里,
solve
是你的解决方案,
除数
是我的。为了进行公平的比较,我们应该编制:;我使用了这个程序:

main = print . last . solve . product $ [1..11]

(类似于
除数
代替
求解
),我用
-O2
编译;你的使用了1.367s的总数,我的使用了0.002s的总数。

我想找到
c
的基本因子会更快,然后找到将它们分成两组的所有方法。@ikegami,谢谢你,我尝试了这个解决方案。λlet f c=[(a,b)| a@Shanthakumar你可以避免创建一堆将被过滤掉的
b
值:
let f c=[(a,b)| a@Shanthakumar一旦选择
b
,则
a
只有一个可能的值可以满足
a*b==c
,即
div c b
。我会检查单个值,而不是
[1..b-1]
中的所有值。
*Main> :set +s
*Main> length $ solve (product [1..10])
135
(3.55 secs, 2,884,836,952 bytes)
*Main> length $ divisors (product [1..10])
135
(0.00 secs, 4,612,104 bytes)
*Main> length $ solve (product [1..15])
^CInterrupted. [after several minutes, I gave up]
*Main> length $ divisors (product [1..15])
2016
(0.03 secs, 33,823,168 bytes)
main = print . last . solve . product $ [1..11]