Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add several projecteuler codes #50

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Created by https://www.gitignore.io/api/haskell,visualstudiocode
# Edit at https://www.gitignore.io/?templates=haskell,visualstudiocode

.DS_Store
*/.DS_Store

### Haskell ###
dist
dist-*
Expand Down Expand Up @@ -40,4 +43,4 @@ cabal.project.local~
### IntelliJ
.idea/

# End of https://www.gitignore.io/api/haskell,visualstudiocode
# End of https://www.gitignore.io/api/haskell,visualstudiocode
19 changes: 19 additions & 0 deletions src/ProjectEuler/Problem12/Problem12.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
main = do
print $ solve 1

-- expected answer around 600ish, actually 8000ish
solve :: Integer -> Integer
solve a
| (length $ divisors $ triangular a) >= 500 = triangular a
| otherwise = solve (a+1)

triangular :: Integer -> Integer
triangular a = quot (a*(a+1)) 2

divisors :: Integer -> [Integer]
divisors num = divisors' 2 num
where
divisors' n k | n*n == k = [n, k]
| n*n > k = [k]
| k `mod` n == 0 = (n:(div k n): (divisors' (n+1) k))
| otherwise = divisors' (n+1) k
16 changes: 16 additions & 0 deletions src/ProjectEuler/Problem14/Problem14.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
main = do
print $ solve [1..1000000]

solve :: [Int] -> [Int]
solve [a] = path a
solve (x:xs) | (head now) > (head after) = now
| otherwise = after
where after = solve xs
now = path x


path :: Int -> [Int]
path a = p a 1 a
where p a n s | a == 1 = [n, s]
| a `mod` 2 == 0 = p (quot a 2) (n+1) s
| otherwise = p (3*a+1) (n+1) s
13 changes: 13 additions & 0 deletions src/ProjectEuler/Problem15/Problem15.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
main = do
print $ choose 40 20

choose :: Int -> Int -> Integer
choose a b = pascal (a+1) (b+1)

pascal :: Int -> Int -> Integer
pascal a b = triangle !! a !! b
where
triangle = [[pascal' a b | b <- [0..]] | a <- [0..]]
pascal' a b | a == 1 && b == 1 = 1
| a <= 0 || b <= 0 = 0
| otherwise = triangle !! (a-1) !! (b-1) + triangle !! (a-1) !! b
14 changes: 14 additions & 0 deletions src/ProjectEuler/Problem16/Problem16.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
main = do
print $ sumDigit $ pow 2 1000

sumDigit :: Integer -> Integer
sumDigit a | a >= 10 = (+) (a `mod` 10) $ sumDigit (quot a 10)
| otherwise = a


pow :: Integer -> Int -> Integer
pow _ 0 = 1
pow a 1 = a
pow a 2 = a * a
pow a b | b `mod` 2 == 0 = pow (pow a (quot b 2)) 2
| otherwise = (pow a (b-1)) * a
39 changes: 39 additions & 0 deletions src/ProjectEuler/Problem17/Problem17.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
main = do
print $ countLetter 342
print $ countLetter 115
print $ sumList $ map countLetter [1..1000]

sumList :: [Int] -> Int
sumList [a] = a
sumList (a:as) = a + sumList as

prefix :: Int -> Int
prefix 3 = 4
prefix 5 = 3
prefix 4 = 3
prefix 8 = 4
prefix a = countLetter a

countLetter :: Int -> Int
countLetter 0 = 0
countLetter 1 = 3
countLetter 2 = 3
countLetter 3 = 5
countLetter 4 = 4
countLetter 5 = 4
countLetter 6 = 3
countLetter 7 = 5
countLetter 8 = 5
countLetter 9 = 4
countLetter 10 = 3
countLetter 11 = 6
countLetter 12 = 6
countLetter 14 = 8
countLetter 20 = 6
countLetter 100 = 10
countLetter 1000 = 11
countLetter a | a < 20 = 4 + prefix (a-10)
| a < 30 = 6 + countLetter (a `mod` 10)
| a < 100 = prefix (quot a 10) + 2 + countLetter (a `mod` 10)
| a `mod` 100 == 0 = countLetter (quot a 100) + 7
| otherwise = countLetter (quot a 100) + 10 + countLetter (a `mod` 100)
11 changes: 11 additions & 0 deletions src/ProjectEuler/Problem20/Problem20.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
main = do
print $ sumDigit $ fact 100

sumDigit :: Integer -> Integer
sumDigit a | a >= 10 = (+) (a `mod` 10) $ sumDigit (quot a 10)
| otherwise = a


fact :: Integer -> Integer
fact 1 = 1
fact x = x * fact (x-1)
15 changes: 15 additions & 0 deletions src/ProjectEuler/Problem21/Problem21.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
main = do
print $ sumDivisors 220
print $ sumDivisors 284
print $ sumList $ filter amicable [1..10000]

amicable :: Int -> Bool
amicable a = ((sumDivisors $ sumDivisors a) == a) && (sumDivisors a /= a)

sumList :: [Int] -> Int
sumList [] = 0
sumList (a:as) = a + sumList as

sumDivisors :: Int -> Int
sumDivisors a = sumList $ filter modB [1..(a-1)]
where modB b = (a `mod` b == 0)
26 changes: 26 additions & 0 deletions src/ProjectEuler/Problem23/Problem23.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Data.Set (Set)
import qualified Data.Set as Set

main = do
print $ length abundants
print $ sum $ filter notSumOfTwoAbun [1..30000]

notSumOfTwoAbun :: Int -> Bool
notSumOfTwoAbun a = notSum' a abundants

notSum' :: Int -> [Int] -> Bool
notSum' a [] = True
notSum' a (x:xs) | Set.member (a-x) abundantSet = False
| otherwise = notSum' a xs

abundantSet :: Set Int
abundantSet = Set.fromList abundants

abundants :: [Int]
abundants = filter isAbundant [1..30000]

isAbundant :: Int -> Bool
isAbundant a = sumDivisors a > a

sumDivisors :: Int -> Int
sumDivisors a = sum $ filter (\b -> (a `mod` b) == 0) [1..(a-1)]
14 changes: 14 additions & 0 deletions src/ProjectEuler/Problem25/Problem25.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
main = do
print $ (findLongFib !! 0) + 1

fibs :: [Integer]
fibs = scanl (+) 1 (0:fibs)

isLarge :: Integer -> Bool
isLarge a = a >= 10^999

findLongFib :: [Int]
findLongFib = do
a <- [1..]
b <- [fibs !! a]
if isLarge b then [a] else []
15 changes: 15 additions & 0 deletions src/ProjectEuler/Problem29/Problem29.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
main = do
print $ length $ unique numbers

numbers :: [Integer]
numbers = [a^b | a <- [2..100], b <- [2..100]]

contain :: [Integer] -> Integer -> Bool
contain [] x = False
contain (a:as) b | a == b = True
| otherwise = contain as b

unique :: [Integer] -> [Integer]
unique [] = []
unique (a:as) | contain as a = unique as
| otherwise = a:(unique as)
11 changes: 11 additions & 0 deletions src/ProjectEuler/Problem30/Problem30.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
main = do
print $ sum $ search [10..1000000]

powOfDig :: Integer -> Integer
powOfDig x | x < 10 = x^5
| otherwise = (+) (powOfDig $ mod x 10) (powOfDig $ quot x 10)

search :: [Integer] -> [Integer]
search [] = []
search (x:xs) | x == powOfDig x = x:(search xs)
| otherwise = search xs
13 changes: 13 additions & 0 deletions src/ProjectEuler/Problem34/Problem34.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
main = do
print $ sum $ search [10..10000000]

factOfDig :: Integer -> Integer
factOfDig x | x < 10 = fact x
| otherwise = (+) (factOfDig $ mod x 10) (factOfDig $ quot x 10)
where fact 0 = 1
fact x = x * fact (x-1)

search :: [Integer] -> [Integer]
search [] = []
search (x:xs) | x == factOfDig x = x:(search xs)
| otherwise = search xs
19 changes: 19 additions & 0 deletions src/ProjectEuler/Problem35/Problem35.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
main = do
print . length $ filter circular [1..1000000]

isPrime :: Int -> Bool
isPrime k = if k > 1 then null [ x | x <- [2..(isqrt k)], k `mod` x == 0] else False
where isqrt = round.sqrt.fromIntegral

nOfDg :: Int -> Int
nOfDg n = 1 + floor ( logBase (fromIntegral 10) (fromIntegral (n)))

rotate :: Int -> Int
rotate x = (mod x 10) * 10^(digit-1) + (quot x 10)
where digit = nOfDg x

circular :: Int -> Bool
circular x = check x (nOfDg x)
where check x 0 = True
check x a | isPrime x = check (rotate x) (a-1)
| otherwise = False
15 changes: 15 additions & 0 deletions src/ProjectEuler/Problem36/Problem36.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
main = do
print $filter (isPalin.toBinary) (filter isPalin [1..1000000])
print.sum $filter (isPalin.toBinary) (filter isPalin [1..1000000])

mirror :: Integer -> Integer
mirror = read.reverse.show

isPalin :: Integer -> Bool
isPalin a = (==) a $mirror a

toBinary :: Integer -> Integer
toBinary a = read.reverse.concat.(map show).toBin $a
where toBin 0 = [0]
toBin 1 = [1]
toBin a = (mod a 2) : (toBin(quot a 2))
26 changes: 26 additions & 0 deletions src/ProjectEuler/Problem37/Problem37.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
main = do
print $ filter truncatable [10..1000000]
print.sum $ filter truncatable [10..1000000]

isPrime :: Int -> Bool
isPrime k = if k > 1 then null [ x | x <- [2..(isqrt k)], k `mod` x == 0] else False
where isqrt = round.sqrt.fromIntegral

nOfDg :: Int -> Int
nOfDg n = 1 + floor ( logBase (fromIntegral 10) (fromIntegral (n)))

truncateL :: Int -> Int
truncateL x = (mod x (10^(digit-1)))
where digit = nOfDg x

truncateR :: Int -> Int
truncateR x = (quot x 10)

truncatable :: Int -> Bool
truncatable x = (tableL x) && (tableR x)
where tableL 0 = True
tableL x | isPrime x = tableL $ truncateL x
| otherwise = False
tableR 0 = True
tableR x | isPrime x = tableR $ truncateR x
| otherwise = False