Day 15 - refactored strict version with some fancy ~~custom operators~~

This commit is contained in:
Jonathan Chan 2017-12-15 09:28:02 -08:00
parent 906eb9106b
commit b12aa2915a
1 changed files with 15 additions and 10 deletions

View File

@ -2,17 +2,22 @@
import Data.Function (on) import Data.Function (on)
import Data.Bits ((.&.)) import Data.Bits ((.&.))
count :: Int -> (Int, Int) -> (Int, Int) -> (Int, Int) -> Int -> Int -> Int divisor = 2147483647
count divisor (factorA, factorB) (seedA, seedB) (divA, divB) acc times = factors = (16807, 48271)
seed = (634, 301)
count :: (Int, Int) -> (Int, Int) -> Int -> Int -> Int
count pair masks acc times =
if times == 0 then acc else if times == 0 then acc else
let !nextA = nextMaskBy factorA divA seedA let !next = nextMaskBy <$$> factors <**> masks <**> pair
!nextB = nextMaskBy factorB divB seedB !eq = fromEnum . uncurry ((==) `on` (.&. 0xffff)) $ next
!eq = fromEnum $ ((==) `on` (.&. 0xffff)) nextA nextB in count next masks (acc + eq) (times - 1)
in count divisor (factorA, factorB) (nextA, nextB) (divA, divB) (acc + eq) (times - 1)
where where
h <$$> (x, y) = (h x, h y)
(f, g) <**> (x, y) = (f x, g y)
nextMaskBy f d s = let t = (f * s) `mod` divisor in if (t .&. d) == 0 then t else nextMaskBy f d t nextMaskBy f d s = let t = (f * s) `mod` divisor in if (t .&. d) == 0 then t else nextMaskBy f d t
main :: IO () main :: IO ()
main = do main = do
print $ count 2147483647 (16807, 48271) (634, 301) (0, 0) 0 40000000 print $ count seed (0, 0) 0 40000000
print $ count 2147483647 (16807, 48271) (634, 301) (3, 7) 0 5000000 print $ count seed (3, 7) 0 5000000