In [1]:
import Data.List
import Data.Char
import Data.Function
import Data.Maybe
import qualified Data.IntMap as IntMap
In [2]:
type State = (IntMap.IntMap (Int, Int), Int)
computeState :: State -> (Int, Char) -> State
computeState (oldMap, oldLevel) (index, c) =
let
newLevel = (if isDigit c then succ else pred) oldLevel
rangeStart = fromMaybe index $ fmap fst $ IntMap.lookup newLevel oldMap
newMap = IntMap.insert newLevel (rangeStart, index) oldMap
in
(newMap, newLevel)
In [3]:
longestSubarray :: String -> String
longestSubarray s =
let
levelMap = fst $ foldl' computeState (IntMap.singleton 0 (0, 0), 0) (zip [1..] s)
(left, right) = minimumBy (compare `on` uncurry (-)) (IntMap.elems levelMap)
in
take (right - left) $ drop left s
In [4]:
longestSubarray "AAA7BB88"
In [5]:
import Test.QuickCheck
In [6]:
testCountDigitsLetters :: String -> Bool
testCountDigitsLetters s =
(==) 0 $ sum $ map (\c -> if isDigit c then 1 else -1) (longestSubarray s)
In [7]:
quickCheck testCountDigitsLetters
In [8]:
testSubstringProperty :: String -> Bool
testSubstringProperty s =
isInfixOf (longestSubarray s) s
In [9]:
quickCheck testSubstringProperty