-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patheuler12.hs
More file actions
88 lines (65 loc) · 2.54 KB
/
euler12.hs
File metadata and controls
88 lines (65 loc) · 2.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import List
-- euler12.hs
primesToQ m = 2 : sieve [3,5..m] where
sieve [] = []
sieve (p:xs) = p : sieve (xs `minus` [p*p, p*p+2*p..m])
-- ordered lists, difference and union
minus (x:xs) (y:ys) = case (compare x y) of
LT -> x : minus xs (y:ys)
EQ -> minus xs ys
GT -> minus (x:xs) ys
minus xs _ = xs
primes = primesToQ 100000
testFactor x y = x `mod` y == 0
dropFactor x y [] = []
dropFactor x y xs
| testFactor x y = y:foo
| otherwise = xs
where foo = dropFactor (div x y) y xs
multipleDivideBy x y
| testFactor x y = recurseDivide
| otherwise = x
where recurseDivide = multipleDivideBy (div x y) y
-- lessThanPrimes :: (RealFrac a, Integral t) => a -> [t]
integerRoot n = ceiling(fromIntegral n**0.5)
lessThanPrimes n = [x | x <- primesToQ 6400000, x < n+1 ]
matchPrimes n = [x | x <- lessThanPrimes n, mod n x == 0]
factors = factors' primes
factors' _ 1 = []
factors' (x:xs) n | (n `mod` x) == 0 = (x, amount):factors' xs left
| otherwise = factors' xs n
where (amount, left) = amountLeft (0,n) x
amountLeft (amount, n) x | (n `mod` x) == 0 = amountLeft (amount + 1, n `div` x) x
| otherwise = (amount, n)
-- prime generator
-- primes = 2 : filter isPrime [3..]
isPrime a = isPrimeHelper a primes
isPrimeHelper a (p:ps)
| p*p > a = True
| a `mod` p == 0 = False
| otherwise = isPrimeHelper a ps
genTriangle n = n*(n+1) `div` 2
unfoldDrop x = unfoldr findFactor x
where
first (a,b,c) = a
findFactor 1 = Nothing
findFactor b = (\(_,d,p)-> Just (p, d))
$ head $ filter ((==0).first)
$ map (\p -> (b `mod` p, b `div` p, p)) $ primes
divisorCount = product . map ((1+) . length) . group . unfoldDrop
divisorCountTriangle = divisorCount . genTriangle
genTriangleList n = map genTriangle [1..n]
divisorCountList (xs) = map (\p -> (divisorCount p,p)) xs
divisorCountTriangleOptimized n
| n `mod` 2 == 0 = divisorCount (n `div` 2) * divisorCount (n +1)
| otherwise = divisorCount((n+1) `div` 2) * divisorCount n
testToLimit limit i
| x >= limit = (i, genTriangle i, x)
| otherwise = rTestToLimit
where rTestToLimit = testToLimit limit (i+1)
x = divisorCountTriangleOptimized i
testToLimit' limit i
| x >= limit = (i, genTriangle i, x)
| otherwise = rTestToLimit
where rTestToLimit = testToLimit limit (i+1)
x = divisorCountTriangle i