From aa14346c6a214a28e30dd8e32f090aedc1b00f9c Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Fri, 15 Dec 2017 13:34:00 +0000 Subject: [PATCH] About to try optimising my version --- src/advent15/advent15.hs | 8 ++-- src/advent15/advent15other.hs | 76 ++++++++++++++++++++++------------- 2 files changed, 51 insertions(+), 33 deletions(-) diff --git a/src/advent15/advent15.hs b/src/advent15/advent15.hs index 6ee03c0..84e2412 100644 --- a/src/advent15/advent15.hs +++ b/src/advent15/advent15.hs @@ -23,14 +23,14 @@ generatorB = generator 2147483647 48271 streamA = stream generatorA generatorAStart streamB = stream generatorB generatorBStart -generator :: Word64 -> Word64 -> Word64 -> Word64 +generator :: Int -> Int -> Int -> Int generator divisor factor n = n * factor `rem` divisor -toWord16 :: Word64 -> Word16 +toWord16 :: Int -> Word16 toWord16 = fromIntegral -stream :: (Word64 -> Word64) -> Word64 -> [Word16] +stream :: (Int -> Int) -> Int -> [Word16] stream gen n0 = map toWord16 $ drop 1 $ iterate gen n0 filteredStream :: Word16 -> [Word16] -> [Word16] -filteredStream f str = filter ((== 0) . ( .&. f)) str +filteredStream f = filter ((== 0) . ( .&. f)) diff --git a/src/advent15/advent15other.hs b/src/advent15/advent15other.hs index 0802707..5f0459c 100644 --- a/src/advent15/advent15other.hs +++ b/src/advent15/advent15other.hs @@ -9,7 +9,7 @@ import Data.List (stripPrefix) import Data.Word (Word64) -- | Returns the initial values for generators A and B. -parse :: String -> (Word64, Word64) +-- parse :: String -> (Word64, Word64) parse _ = (873, 583) -- parse input = (read a, read b) where -- [line1, line2] = lines input @@ -23,40 +23,58 @@ main = do print $ day15b "none" --- | One step of generator A. -genA :: Word64 -> Word64 -genA x = x * 16807 `mod` 2147483647 --- | One step of generator B. -genB :: Word64 -> Word64 +genA, genB :: Int -> Int +genA x = x * 16807 `mod` 2147483647 genB x = x * 48271 `mod` 2147483647 --- | Step generator A until a multiple of 4. -genA' :: Word64 -> Word64 -genA' x = let y = genA x in if y .&. 3 == 0 then y else genA' y +day15a :: String -> Int +day15a input = length . filter id . take 40000000 $ zipWith (==) a b where + (a0, b0) = parse input + a = map (.&. 0xffff) $ iterate genA a0 + b = map (.&. 0xffff) $ iterate genB b0 --- | Step generator A until a multiple of 8. -genB' :: Word64 -> Word64 -genB' x = let y = genB x in if y .&. 7 == 0 then y else genB' y +day15b :: String -> Int +day15b input = length . filter id . take 5000000 $ zipWith (==) a b where + (a0, b0) = parse input + a = map (.&. 0xffff) . filter ((== 0) . (`mod` 4)) $ iterate genA a0 + b = map (.&. 0xffff) . filter ((== 0) . (`mod` 8)) $ iterate genB b0 --- | One step of both generators A and B. -gen :: (Word64, Word64) -> (Word64, Word64) -gen = genA *** genB --- | Step both generators A and B until a multiple of 4 and 8 respectively. -gen' :: (Word64, Word64) -> (Word64, Word64) -gen' = genA' *** genB' +-- -- | One step of generator A. +-- genA :: Word64 -> Word64 +-- genA x = x * 16807 `mod` 2147483647 --- | prop> count p f x n == length (filter p . take n . tail $ iterate f x) -count :: (a -> Bool) -> (a -> a) -> a -> Int -> Int -count p f = count' 0 where - count' !k x 0 = k - count' !k x n = count' (if p y then k + 1 else k) y (n - 1) where y = f x +-- -- | One step of generator B. +-- genB :: Word64 -> Word64 +-- genB x = x * 48271 `mod` 2147483647 -day15a :: String -> Int -day15a input = - count (uncurry ((==) `on` (.&. 0xffff))) gen (parse input) 40000000 +-- -- | Step generator A until a multiple of 4. +-- genA' :: Word64 -> Word64 +-- genA' x = let y = genA x in if y .&. 3 == 0 then y else genA' y -day15b :: String -> Int -day15b input = - count (uncurry ((==) `on` (.&. 0xffff))) gen' (parse input) 5000000 +-- -- | Step generator A until a multiple of 8. +-- genB' :: Word64 -> Word64 +-- genB' x = let y = genB x in if y .&. 7 == 0 then y else genB' y + +-- -- | One step of both generators A and B. +-- gen :: (Word64, Word64) -> (Word64, Word64) +-- gen = genA *** genB + +-- -- | Step both generators A and B until a multiple of 4 and 8 respectively. +-- gen' :: (Word64, Word64) -> (Word64, Word64) +-- gen' = genA' *** genB' + +-- -- | prop> count p f x n == length (filter p . take n . tail $ iterate f x) +-- count :: (a -> Bool) -> (a -> a) -> a -> Int -> Int +-- count p f = count' 0 where +-- count' !k x 0 = k +-- count' !k x n = count' (if p y then k + 1 else k) y (n - 1) where y = f x + +-- day15a :: String -> Int +-- day15a input = +-- count (uncurry ((==) `on` (.&. 0xffff))) gen (parse input) 40000000 + +-- day15b :: String -> Int +-- day15b input = +-- count (uncurry ((==) `on` (.&. 0xffff))) gen' (parse input) 5000000 -- 2.34.1