{-# OPTIONS_GHC -O2 #-}
-- http://stackoverflow.com/questions/26075806/haskell-garbage-collector/
import Data
.List
(foldl') -- '
erat_ (c,b) ((x,y):xs)
| c < x = (x,y) : erat_ (c,b) xs
| c == x = (x+y,y) : erat_ (c,True) xs
| c > x = (x+y,y) : erat_ (c,b) xs
erat_ (c,b) []
| b = []
{-
erat :: [Integer] -> [(Integer,Integer)]
erat = foldl_ (\a c -> erat' (c,False) a) []
primes :: Integer -> [Integer]
primes n = map snd $ erat [2..n]
-}
-- main = print . last . primes . read =<< getLine
-- NO FORCING
foldl_ (\a c -> erat_ (c,False) a)
[] [2..n])
-- 10k: 0.46s-8.4MB 20k: 2.34s-8.4MB 30k: 7.13s-9.4MB
-- N^2.35 N^2.75
{- WITH FORCING
main = print . length . (\n->
foldl_ (\a c -> (if null a then 0 else
case last a of (x,y) -> y) `seq` erat_ (c,False) a)
[] [2..n])
. read =<< getLine
-}
-- 10k: 0.27s-6.3MB 20k: 1.07s-7.4MB 40k: 3.99s-7.4MB 70k: 13.63-7.3MB
-- N^1.99 N^1.90 N^2.20
----- STOPPING EARLY -----
g (c,b) ((x,y):xs)
| c < x = (x, y) : if x==y*y then (if b then xs
else xs++[(c*c,c)])
else g (c,b) xs
| c == x = (x+y,y) : if x==y*y then xs
else g (c,True) xs
| c > x = (x+y,y) : g (c,b) xs
g (c,True) [] = []
g (c,False) [] = [(c*c,c)]
{- WITH FORCING
main = print . length . (\n->
foldl_ (\a c -> (if null a then 0 else
case last a of (x,y) -> y) `seq` g (c,False) a)
[] [2..n])
. read =<< getLine
-}
-- 20k: 0.30s-6.3MB 40k: 1.05s-6.3MB 80k: 3.99s-7.4MB 100k: 5.70s-7.4MB
-- N^1.80 N^1.93 N^1.60(1.85)
{- NO FORCING
main = print . length . (\n->
foldl_ (\a c -> g (c,False) a)
[] [2..n])
. read =<< getLine
-}
-- 20k: 0.20s-8.4MB 40k: 0.75s-9.4MB 80k: 2.55s-9.4MB 100k: 3.87s-9.4MB
-- N^1.90 N^1.77 N^1.87(1.79)
foldl
_ f z xs
= foldl' f z xs -- '
ey0jIE9QVElPTlNfR0hDIC1PMiAjLX0KCi0tIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjYwNzU4MDYvaGFza2VsbC1nYXJiYWdlLWNvbGxlY3Rvci8KCmltcG9ydCBEYXRhLkxpc3QgKGZvbGRsJykgIC0tICcKCmVyYXRfIDo6IChJbnRlZ2VyLCBCb29sKSAtPiBbKEludGVnZXIsSW50ZWdlcildIC0+IFsoSW50ZWdlcixJbnRlZ2VyKV0KZXJhdF8gKGMsYikgKCh4LHkpOnhzKQogICAgfCBjIDwgeCA9ICh4LHkpIDogZXJhdF8gKGMsYikgeHMKICAgIHwgYyA9PSB4ID0gKHgreSx5KSA6IGVyYXRfIChjLFRydWUpIHhzCiAgICB8IGMgPiB4ID0gKHgreSx5KSA6IGVyYXRfIChjLGIpIHhzCmVyYXRfIChjLGIpIFtdCiAgICB8IGIgPSBbXQogICAgfCBvdGhlcndpc2UgPSBbKGMsYyldCnstCmVyYXQgOjogW0ludGVnZXJdIC0+IFsoSW50ZWdlcixJbnRlZ2VyKV0KZXJhdCA9IGZvbGRsXyAoXGEgYyAtPiBlcmF0JyAoYyxGYWxzZSkgYSkgW10KCnByaW1lcyA6OiBJbnRlZ2VyIC0+IFtJbnRlZ2VyXQpwcmltZXMgbiA9IG1hcCBzbmQgJCBlcmF0IFsyLi5uXQotfQotLSBtYWluID0gcHJpbnQgLiBsYXN0IC4gcHJpbWVzIC4gcmVhZCA9PDwgZ2V0TGluZQoKLS0gICBOTyAgRk9SQ0lORwptYWluID0gcHJpbnQgLiBsZW5ndGggLiAoXG4tPiAgCiAgICAgICAgICAgICAgICAgICBmb2xkbF8gKFxhIGMgLT4gZXJhdF8gKGMsRmFsc2UpIGEpIAogICAgICAgICAgICAgICAgICAgICBbXSBbMi4ubl0pCiAgICAgICAgICAgICAuIHJlYWQgPTw8IGdldExpbmUKCi0tIDEwazogMC40NnMtOC40TUIgICAyMGs6IDIuMzRzLTguNE1CICAgMzBrOiA3LjEzcy05LjRNQgotLSAgICAgICAgICAgICAgIE5eMi4zNSAgICAgICAgICAgICBOXjIuNzUKCnstICAgV0lUSCAgRk9SQ0lORwptYWluID0gcHJpbnQgLiBsZW5ndGggLiAoXG4tPiAgCiAgICAgICAgICAgICAgICAgICBmb2xkbF8gKFxhIGMgLT4gKGlmIG51bGwgYSB0aGVuIDAgZWxzZSAKICAgICAgICBjYXNlIGxhc3QgYSBvZiAoeCx5KSAtPiB5KSBgc2VxYCBlcmF0XyAoYyxGYWxzZSkgYSkgCiAgICAgICAgICAgICAgICAgICAgIFtdIFsyLi5uXSkKICAgICAgICAgICAgIC4gcmVhZCA9PDwgZ2V0TGluZQotfQotLSAxMGs6IDAuMjdzLTYuM01CICAyMGs6IDEuMDdzLTcuNE1CICA0MGs6IDMuOTlzLTcuNE1CICA3MGs6IDEzLjYzLTcuM01CCi0tICAgICAgICAgICAgICAgTl4xLjk5ICAgICAgICAgICAgTl4xLjkwICAgICAgICAgICAgTl4yLjIwCgotLS0tLSBTVE9QUElORyBFQVJMWSAtLS0tLQoKZyA6OiAoSW50ZWdlciwgQm9vbCkgLT4gWyhJbnRlZ2VyLEludGVnZXIpXSAtPiBbKEludGVnZXIsSW50ZWdlcildCmcgKGMsYikgKCh4LHkpOnhzKQogICAgfCBjIDwgeCAgPSAoeCwgIHkpIDogaWYgeD09eSp5IHRoZW4gKGlmIGIgdGhlbiB4cyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgeHMrK1soYypjLGMpXSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGcgKGMsYikgICAgeHMgCiAgICB8IGMgPT0geCA9ICh4K3kseSkgOiBpZiB4PT15KnkgdGhlbiAgICAgICAgICAgIHhzIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgZyAoYyxUcnVlKSB4cyAKICAgIHwgYyA+IHggID0gKHgreSx5KSA6ICAgICAgICAgICAgICAgIGcgKGMsYikgICAgeHMgCmcgKGMsVHJ1ZSkgIFtdID0gW10KZyAoYyxGYWxzZSkgW10gPSBbKGMqYyxjKV0KCnstICAgICBXSVRIIEZPUkNJTkcKCm1haW4gPSBwcmludCAuIGxlbmd0aCAuIChcbi0+ICAKICAgICAgICAgICAgICAgICAgIGZvbGRsXyAoXGEgYyAtPiAoaWYgbnVsbCBhIHRoZW4gMCBlbHNlIAogICAgICAgIGNhc2UgbGFzdCBhIG9mICh4LHkpIC0+IHkpIGBzZXFgIGcgKGMsRmFsc2UpIGEpIAogICAgICAgICAgICAgICAgICAgICBbXSBbMi4ubl0pCiAgICAgICAgICAgICAuIHJlYWQgPTw8IGdldExpbmUKLX0KLS0gMjBrOiAwLjMwcy02LjNNQiAgNDBrOiAxLjA1cy02LjNNQiAgODBrOiAzLjk5cy03LjRNQiAgMTAwazogNS43MHMtNy40TUIKLS0gICAgICAgICAgICAgICBOXjEuODAgICAgICAgICAgICBOXjEuOTMgICAgICAgICAgICBOXjEuNjAoMS44NSkKCnstICAgIE5PIEZPUkNJTkcKCm1haW4gPSBwcmludCAuIGxlbmd0aCAuIChcbi0+ICAKICAgICAgICAgICAgICAgICAgIGZvbGRsXyAoXGEgYyAtPiBnIChjLEZhbHNlKSBhKSAKICAgICAgICAgICAgICAgICAgICAgW10gWzIuLm5dKQogICAgICAgICAgICAgLiByZWFkID08PCBnZXRMaW5lCi19Ci0tIDIwazogMC4yMHMtOC40TUIgIDQwazogMC43NXMtOS40TUIgIDgwazogMi41NXMtOS40TUIgIDEwMGs6IDMuODdzLTkuNE1CIAotLSAgICAgICAgICAgICAgIE5eMS45MCAgICAgICAgICAgIE5eMS43NyAgICAgICAgICAgIE5eMS44NygxLjc5KQoKZm9sZGxfIGYgeiB4cyA9IGZvbGRsJyBmIHogeHMgIC0tICc=