+-- useRule :: Interval -> Rule -> [Interval]
+-- useRule (Iv xl xh) (Rule (Iv rl rh) d)
+-- | x >= src && x < (src + rl) = Just (x + dest - src)
+-- | otherwise = Nothing
+
+-- useRules :: [Rule] -> Int -> Int
+-- useRules rs x
+-- | null ruleResults = x
+-- | otherwise = head ruleResults
+-- where ruleResults = catMaybes $ fmap (useRule x) rs
+
+useRule :: Rule -> Interval -> ([Interval], [Interval], [Rule])
+useRule (Rule (Iv rl rh) d) (Iv xl xh) = (newResults, newIvs, newRules)
+ where newResults =
+ filter legalInterval [ Iv (min xl rl) (min xh (rl - 1)) -- input below rule
+ , Iv ((max xl rl) + d) ((min xh rh) + d)] -- input within rule
+ newIvs = filter legalInterval [Iv (max xl (rh + 1)) (max xh rh)] -- input above rule
+ newRules = filter legalRule [Rule (Iv (max (xh + 1) rl) (max xh rh)) d] -- rule above input
+
+
+useRules :: [Rule] -> [Interval] -> [Interval]
+useRules [] ivs = ivs
+useRules _ [] = []
+useRules (r@(Rule (Iv rl rh) d):rs) (iv@(Iv xl xh):ivs)
+ | rh < xl = useRules rs (iv:ivs)
+ | xh < rl = iv : useRules (r:rs) ivs
+ | otherwise = newResults ++ (useRules (newRules ++ rs) (newIvs ++ ivs))
+ where (newResults, newIvs, newRules) = useRule r iv
+
+
+legalInterval :: Interval -> Bool
+legalInterval (Iv l h) = l <= h