#!/usr/bin/env runghc

import Data.HashSet (HashSet, fromList, member)
import Data.List
import Data.Numbers.Primes
import System.Environment
import System.Exit
import System.IO


startDigOK :: Integer -> Bool
startDigOK n = head (show n) `elem` "1379"


filtPrimes :: [Integer]
filtPrimes = filter startDigOK primes



nDigsFPr :: Integer -> [Integer]
nDigsFPr n =
  takeWhile (< hi) $ dropWhile (< lo) filtPrimes
  where lo = 10 ^ (n - 1)
        hi = 10 ^ n


nDigsFPrHS :: Integer -> HashSet Integer
nDigsFPrHS n = fromList $ nDigsFPr n





fPrByDigs :: [HashSet Integer]
fPrByDigs = map nDigsFPrHS [0 ..]

isEmirp :: Integer -> Bool
isEmirp n =
  let revStr = reverse $ show n
      reversed = read revStr
      hs = fPrByDigs !! length revStr
  in (startDigOK n) && (reversed /= n) && (reversed `member` hs)

emirps :: [Integer]
emirps = filter isEmirp primes

emirpSlice :: Integer -> Integer -> [Integer]
emirpSlice from to =
  genericTake numToTake $ genericDrop numToDrop emirps
  where
    numToDrop = from - 1
    numToTake = 1 + to - from

emirpValues :: Integer -> Integer -> [Integer]
emirpValues lo hi =
  dropWhile (< lo) $ takeWhile (<= hi) emirps

usage = do
  name <- getProgName
  putStrLn $ "usage: " ++ name ++ " lo hi [slice | values]"
  exitFailure

main = do
  hSetBuffering stdout NoBuffering
  args <- getArgs
  fixedArgs <- case length args of
    1 -> return $ args ++ args ++ ["slice"]
    2 -> return $ args ++ ["slice"]
    3 -> return args
    _ -> usage
  let lo = read $ fixedArgs !! 0
      hi = read $ fixedArgs !! 1
  case fixedArgs !! 2 of
   "slice" -> print $ emirpSlice lo hi
   "values" -> print $ emirpValues lo hi
   _ -> usage