40 lines
1.1 KiB
Text
40 lines
1.1 KiB
Text
module Main
|
|
import Data.Vect
|
|
|
|
isOdd : (x : Int) -> Bool
|
|
isOdd x = case mod x 2 of
|
|
0 => False
|
|
1 => True
|
|
|
|
popcnt : Int -> Int
|
|
popcnt 0 = 0
|
|
popcnt x = case isOdd x of
|
|
False => popcnt (shiftR x 1)
|
|
True => 1 + popcnt (shiftR x 1)
|
|
|
|
isOdious : Int -> Bool
|
|
isOdious k = isOdd (popcnt k)
|
|
|
|
isEvil : Int -> Bool
|
|
isEvil k = not (isOdious k)
|
|
|
|
filterUnfoldN : (n : Nat) ->
|
|
(pred : Int -> Bool) -> (f : Int -> a) ->
|
|
(next : Int -> Int) -> (seed : Int) ->
|
|
Vect n a
|
|
filterUnfoldN Z pred f next seed = []
|
|
filterUnfoldN (S k) pred f next seed =
|
|
if pred seed
|
|
then (f seed) :: filterUnfoldN k pred f next (next seed)
|
|
else filterUnfoldN (S k) pred f next (next seed)
|
|
|
|
printCompact : (Show a) => Vect n a -> IO ()
|
|
printCompact v = putStrLn (unwords (map show (toList v)))
|
|
|
|
main : IO ()
|
|
main = do putStr "popcnt(3**i): "
|
|
printCompact (filterUnfoldN 30 (\_ => True) popcnt (3 *) 1)
|
|
putStr "Evil: "
|
|
printCompact (filterUnfoldN 30 isEvil id (1 +) 0)
|
|
putStr "Odious: "
|
|
printCompact (filterUnfoldN 30 isOdious id (1 +) 0)
|