-- Helpers/Numbers.hs
module Helpers.Numbers (
    divisors,
    divisorCount,
    intToDigits,
    lcm',
    gcd',
    collatz,
    fact,
    digitSum ) where

import Data.IntSet (toList, fromList)
import Data.List
import Data.Maybe

divisorCount :: Int -> Int
divisorCount num = length $ divisors num

divisors :: Int -> [Int]
divisors 0 = []
divisors num = nub' $ 1:firstHalf ++ reverse (map (\x -> num `div` x) firstHalf) where
    nub' = toList . fromList
    firstHalf = filter (\x -> num `mod` x == 0) [2..(round . sqrt $ fromIntegral num)]

intToDigits :: Integral a => a -> [a]
intToDigits 0 = []
intToDigits num = intToDigits (num `div` 10) ++ [num `mod` 10]

lcm' :: Int -> Int -> Int
lcm' a b = abs a `div` gcd a b * abs b

gcd' :: Int -> Int -> Int
gcd' a b = fromJust $ find (\x -> a `mod` x == 0 && b `mod` x == 0) $ reverse [1..(max a b)]

collatz :: Int -> [Int]
collatz 1 = [1]
collatz num 
    | even num = num : (collatz $ num `div` 2)
    | otherwise = num : (collatz $ 3 * num + 1)

fact :: Integer -> Integer
fact 0 = 1
fact num = foldr1 (*) [1..num]

digitSum :: Integer -> Integer
digitSum = sum . map (read . return) . show
