fork(1) download
  1. {-# OPTIONS_GHC -O2 #-}
  2. module Main where
  3. main = print $ primes !! 1000000 -- -fno-cse -fno-full-laziness
  4.  
  5. primes :: [Int]
  6. primes = [2,3,5,7] ++ _Y ((11:) . tail -- no leak on 7.8.3 either
  7. . gaps 11 wh11
  8. . _U . map (\(w,p)->scanl (\c x-> c+p*x) (p*p) w)
  9. . hits 11 wh11)
  10. where
  11. gaps k (d:w) s@(c:t) | k < c = k : gaps (k+d) w s
  12. | otherwise = gaps (k+d) w t -- k==c
  13. hits k (d:w) s@(p:t) | k < p = hits (k+d) w s
  14. | otherwise = (d:w,p) : hits (k+d) w t -- k==p
  15.  
  16. _Y g = g (_Y g) -- multistage with non-sharing fixpoint combinator
  17. -- = g (fix g) -- two stages with sharing fixpoint combinator
  18.  
  19. _U ((x:xs):t) = x : (union xs . _U . pairs) t
  20. where
  21. pairs (xs:ys:t) = union xs ys : pairs t
  22.  
  23. union a@(x:xs) b@(y:ys) = case compare x y of
  24. LT -> x : union xs b
  25. EQ -> x : union xs ys
  26. GT -> y : union a ys
  27.  
  28. wh3 = 2:wh3 -- n=1, d=2 [3, 5..] \\ ((3*) <$> _)
  29. wh5 = 2:4:wh5 -- n=2, d=6 [5,7,_, 11,..] \\ ((5*) <$> _)
  30. wh7 = 4:2:4:2:4:6:2:6:wh7 -- n=8, d=30 [7,11,13,17,19,23,_,29,31,_, 37..]
  31. wh11 = -- n=48, d=210 \\ ((7*) <$> _)
  32. 2:4:2:4:6:2:6:4:2:4:6:6:2:6:4:2:6:4:6:8:4:2:4:2:
  33. 4:8:6:4:6:2:4:6:2:6:6:4:2:4:6:2:6:4:2:4:2:10:2:10:wh11
  34.  
  35. primes2 = [2,3,5,7] ++ _Y ((11:) . tail . gaps (scanl (+) 11 wh11)
  36. . _U . hits (scanl (+) 11 wh11))
  37. where
  38. gaps (n:w) s@(c:t) | n < c = n : gaps w s
  39. | otherwise = gaps w t -- k==c
  40. hits (n:w) s@(p:t) | n < p = hits w s
  41. | otherwise = map (p*) (p:w) : hits w t -- n==p
  42. -- almost the same as Dave Bayer's code except here _^_ he has, in effect,
  43. -- ~~~~~~ (filter ((/=0).(`rem`p)) w)
  44. -- (and also, he doesn't sync on primes, since he uses the filter)
  45. -- see www.haskell.org/pipermail/haskell-cafe/2007-July/029077.html
  46. wo_hits_Bayer (n:w) (p:t) = map (p*) (p:w) :
  47. wo_hits_Bayer (filter ((/=0).(`rem`p)) w) t
  48. -- also, he uses diff, but
  49. -- gaps a b == diff a b when b ⊂ a is more efficient
  50.  
  51. -- but most importantly he names a lot of stuff, and thus creates
  52. -- and re-uses a lot of shared structure; in my code data separation
  53. -- is the goal, which enables definitions of gaps/hits be fused w/ scanl
  54.  
  55. {- gaps ~= minus
  56.   hits ~= equalsBy
  57.   see ideone.com/nuoLUE, rHJ9ub -}
Success #stdin #stdout 1.47s 7304KB
stdin
1 mln: 15485867  1.41s - 7.3 MB                             
2 mln: 32452867  3.32s - 7.3 MB   n^1.24                
3 mln: 49979693  5.54s - 7.3 MB   n^1.26 1.25        
4 mln: 67867979  7.91s - 7.3 MB   n^1.24 
6 mln: 104395303  13.0s- 7.3 MB   n^1.23

primes2:
1 mln: 15485867      2.54s - 9.3MB    1.8x         (2.99s w/Bayer's "filter")
2 mln: 32452867      5.97s - 9.4MB    1.8x     (5.68)       5.05s-9.4MB WRNG_ANSWR    
3 mln: 49979693      9.86s - 9.3MB    1.8x        or       5.09s-245(!)MB RT_ERROR
4 mln: 67867979                                                       11.31s-554(!)MB RT_ERROR
------ perhaps Ideone has TWO sets of servers with TWO different GHC versions or flags or something
stdout
15485867