never executed always true always false
    1 {-|
    2 Module:      Y2015.D20
    3 Description: Advent of Code Day 20 Solutions.
    4 License:     MIT
    5 Maintainer:  @tylerjl
    6 
    7 Solutions to the day 20 set of problems for <adventofcode.com>.
    8 
    9 Original credit for most of this due to aepsilon:
   10 <https://www.reddit.com/r/adventofcode/comments/3xjpp2/day_20_solutions/cy5brqe>
   11 -}
   12 
   13 module Y2015.D20 (withMinPresents, withMinPresents2) where
   14 
   15 import           Data.List   (group)
   16 import           Data.Set    (Set)
   17 import qualified Data.Set as Set
   18 
   19 -- |Finds lowest house number that receives as many as the given presents
   20 withMinPresents :: Int -- ^ Minimum number of presents house should receive
   21                 -> Int -- ^ Position of house
   22 withMinPresents n = head $ filter ((>=n `divCeil` 10) . divisorSum) [1..]
   23 
   24 divCeil :: Int -> Int -> Int
   25 n `divCeil` d = (n-1) `div` d + 1
   26 
   27 divisorSum :: Int -> Int
   28 divisorSum = sum . divisorList
   29 
   30 divisorList :: Int -> [Int]
   31 divisorList = map product . mapM (scanl (*) 1) . group . factorize
   32 
   33 factorize :: Int -> [Int]
   34 factorize 1                = []
   35 factorize n | null factors = [n]
   36             | otherwise    = p : factorize q
   37   where factors = [ (p',q') | p' <- takeWhile (<= intsqrt n) primes
   38                           , let (q',r) = quotRem n p'
   39                           , r == 0 ]
   40         p = fst $ head factors
   41         q = snd $ head factors
   42 
   43 intsqrt :: Int -> Int
   44 intsqrt i = floor ((sqrt $ fromIntegral i) :: Double)
   45 
   46 primes :: [Int]
   47 primes = 2 : 3 : [ p | p <- [5,7..]
   48                      , and [p `rem` d /= 0 | d <- takeWhile (<= intsqrt p) primes]
   49                  ]
   50 
   51 -- |Finds lowest house number that receives as many as the given presents
   52 -- |given the special delivery case.
   53 withMinPresents2 :: Int -- ^ Minimum number of presents house should receive
   54                  -> Int -- ^ Position of house
   55 withMinPresents2 n = head $ filter ((>=n `divCeil` 11)
   56                           . divisorSumLimit 50) [1..]
   57 
   58 divisorSumLimit :: Int -> Int -> Int
   59 divisorSumLimit limit n = sum . snd . Set.split ((n-1)`div`limit) . divisors $ n
   60 
   61 divisors :: Int -> Set Int
   62 divisors = Set.fromList . divisorList