球拍编程。 我要去哪里错了?(Racket Programming. Where am I go

2019-08-18 05:00发布

这个问题我试图回答:
的13195的首要因素是5,7,13和29是什么号码600851475143的最大质因数?

我要去哪里错了? 我的黄金? 测试似乎是问题,但它适用于相对较少的罚款。 然而黄金? 测试给出了错误的答案用更大的数字。 是否有更简单的方法来进行此事?

    (define b 3)

    (define z 0)

    (define divides?
      (lambda (a b)
        (= (remainder a b) 0)))

    (define (prime? n)
        (cond
          ((or (= n 1) (= n 0)) false)
          ((even? n) false)
          ((= n 2) true)
          ((= n b) true)
          ((divides? n b) false)
          (else (and (set! b (+ b 1)) (prime? n)))))

    ;Largest Prime Factor Test
    (define (LPF x)
      (cond
        ((divides? 600851475143 x)
         (cond
           ((prime? x)
            (cond
              ((> x z) (set! z x)))))))
      (if (< x 775146) (LPF (+ x 1)) (display z)))

Answer 1:

写在一定的伪代码,你的意图似乎是

 pe3 = last [x | x <- [2 .. 775146], isPrime x, rem 600851475143 x == 0]

读取它: 对于x从范围2吸引到775146,如果isPrime x成立,如果600851475143 % x 0,收集这样x ; 返回最大 。 我们还编写应用程序(gx)这里没有括号,如刚才gx

计算的余数比测试素性便宜,所以我们会交换两个操作:

pe3 n = last [x | x <- [2 .. isqrt n], rem n x == 0, isPrime x] 

这种算法可能参与具体的数字工作,但不幸的是,一般不正确-说为9000009,其整数平方根是3000,它会返回101,但9901是正确的答案(即9901是9000009的最大素因子不是101)。

我们首先关注于寻找最小的首要因素,而不是:

pe3a n = head ([x | x <- [2 .. isqrt n], rem n x == 0, isPrime x] ++ [n])

为什么( ... ++ [n])++意列出的串联)? 因为如果n本身是素数,没有除数将全部找到,第一个列表会回来空, [] 在这种情况下,答案一定是n本身。 但如果不是,那么答案是第一个(即head除数列表)。 当然,当我们发现,我们并不需要继续寻找更多。 只要一个就够了,如果最小的是我们所需要的。

OK,所以想它(在一个假想的懒惰伪翻译),我们得到3作为它的第一个因素:

> pe3a 9000009
3

现在,我们可以除以3我们的一些:

> div 9000009 3 
3000003

并继续与3000003,而不是9000009.这意味着我们可以在它的平方根,1732停止,而不是在3000 -效率相当大的收获! 此外,我们不需要从2重新开始 - 它已经被测试了 - 我们可以从过去发现的因素入手:

pe3b (start, n) = (d, div n d)
  where
     d = head ([x | x <- [start .. isqrt n], rem n x == 0, isPrime x] ++ [n])

> pe3b (3, 3000003)
(3,1000001)

这样我们就得到第二三回头,及数由发现除数再次分开。

> pe3b (3, 1000001)
(101,9901)

发现下一个素因子是101,而现在因式分解的数量101分之1000001= 9901我们再一次从最后发现除数,101开始,因为所有的小的都已经尝试过:

> pe3b (101, 9901)
(9901,1)

有趣。 isqrt(9901) == 99 ,列表[101 .. 99]是空的,所以结果是立即产生的。 9901是本身高于100的第一因素,在上述1的事实,因为以前所有的号码都已经尝试过,在继承和分割出来。 这意味着9901是素数,没有必要对其进行测试素性。

事实上,该算法发现所有的因素都保证用同样的理由是施工黄金 ,和所有的通话isPrime是多余的。

难道还需要注意,这是在这里进行的最大数师(求余运算),为101 - 3000 不仅是我们新的算法是正确的,也更有效!

现在,您可以在方案代号这种算法重复pe3b由最后发现因子的应用和划分。 达到1时停止。


所以,在相同的伪代码 ,

divStep (start, n) = (d, div n d) 
  where d = head ([x | x <- [start .. isqrt n], rem n x == 0] ++ [n])

pe3 n = fst . until ((== 1) . snd) divStep $ (2,n)  -- (1st,2nd) in a tuple

factorizing n = takeWhile ((> 1) . fst) . drop 1 . iterate divStep $ (2,n)

factors n = map fst . factorizing $ n

isPrime n = factors n == [n]      

阅读.$为“”。 until 预解码步骤开始是一个函数的重复应用的高次模式,直到谓词被满足( ((== 1) . snd)表示结果的第二分量等于1)。 它通常是编码方案名为let

要查看计算的整个历史, iterate 步开始是收集所有的中期业绩另一种模式(与初始值,这是我们不需要的,所以我们drop吧)。 看到刚才的因素本身,我们把每个结果的第一个组件map fst 。 一个数字是素数,如果它是唯一的除数,大于1,本身。 测试:

> pe3 9000009
9901
> factorizing 9000009
[(3,3000003),(3,1000001),(101,9901),(9901,1)]
> factors 9000009
[3,3,101,9901]

> pe3 600851475143
6857
> factorizing 600851475143
[(71,8462696833),(839,10086647),(1471,6857),(6857,1)]   -- 1471 is the largest
> factors 600851475143                                  --   factor tried, 
[71,839,1471,6857]                                      --   *not* 775146 !!

> factors 600851475143999917      -- isqrt 600851475143999917 == 775146099
[41,37309,392798360393]           -- isqrt 392798360393       ==    626736


Answer 2:

简单的答案:

$ factor 600851475143
600851475143: 71 839 1471 6857

更严重的答案:你的prime? 功能确实破裂; 我甚至不能肯定什么它试图做。 (另外,你(= n 2)测试是来不及有用:在(even? n)测试已经胜过它。)

我的建议是:实现埃拉托色尼的筛 。 下面是我的实现 。



文章来源: Racket Programming. Where am I going wrong?