content: import Data.List (sort)
  import Control.Arrow ((&&&))
  
  -- VAMPIRE NUMBERS ------------------------------------------------------------
  vampires :: [Int]
  vampires = filter (not . null . fangs) [1 ..]
  
  fangs :: Int -> [(Int, Int)]
  fangs n
    | odd w = []
    | otherwise = ((,) <*> quot n) <$> filter isfang (integerFactors n)
    where
      ndigit :: Int -> Int
      ndigit 0 = 0
      ndigit n = 1 + ndigit (quot n 10)
      w = ndigit n
      xmin = 10 ^ (quot w 2 - 1)
      xmax = xmin * 10
      isfang x =
        x > xmin &&
        x < y &&
        y < xmax && -- same length
        (quot x 10 /= 0 || quot y 10 /= 0) && -- not zero-ended
        sort (show n) == sort (show x ++ show y)
        where
          y = quot n x
  
  -- FACTORS --------------------------------------------------------------------
  integerFactors :: Int -> [Int]
  integerFactors n
    | n < 1 = []
    | otherwise =
      lows ++
      (quot n <$>
       (if intSquared == n -- A perfect square,
          then tail -- and cofactor of square root would be redundant.
          else id)
         (reverse lows))
    where
      (intSquared, lows) =
        (^ 2) &&& (filter ((0 ==) . rem n) . enumFromTo 1) $
        floor (sqrt $ fromIntegral n)
  
  -- TEST -----------------------------------------------------------------------
  main :: IO [()]
  main =
    mapM
      (print . ((,) <*>) fangs)
      (take 25 vampires ++ [16758243290880, 24959017348650, 14593825548650])
  