-- | Determines whether it is numberwang.
module Acme.Colosson
    ( numberwang
    ) where

import System.Random
import System.IO.Unsafe

data Wanger = Numb Bool Wanger Wanger

simon :: Wanger -> Integer -> Bool
simon (Numb b _ _) 0 = b
simon (Numb _ x y) n = case divMod n 2 of
    (m, 0) -> simon x m
    (m, _) -> simon y m

julie :: StdGen -> Wanger
julie g0 =
    let (b,  g1) = random g0
        (g2, g3) = split  g1
    in  Numb b (julie g2) (julie g3)

colosson :: IO (Integer -> Bool)
colosson = do
    nt <- julie `fmap` newStdGen
    pt <- julie `fmap` newStdGen
    let f n | n < 0     = simon nt (-n)
            | otherwise = simon pt n
    return f

-- | Is it numberwang?
numberwang :: Integer -> Bool
numberwang = unsafePerformIO colosson
{-# NOINLINE numberwang #-}