{-# OPTIONS -O2 -XBangPatterns #-}
import Data.List
import Data.Function (on)
import Control.Arrow
main
= let (r
,t
) = nthHam
10000000000 in print t
-- >> print (trival t)
trival (i,j,k) = 2^i * 3^j * 5^k
estval n
= (6*lg3
*lg5
* fromIntegral n
)**(1/3) -- estimated logval, base 2rngval n
| n > 500000 = (ww - (3/estval n), 6/estval n) -- the space tweak! (thx, GBG!)
| n > 500000 = (2.4496 , 0.0076 ) -- empirical estimation
| n > 50000 = (2.4424 , 0.0146 ) -- correction, base 2
| n > 500 = (2.3948 , 0.0723 ) -- (dist,width)
| n > 1 = (2.2506 , 0.2887 ) -- around (log $ sqrt 30),
nthHam n -- n: 1-based: 1,2,3...
| w
>= 1 = error $ "Breach of contract: (w < 1): " ++ show w
| m
< 0 = error $ "Not enough triples generated: " ++ show (c
,n
) | m
>= nb
= error $ "Generated band is too narrow: " ++ show (m
,nb
) where
(d,w) = rngval n -- correction dist, width
hi = estval n - d -- hi > logval > hi-w
(s
,res
) = ( sortBy
(flip compare `on`
fst) b
, s
!!m
) -- sorted decreasing, result (c,b) = -- cb hi w
-- f (0 :: Integer) -- total triples count, band
[ (r,(i,j,k)) | frac < w ] ) -- store it, if inside band
let (i,frac) = pr (hi-q) ; r = hi-frac ] -- r = i + q
-- f 0 z == (sum $ map fst z, concat $ map snd z)
{- f !c [] = (c,[]) -- code as a loop
f !c ((c1,b1):r) = let (cr,br) = f (c+c1) r -- to prevent space leak
in case b1 of { [v] -> (cr,v:br)
; _ -> (cr, br) }
-}
cb hi w = gk 0 [] 0
where
gk c b k | k > kmax = (c,b)
where
jmax
= floor ((hi
-p
)/lg3
) gj c b j | j > jmax = gk c b (k+1)
where
r = hi-frac
b2 = if frac < w then (r,(i,j,k)):b else b
ey0jIE9QVElPTlMgLU8yIC1YQmFuZ1BhdHRlcm5zICMtfQppbXBvcnQgRGF0YS5MaXN0IAppbXBvcnQgRGF0YS5GdW5jdGlvbiAob24pCmltcG9ydCBDb250cm9sLkFycm93CgptYWluID0gbGV0IChyLHQpID0gbnRoSGFtIDEwMDAwMDAwMDAwIGluIHByaW50IHQgLS0gPj4gcHJpbnQgKHRyaXZhbCB0KQoKbGczID0gbG9nQmFzZSAyIDM7ICBsZzUgPSBsb2dCYXNlIDIgNTsgIHd3ID0gbG9nQmFzZSAyIDMwIC8gMgpsb2d2YWwgKGksaixrKSAgICA9IGZyb21JbnRlZ3JhbCBpICsgZnJvbUludGVncmFsIGoqbGczICsgZnJvbUludGVncmFsIGsqbGc1CnRyaXZhbCAoaSxqLGspICAgID0gMl5pICogM15qICogNV5rCmVzdHZhbCBuICAgICAgICAgID0gKDYqbGczKmxnNSogZnJvbUludGVncmFsIG4pKiooMS8zKSAgLS0gZXN0aW1hdGVkIGxvZ3ZhbCwgYmFzZSAyCnJuZ3ZhbCBuICAgICAgIAogICAgfCBuID4gNTAwMDAwICA9ICh3dyAtICgzL2VzdHZhbCBuKSwgNi9lc3R2YWwgbikgICAgIC0tIHRoZSBzcGFjZSB0d2VhayEgKHRoeCwgR0JHISkKICAgIHwgbiA+IDUwMDAwMCAgPSAoMi40NDk2ICwgMC4wMDc2ICkgICAgICAgICAgICAgICAgICAtLSBlbXBpcmljYWwgZXN0aW1hdGlvbiAKICAgIHwgbiA+IDUwMDAwICAgPSAoMi40NDI0ICwgMC4wMTQ2ICkgICAgICAgICAgICAgICAgICAtLSAgIGNvcnJlY3Rpb24sIGJhc2UgMgogICAgfCBuID4gNTAwICAgICA9ICgyLjM5NDggLCAwLjA3MjMgKSAgICAgICAgICAgICAgICAgIC0tICAgICAoZGlzdCx3aWR0aCkKICAgIHwgbiA+IDEgICAgICAgPSAoMi4yNTA2ICwgMC4yODg3ICkgICAgICAgICAgICAgICAgICAtLSBhcm91bmQgKGxvZyAkIHNxcnQgMzApLCAKICAgIHwgb3RoZXJ3aXNlICAgPSAoMi4yNTA2ICwgMC41NzcxICkgICAgICAgICAgICAgICAgICAtLSAgIHNheXMgV1AKCm50aEhhbSA6OiBJbnRlZ2VyIC0+IChEb3VibGUsIChJbnQsIEludCwgSW50KSkgICAgICAgICAgLS0gb24gNjQtYml0cywgdXNlIEludCEKbnRoSGFtIG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAtLSBuOiAxLWJhc2VkOiAxLDIsMy4uLgogIHwgdyA+PSAxICAgID0gZXJyb3IgJCAiQnJlYWNoIG9mIGNvbnRyYWN0OiAodyA8IDEpOiAgIiArKyBzaG93IHcKICB8IG0gPCAgMCAgICA9IGVycm9yICQgIk5vdCBlbm91Z2ggdHJpcGxlcyBnZW5lcmF0ZWQ6ICIgKysgc2hvdyAoYyxuKQogIHwgbSA+PSBuYiAgID0gZXJyb3IgJCAiR2VuZXJhdGVkIGJhbmQgaXMgdG9vIG5hcnJvdzogIiArKyBzaG93IChtLG5iKQogIHwgb3RoZXJ3aXNlID0gcmVzCiB3aGVyZQogIChkLHcpICAgPSBybmd2YWwgbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAtLSBjb3JyZWN0aW9uIGRpc3QsIHdpZHRoCiAgaGkgICAgICA9IGVzdHZhbCBuIC0gZCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0tICAgaGkgPiBsb2d2YWwgPiBoaS13CiAgKG0sbmIpICA9ICggZnJvbUludGVncmFsICQgYyAtIG4sIGxlbmd0aCBiICkgICAgICAgICAgIC0tIG0gMC1iYXNlZCBmcm9tIHRvcCwgfGJhbmR8CiAgKHMscmVzKSA9ICggc29ydEJ5IChmbGlwIGNvbXBhcmUgYG9uYCBmc3QpIGIsIHMhIW0gKSAgIC0tIHNvcnRlZCBkZWNyZWFzaW5nLCByZXN1bHQKICAoYyxiKSAgID0gLS0gY2IgaGkgdwogICAgICAgICAgICAoc3VtICoqKiBjb25jYXQpIC4gdW56aXAgJAogICAgICAgICAtLSBmICgwIDo6IEludGVnZXIpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAtLSB0b3RhbCB0cmlwbGVzIGNvdW50LCBiYW5kCiAgICAgICAgICAgICAgWyAoIGZyb21JbnRlZ3JhbCBpKzEsICAgICAgICAgICAgICAgICAgICAgIC0tIHRvdGFsIHRyaXBsZXMgdy8gdGhpcyAoaixrKQogICAgICAgICAgICAgICAgICBbIChyLChpLGosaykpIHwgZnJhYyA8IHcgXSApICAgICAgICAgICAtLSBzdG9yZSBpdCwgaWYgaW5zaWRlIGJhbmQKICAgICAgICAgICAgICAgIHwgayA8LSBbIDAgLi4gZmxvb3IgKCBoaSAgIC9sZzUpIF0sICBsZXQgcCA9IGZyb21JbnRlZ3JhbCBrKmxnNSwKICAgICAgICAgICAgICAgICAgaiA8LSBbIDAgLi4gZmxvb3IgKChoaS1wKS9sZzMpIF0sICBsZXQgcSA9IGZyb21JbnRlZ3JhbCBqKmxnMyArIHAsCiAgICAgICAgICAgICAgICAgIGxldCAoaSxmcmFjKSA9IHByICAoaGktcSkgOyAgICAgICAgICAgIHIgPSBoaS1mcmFjIF0gLS0gciA9IGkgKyBxCiAgICAgICAgIC0tIGYgMCB6ID09IChzdW0gJCBtYXAgZnN0IHosIGNvbmNhdCAkIG1hcCBzbmQgeikKICAgIHdoZXJlIHByID0gcHJvcGVyRnJhY3Rpb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgLS0gcHIgMTIuNSA9PSAoMTIsIDAuNSkKey0gICAgICAgIGYgIWMgW10gICAgICAgICAgPSAoYyxbXSkgICAgICAgICAgICAgICAgICAgICAgLS0gY29kZSBhcyBhIGxvb3AgCiAgICAgICAgICBmICFjICgoYzEsYjEpOnIpID0gbGV0IChjcixicikgPSBmIChjK2MxKSByICAgIC0tICAgdG8gcHJldmVudCBzcGFjZSBsZWFrCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW4gY2FzZSBiMSBvZiB7IFt2XSAtPiAoY3IsdjpicikgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7ICBfICAtPiAoY3IsIGJyKSB9Ci19CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKY2IgOjogRG91YmxlIC0+IERvdWJsZSAtPiAoSW50ZWdlciwgWyhEb3VibGUsKEludCxJbnQsSW50KSldKSAtLSB+IDIwJSBmYXN0ZXIKY2IgaGkgdyA9IGdrIDAgW10gMAogIHdoZXJlCiAga21heCA9IGZsb29yICggaGkgICAvbGc1KQogIGdrIGMgYiBrIHwgayA+IGttYXggID0gKGMsYikKICAgICAgICAgICB8IG90aGVyd2lzZSA9IGdqIGMgYiAwCiAgICAgICB3aGVyZQogICAgICAgcCAgICA9IGZyb21JbnRlZ3JhbCBrKmxnNSAKICAgICAgIGptYXggPSBmbG9vciAoKGhpLXApL2xnMykKICAgICAgIGdqIGMgYiBqIHwgaiA+IGptYXggID0gZ2sgYyBiIChrKzEpCiAgICAgICAgICAgICAgICB8IG90aGVyd2lzZSA9IHIgYHNlcWAgYzIgYHNlcWAgYjIgYHNlcWAgZ2ogYzIgYjIgKGorMSkKICAgICAgICAgICB3aGVyZQogICAgICAgICAgIHEgPSBmcm9tSW50ZWdyYWwgaipsZzMgKyBwCiAgICAgICAgICAgKGksZnJhYykgPSBwcm9wZXJGcmFjdGlvbiAoaGktcSkKICAgICAgICAgICByID0gaGktZnJhYyAKICAgICAgICAgICBjMiA9IGMgKyBmcm9tSW50ZWdyYWwgaSsxCiAgICAgICAgICAgYjIgPSBpZiBmcmFjIDwgdyB0aGVuICAociwoaSxqLGspKTpiIGVsc2UgYg==
d2l0aCBgY2JgIChsb29wcyk6CjFUOiAgMTAuOTdzLTcuOE1CICAoMTEyNiwxNjkzMCw0MCkgICAgICB0fm5eMC42NwoxMDBCOiAyLjM1cy01LjhNQiAgKDEwMTc4LDEzODQsMjc5KSAgICAgdH5uXjAuNzMKMjBCOiAgMC43NnMtNS44TUIgICg0MDc3LDkyNyw4OTApCjEwQjogIDAuNDRzLTUuOE1CICAoMjE3Nyw4LDE2NTkpCjFCOiAgIDAuMDJzLTQuOE1CICAoMTMzNCwzMzUsNDA0KQoKd2l0aCBgZmAgKGxlZnQgZm9sZCBvdmVyIGEgbGlzdCk6CjEwMEI6ICgxMDE3OCwxMzg0LDI3OSkgMy4zOXMtNi44TUIgdnMgMi43NHMtNi45TUIKMTBCOiAgKDIxNzcsOCwxNjU5KSAgICAwLjY0cy01LjhNQiB2cyAwLjQ5cy01LjlNQiAgIG9mIGZvbGRsJyB2ZXJzaW9uIGluIHEzZm1hCjFCOiAgICgxMzM0LDMzNSw0MDQpICAgMC4wOHMtNC44TUIgdnMgMC4wNXMtNC45TUIKCndpdGggSE9GIChgKHN1bSAqKiogY29uY2F0KSAuIHVuemlwICRgIGEgbGlzdCk6CjEwMEI6IHByb2c6IG91dCBvZiBtZW1vcnkgKHJlcXVlc3RlZCAxMDQ4NTc2IGJ5dGVzKSAgKDUwQiB0b28pCjIwQjogKDQwNzcsOTI3LDg5MCkgIDIuNDRzLTcuOE1CCjEwQjogKDIxNzcsOCwxNjU5KSAgIDEuOTFzLTcuOE1CCjFCOiAgKDEzMzQsMzM1LDQwNCkgIDAuMzRzLTcuOE1CCg==
with `cb` (loops):
1T: 10.97s-7.8MB (1126,16930,40) t~n^0.67
100B: 2.35s-5.8MB (10178,1384,279) t~n^0.73
20B: 0.76s-5.8MB (4077,927,890)
10B: 0.44s-5.8MB (2177,8,1659)
1B: 0.02s-4.8MB (1334,335,404)
with `f` (left fold over a list):
100B: (10178,1384,279) 3.39s-6.8MB vs 2.74s-6.9MB
10B: (2177,8,1659) 0.64s-5.8MB vs 0.49s-5.9MB of foldl' version in q3fma
1B: (1334,335,404) 0.08s-4.8MB vs 0.05s-4.9MB
with HOF (`(sum *** concat) . unzip $` a list):
100B: prog: out of memory (requested 1048576 bytes) (50B too)
20B: (4077,927,890) 2.44s-7.8MB
10B: (2177,8,1659) 1.91s-7.8MB
1B: (1334,335,404) 0.34s-7.8MB