Separate the Numbers

  • + 0 comments

    Haskell

    More haskell-y than necessary, but fun. Relies on the max input string length of 32.

    module Main where
    
    import Data.List (find, inits)
    import Data.Set qualified as S
    
    -- problem constraint
    maxsize :: Int
    maxsize = 32
    
    -- seed & iterations
    newtype BeautifulString = BeautifulString (Int, Int)
    
    -- conversion to string
    instance Show BeautifulString where
        show (BeautifulString (seed, iterations)) = concatMap show [seed .. seed + iterations - 1]
    
    -- all BSs with seed and net string length <= maxsize
    validBSs :: Int -> S.Set String
    validBSs seed =
        let bss = [show $ BeautifulString (seed, k) | k <- [2 ..]]
         in S.fromList $ takeWhile (\bs -> length bs <= maxsize) bss
    
    -- if string is beautiful, return the seed
    isBeautiful :: String -> Maybe Int
    isBeautiful "" = Nothing
    isBeautiful ('0' : _) = Nothing
    isBeautiful s =
        let stemStrings = tail $ inits s -- first is ""
            halflen = length s `div` 2
            validSeeds = map read $ takeWhile (\stem -> length stem <= halflen) stemStrings
         in find (S.member s . validBSs) validSeeds
    
    -- display result in required format
    showIsBeautiful :: String -> String
    showIsBeautiful s =
        case isBeautiful s of
            Just n -> "YES " <> show n
            Nothing -> "NO"
    
    -- process input list, ignoring the first line (the count)
    main :: IO ()
    main = getContents >>= mapM_ (putStrLn . showIsBeautiful) . tail . lines