fork download
  1. open System
  2.  
  3. type SeqDesc<'a> = SeqDesc of 'a * (unit -> SeqDesc<'a>) //' a self referring tuple type
  4.  
  5. let primesMPWSE () = // original code by GordonBGood, http://stackoverflow.com/a/17401770/849891
  6. let wh = [| 2;4;2;4;6;2;6;4;2;4;6;6;2;6;4;2;6;4;6;8;4;2;4;2;
  7. 4;8;6;4;6;2;4;6;2;6;6;4;2;4;6;2;6;4;2;4;2;10;2;10 |]
  8. let inline adv i = if i < 47 then i + 1 else 0
  9. let reinsert c m (p,pi) =
  10. let c2 = c + wh.[pi] * p
  11. match Map.tryFind c2 m with
  12. | None -> m |> Map.add c2 [(p,adv pi)]
  13. | Some(facts) -> m |> Map.add c2 ((p,adv pi)::facts)
  14. let rec mkprimes (n,i) m (SeqDesc((p,pi),f) as psd) q =
  15. let n2,i2 = n + wh.[i],adv i
  16.  
  17. match Map.tryFind n m with
  18. | None -> if n < q then SeqDesc((n,i),fun() -> mkprimes (n2,i2) m psd q)
  19. else let (SeqDesc((p2,_),_) as nsd),c2 = f(),n + wh.[pi] * p
  20. mkprimes (n2,i2) (Map.add c2 [(p,adv pi)] m) nsd (p2 * p2)
  21. | Some(skips) -> let m2 = skips |> List.fold (reinsert n) (m |> Map.remove n)
  22. mkprimes (n2,i2) m2 psd q
  23. let rec prs = SeqDesc((11,0),fun() -> mkprimes (13,1) Map.empty prs 121 )
  24. let genseq sd = Seq.unfold (fun (SeqDesc((p,_), g)) -> Some(p, g())) sd
  25. seq { yield 2; yield 3; yield 5; yield 7; yield! mkprimes (11,0) Map.empty prs 121 |> genseq }
  26.  
  27. primesMPWSE() |> Seq.nth 100000 |> printfn "%A"
Success #stdin #stdout 1.05s 12656KB
stdin
-- with wh etc internal to mkprimes:     -- external to mkprimes:        --  ()
100k: 1299721: 1.26s 12.7MB                    1.06s                    1.06s    12.6MB
200k: 2750161: 2.53s 12.9MB    n^1.01          2.33s                    2.21s    12.6MB
400k: 5800139: 5.61s 12.7MB    n^1.15
800k: 12195263 12.3s 12.9MB    n^1.13         11.11s   n^1.13          10.84s    12.6MB (11.06-12.8)??
1mln:         -15.7s-                         14.33s   n^1.13          14.15s    12.9MB (limit exceeded)??
stdout
1299721