module Address where import Control.Monad (guard) import Data.Ratio ((%), denominator) import Fractal.RUFF.Mandelbrot.Address (AngledInternalAddress(Unangled, Angled), Angle, angledFromList, angledToList) import Utils (safeRead) parseAngles :: String -> Maybe [Angle] parseAngles = mapM parseAngle . words parseAngle :: String -> Maybe Angle parseAngle s = do let (n, d) = break ('/'==) s n' <- safeRead (filter (' '/=) n) d' <- safeRead (filter (' '/=) (drop 1 d)) guard (0 < n' && n' < d') return $ n' % d' splitAddress :: AngledInternalAddress -> Maybe (AngledInternalAddress, [Angle]) splitAddress a = let (ps0, rs0) = unzip $ angledToList a ps1 = reverse ps0 rs1 = reverse (Nothing : init rs0) prs1 = zip ps1 rs1 f ((p, Just r):qrs@((q, _):_)) acc | p == denominator r * q = f qrs (r : acc) f prs acc = g prs acc g prs acc = let (ps2, rs2) = unzip prs ps3 = reverse ps2 rs3 = reverse (Nothing : init rs2) prs3 = zip ps3 rs3 aa = angledFromList prs3 in case aa of Nothing -> Nothing Just aa' -> Just (aa', acc) in f prs1 [] joinAddress :: AngledInternalAddress -> [Angle] -> AngledInternalAddress joinAddress (Unangled p) [] = Unangled p joinAddress (Unangled p) (r:rs) = Angled p r (joinAddress (Unangled $ p * denominator r) rs) joinAddress (Angled p r a) rs = Angled p r (joinAddress a rs) addressPeriod :: AngledInternalAddress -> Integer addressPeriod (Unangled p) = p addressPeriod (Angled _ _ a) = addressPeriod a