F# F中的欧拉问题27#

F# F中的欧拉问题27#,f#,functional-programming,primes,F#,Functional Programming,Primes,我一直在努力完成Euler项目,但这一个似乎让我难堪。首先,代码运行时间太长(在我的机器上可能需要几分钟,但更重要的是,它返回了错误的答案,尽管我在浏览了一段时间后,确实无法发现算法有任何错误) 这是我当前的解决方案代码 /// Checks number for primality. let is_prime n = [|1 .. 2 .. sqrt_int n|] |> Array.for_all (fun x -> n % x <> 0) /// Mem

我一直在努力完成Euler项目,但这一个似乎让我难堪。首先,代码运行时间太长(在我的机器上可能需要几分钟,但更重要的是,它返回了错误的答案,尽管我在浏览了一段时间后,确实无法发现算法有任何错误)

这是我当前的解决方案代码

/// Checks number for primality.
let is_prime n = 
    [|1 .. 2 .. sqrt_int n|] |> Array.for_all (fun x -> n % x <> 0)

/// Memoizes a function.
let memoize f = 
    let cache = Dictionary<_, _>()
    fun x -> 
        let found, res = cache.TryGetValue(x)
        if found then
            res
        else
            let res = f x
            cache.[x] <- res
            res

/// Problem 27
/// Find a quadratic formula that produces the maximum number of primes for consecutive values of n.
let problem27 n =
    let is_prime_mem = memoize is_prime
    let range = [|-(n - 1) .. n - 1|]
    let natural_nums = Seq.init_infinite (fun i -> i)
    range |> Array.map (fun a -> (range |> Array.map (fun b ->
        let formula n = n * n + a * n + b
        let num_conseq_primes = natural_nums |> Seq.map (fun n -> (n, formula n))
                                |> Seq.find (fun (n, f) -> not (is_prime_mem f)) |> fst
        (a * b, num_conseq_primes)) |> Array.max_by snd)) |> Array.max_by snd |> fst

printn_any (problem27 1000)
///检查数字的素性。
设is_素数n=
[| 1..2..sqrt|u int n |]|>Array.for|u all(乐趣x->n%x 0)
///记忆一个函数。
让我们回忆一下f=
让缓存=字典()
乐趣x->
let found,res=cache.TryGetValue(x)
如果找到了
物件
其他的
设res=fx
缓存[x]i)
range>Array.map(乐趣a->(range>Array.map)(乐趣b->
设公式n=n*n+a*n+b
设num_conseq_primes=natural_nums |>Seq.map(fun->(n,公式n))
|>Seq.find(fun(n,f)->not(is_prime_mem f))->fst
(a*b,num_conseq_primes))|>Array.max_by snd))|>Array.max_by snd |>fst
打印任何(问题27 1000)
关于如何a)让该算法实际返回正确答案(我认为我至少采取了可行的方法)和b)提高性能的任何提示,因为它明显超过了Project Euler常见问题解答中规定的“一分钟规则”。对于函数式编程,我有点新手,所以我对如何用更有效的解决方案来考虑这个问题的任何建议也会被理解。

< p>您可以使用概率算法加快您的“iSyPrimy”函数。最简单的快速算法之一是算法。

您可以使用概率算法来加速“is_prime”函数。最简单的快速算法之一是算法。

