content: 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)
  