import Data.Char (chr, digitToInt, intToDigit, isDigit, ord) import Data.Complex (Complex (..), imagPart, realPart) import Data.List (delete, elemIndex) import Data.Maybe (fromMaybe) base :: Complex Float base = 0 :+ 2 quotRemPositive :: Int -> Int -> (Int, Int) quotRemPositive a b | r < 0 = (1 + q, floor (realPart (-base ^^ 2)) + r) | otherwise = (q, r) where (q, r) = quotRem a b digitToIntQI :: Char -> Int digitToIntQI c | isDigit c = digitToInt c | otherwise = ord c - ord 'a' + 10 shiftRight :: String -> String shiftRight n | l == '0' = h | otherwise = h <> ('.' : [l]) where (l, h) = (last n, init n) intToDigitQI :: Int -> Char intToDigitQI i | i `elem` [0 .. 9] = intToDigit i | otherwise = chr (i - 10 + ord 'a') fromQItoComplex :: String -> Complex Float -> Complex Float fromQItoComplex num b = let dot = fromMaybe (length num) (elemIndex '.' num) in fst $ foldl ( \(a, indx) x -> ( a + fromIntegral (digitToIntQI x) * (b ^^ (dot - indx)), indx + 1 ) ) (0, 1) (delete '.' num) euclidEr :: Int -> Int -> [Int] -> [Int] euclidEr a b l | a == 0 = l | otherwise = let (q, r) = quotRemPositive a b in euclidEr q b (0 : r : l) fromIntToQI :: Int -> [Int] fromIntToQI 0 = [0] fromIntToQI x = tail ( euclidEr x (floor $ realPart (base ^^ 2)) [] ) getCuid :: Complex Int -> Int getCuid c = imagPart c * floor (imagPart (-base)) qizip :: Complex Int -> [Int] qizip c = let (r, i) = ( fromIntToQI (realPart c) <> [0], fromIntToQI (getCuid c) ) in let m = min (length r) (length i) in take (length r - m) r <> take (length i - m) i <> reverse ( zipWith (+) (take m (reverse r)) (take m (reverse i)) ) fromComplexToQI :: Complex Int -> String fromComplexToQI = shiftRight . fmap intToDigitQI . qizip main :: IO () main = putStrLn (fromComplexToQI (35 :+ 23)) >> print (fromQItoComplex "10.2" base)