两条注释:

  • 您可以利用
    b
    必须为素数这一事实。这是因为问题要求
    n=0,1,2,…
    因此,
    公式(0)
    必须以素数开头,但是
    公式(0)=b
    ,因此,b必须是素数

  • 我不是F#程序员,但在我看来,代码根本不尝试n=0。当然,这不符合问题的要求,即
    n
    必须从
    0
    开始,因此产生正确答案的可能性很小

  • 两点意见:

  • 您可以利用
    b
    必须为素数这一事实。这是因为问题要求
    n=0,1,2,…
    因此,
    公式(0)
    必须以素数开头,但是
    公式(0)=b
    ,因此,b必须是素数

  • 我不是F#程序员,但在我看来,代码根本不尝试n=0。当然,这不符合问题的要求,即
    n
    必须从
    0
    开始,因此产生正确答案的可能性很小


  • 是的,在检查了所有的助手函数是否都在做它们应该做的事情之后,我终于找到了一个有效的解决方案

    /// Checks number for primality.
    let is_prime n = 
        [|1 .. 2 .. sqrt_int n|] |> Array.for_all (fun x -> n % x <> 0)
    
    /// Memoizes a function.
    let memoize f = 
        let cache = Dictionary<_, _>()
        fun x -> 
            let found, res = cache.TryGetValue(x)
            if found then
                res
            else
                let res = f x
                cache.[x] <- res
                res
    
    /// Problem 27
    /// Find a quadratic formula that produces the maximum number of primes for consecutive values of n.
    let problem27 n =
        let is_prime_mem = memoize is_prime
        let range = [|-(n - 1) .. n - 1|]
        let natural_nums = Seq.init_infinite (fun i -> i)
        range |> Array.map (fun a -> (range |> Array.map (fun b ->
            let formula n = n * n + a * n + b
            let num_conseq_primes = natural_nums |> Seq.map (fun n -> (n, formula n))
                                    |> Seq.find (fun (n, f) -> not (is_prime_mem f)) |> fst
            (a * b, num_conseq_primes)) |> Array.max_by snd)) |> Array.max_by snd |> fst
    
    printn_any (problem27 1000)
    
    首先,is_素数函数是完全错误的(感谢Dimitre Novatchev让我看到了这一点)。我不太清楚我是如何达到我在原始问题中发布的功能的,但我假设它是有效的,因为我在以前的问题中使用过它。(最有可能的是,我刚刚对它进行了调整并从那时起将其破坏。)不管怎样,该函数的工作版本(对于所有小于2的整数,该函数都返回false)是这样的:

    这里提高速度的关键是只为b的值生成1到1000之间的一组素数(使用素数函数,我实现了Eratosthenes方法的筛选)。我还消除了不必要的Seq.map,从而使代码更加简洁


    因此,我对我现在的解决方案非常满意(只需要不到一秒钟),当然,任何进一步的建议都是欢迎的…

    对,在检查了所有帮助函数是否都在做它们应该做的事情之后,我终于找到了一个有效的解决方案

    /// Checks number for primality.
    let is_prime n = 
        [|1 .. 2 .. sqrt_int n|] |> Array.for_all (fun x -> n % x <> 0)
    
    /// Memoizes a function.
    let memoize f = 
        let cache = Dictionary<_, _>()
        fun x -> 
            let found, res = cache.TryGetValue(x)
            if found then
                res
            else
                let res = f x
                cache.[x] <- res
                res
    
    /// Problem 27
    /// Find a quadratic formula that produces the maximum number of primes for consecutive values of n.
    let problem27 n =
        let is_prime_mem = memoize is_prime
        let range = [|-(n - 1) .. n - 1|]
        let natural_nums = Seq.init_infinite (fun i -> i)
        range |> Array.map (fun a -> (range |> Array.map (fun b ->
            let formula n = n * n + a * n + b
            let num_conseq_primes = natural_nums |> Seq.map (fun n -> (n, formula n))
                                    |> Seq.find (fun (n, f) -> not (is_prime_mem f)) |> fst
            (a * b, num_conseq_primes)) |> Array.max_by snd)) |> Array.max_by snd |> fst
    
    printn_any (problem27 1000)
    
    首先,is_素数函数是完全错误的(感谢Dimitre Novatchev让我看到了这一点)。我不太清楚我是如何达到我在原始问题中发布的功能的,但我假设它是有效的,因为我在以前的问题中使用过它。(最有可能的是,我刚刚对它进行了调整并从那时起将其破坏。)不管怎样,该函数的工作版本(对于所有小于2的整数,该函数都返回false)是这样的:

    这里提高速度的关键是只为b的值生成1到1000之间的一组素数(使用素数函数,我实现了Eratosthenes方法的筛选)。我还消除了不必要的Seq.map,从而使代码更加简洁


    所以,我对我现在的解决方案非常满意(只需不到一秒钟),当然,任何进一步的建议都是受欢迎的…

    要去掉一半的计算,你还可以让可能的a的数组只包含奇数

    要去掉一半的计算,你还可以让可能的a的数组只包含奇数

    我的超快python解决方案:p

    flag = [0]*204
    primes = []
    
    def ifc(n): return flag[n>>6]&(1<<((n>>1)&31))
    
    def isc(n): flag[n>>6]|=(1<<((n>>1)&31))
    
    def sieve():
        for i in xrange(3, 114, 2):
            if ifc(i) == 0:
                for j in xrange(i*i, 12996, i<<1): isc(j)
    
    def store():
        primes.append(2)
        for i in xrange(3, 1000, 2):
            if ifc(i) == 0: primes.append(i)
    
    def isprime(n):
        if n < 2: return 0
        if n == 2: return 1
        if n & 1 == 0: return 0
        if ifc(n) == 0: return 1
        return 0    
    
    def main():
        sieve()
        store()
        mmax, ret = 0, 0
        for b in primes:
            for a in xrange(-999, 1000, 2):
                n = 1
                while isprime(n*n + a*n + b): n += 1
                if n > mmax: mmax, ret = n, a * b
        print ret
    
    main()
    
    flag=[0]*204
    素数=[]
    def ifc(n):返回标志[n>>6]&(11)和31))
    def isc(n):标志[n>>6]|=(11)和31))
    def sieve():
    对于x范围内的i(3114,2):
    如果ifc(i)==0:
    
    对于xrange中的j(i*i,12996,i我的超快python解决方案:p

    flag = [0]*204
    primes = []
    
    def ifc(n): return flag[n>>6]&(1<<((n>>1)&31))
    
    def isc(n): flag[n>>6]|=(1<<((n>>1)&31))
    
    def sieve():
        for i in xrange(3, 114, 2):
            if ifc(i) == 0:
                for j in xrange(i*i, 12996, i<<1): isc(j)
    
    def store():
        primes.append(2)
        for i in xrange(3, 1000, 2):
            if ifc(i) == 0: primes.append(i)
    
    def isprime(n):
        if n < 2: return 0
        if n == 2: return 1
        if n & 1 == 0: return 0
        if ifc(n) == 0: return 1
        return 0    
    
    def main():
        sieve()
        store()
        mmax, ret = 0, 0
        for b in primes:
            for a in xrange(-999, 1000, 2):
                n = 1
                while isprime(n*n + a*n + b): n += 1
                if n > mmax: mmax, ret = n, a * b
        print ret
    
    main()
    
    flag=[0]*204
    素数=[]
    def ifc(n):返回标志[n>>6]&(11)和31))
    def isc(n):标志[n>>6]|=(11)和31))
    def sieve():
    因为我