gruff-0.1: Address.hs
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