import System.IO.Unsafe

font=[
      [" ## ",
       "#  #",
       "#  #",
       "#  #",
       " ## "
      ],
      ["  # ",
       " ## ",
       "# # ",
       "  # ",
       "  # "
      ],
      [" ## ",
       "#  #",
       "  # ",
       " #  ",
       "####"
      ],
      [" ## ",
       "   #",
       " ###",
       "   #",
       " ## "
      ],
      ["  # ",
       " ## ",
       "# # ",
       "####",
       "  # "
      ],
      ["####",
       "#   ",
       "### ",
       "   #",
       "### "
      ],
      [" ## ",
       "#   ",
       "### ",
       "#  #",
       " ## "
      ],
      ["####",
       "   #",
       "  # ",
       " #  ",
       "#   "
      ],
      [" ## ",
       "#  #",
       " ## ",
       "#  #",
       " ## "
      ],
      [" ## ",
       "#  #",
       " ###",
       "   #",
       " ## "
      ]
     ]

fontToNumber font = foldr toNumber 0 $ concatMap (concat.reverse) font
  where
    toNumber a b = b*2 + if a=='#' then 1 else 0
    

bitmapSource= 
  let str=unsafePerformIO $ readFile "bitmapa.pbm"
  in lineSplitter 367 $ concat(drop 3 $ lines str)
  
lineSplitter n = splitIt
  where
    splitIt str = splitIt2 $ splitAt n str
    splitIt2 ([],_) = []
    splitIt2 (pre,rest) = pre : splitIt rest


bitmapSourceToNumber bs = foldr toNumber 0 (concat $ reverse bs)
  where
    toNumber a b = b*2 + if a=='1' then 1 else 0


fontNumber = fontToNumber font

bitmapSourceNumber = bitmapSourceToNumber bitmapSource

pow x 0 = 1
pow x y = pow2 y x 1
  where
    pow2 0 b r = r
    pow2 a b r = pow2 (a `div` 2) (b*b) (r*(if a `mod` 2 == 1 then b else 1))

renderMap :: Int -> Int -> Int -> Int -> (Float->Float->Bool) -> [[Bool]]
renderMap x1 x2 y1 y2 fn =
  [[fn (fromIntegral x) (fromIntegral y)|x<-[x1..x2]]|y<-(reverse [y1..y2])]

renderChar True = "#"
renderChar False = " "

mapToString :: [[Bool]] -> String
mapToString = concatMap (\x->(concatMap renderChar x)++"\n")


nnn = (fontNumber + (pow 2 200) * bitmapSourceNumber)


renderTile :: Integer -> Integer -> Integer -> (Float->Float->Integer)
renderTile tile w h x y =
  let 
    ix = floor x
    iy = floor y
  in
   if ix >= 0 && iy >= 0 && ix < w && iy < h then
     fromIntegral ((tile `div` (pow 2 (w*iy+ix))) `mod` 2)
   else
     0

bitmap :: Float -> Float -> Bool
bitmap x y =
  0 < (rf x y nnn (floor (logBase 10 (fromIntegral nnn)))) + (renderTile (nnn `div` (pow 2 200)) 100 100 x y)

rf :: Float -> Float -> Integer -> Integer -> Integer
rf x y k p | p >=0 = (renderTile (nnn `div` (pow 2 (20*(k `mod` 10)))) 4 5 (x-(fromIntegral (5*(p`mod` 40)))) (y+6*fromIntegral(p `div` 40))) + 
                        (rf x y (k `div` 10) (p-1))
rf _ _ _ _ = 0



renderMapInt :: Int -> Int -> Int -> Int -> (Int->Int->Bool) -> [[Bool]]
renderMapInt x1 x2 y1 y2 fn =
  [[fn x y|x<-[x1..x2]]|y<-(reverse [y1..y2])]

renderTileInt :: Integer -> Int -> Int -> (Int->Int->Integer)
renderTileInt tile w h x y =
  let 
    ix = x
    iy = y
  in
   if ix >= 0 && iy >= 0 && ix < w && iy < h then
     ((tile `div` (pow 2 (w*iy+ix))) `mod` 2)
   else
     0

bitmapInt :: Int -> Int -> Bool
bitmapInt x y =
  0 < (rfInt x y nnn (floor (logBase 10 (fromIntegral nnn)))) + (renderTileInt (nnn `div` (pow 2 200)) 100 100 x y)

rfInt :: Int -> Int -> Integer -> Integer -> Integer
rfInt x y k p | p >=0 = (renderTileInt (nnn `div` (pow 2 (20*(k `mod` 10)))) 4 5 (x-(fromIntegral (5*(p`mod` 40)))) (y+6*fromIntegral(p `div` 40))) + 
                        (rfInt x y (k `div` 10) (p-1))
rfInt _ _ _ _ = 0


-- g :: Integer -> Integer -> Integer -> (Float->Float->Float)
-- g t w h x y =
--   let 
--     ix = floor x
--     iy = floor y
--   in
--    if ix >= 0 && iy >= 0 && ix < w && iy < h then
--      fromIntegral ((t `div` (pow 2 (w*iy+ix))) `mod` 2)
--    else
--      0
--
-- f :: Float -> Float -> Bool
-- f x y =
--   0 < (h x y nnn (floor (logBase 10 (fromIntegral nnn)))) + (g (nnn `div` (pow 2 200)) 100 100 x (y-6))
--
-- h :: Float -> Float -> Integer -> Integer -> Integer
-- h x y k p | p >=0 = (g (nnn `div` (pow 2 (20*(k `mod` 10)))) 4 5 (x-(fromIntegral (5*p))) y) + 
--                         (h x y (k `div` 10) (p-1))
-- h _ _ _ _ = 0




main = do
  putStrLn $ mapToString $ renderMapInt 0 20 (-10) 20 bitmapInt
  putStrLn $ show $ nnn



