import Data.Ratio (Rational(..), (%), numerator, denominator)
import Data.List (unfoldr)
import Text.Printf (printf)


newtype Rat =
  Rat Rational

instance Show Rat where
  show (Rat n) = show (numerator n) <> ('/': show (denominator n))




digitsToNum :: Integer -> [Integer] -> Integer
digitsToNum b = foldr1 (\d acc -> b * acc + d)



numToDigits :: Integer -> Integer -> [Integer]
numToDigits _ 0 = [0]
numToDigits b n = unfoldr step n
  where
    step 0 = Nothing
    step m =
      let (q, r) = m `quotRem` b
      in Just (r, q)



vdc :: Integer -> Integer -> Rat
vdc b n
  | b < 2 = error "vdc: base must be  2"
  | otherwise =
    let ds = reverse $ numToDigits b n
    in Rat (digitsToNum b ds % b ^ length ds)


printVdcRanges :: ([Integer], [Integer]) -> IO ()
printVdcRanges (bases, nums) =
  mapM_
    putStrLn
    [ printf "Base%d:" b <> concatMap (printf "%5s" . show) rs
    | b <- bases 
    , let rs = map (vdc b) nums ]

main :: IO ()
main = do
  
  printVdcRanges ([2, 3, 4, 5], [0 .. 9])
  putStrLn []

  
  printVdcRanges ([123], [50,100 .. 300])