import Data.List
import Control.Monad (guard)

isPrime :: Int -> Bool
isPrime n
  | n <= 3 = n > 1
  | n `mod` 2 == 0 || n `mod` 3 == 0 = False
  | otherwise = l2 5 n
  where l2 d n = x > n || l3 d n
          where x = d * d
                l3 d n
                  | n `mod` d == 0       = False
                  | n `mod` (d + 2) == 0 = False
                  | otherwise = l2 (d + 6) n

showPrime :: Int -> Int -> [(Int, Int)]
showPrime i n = if isPrime i
                then (n, i): showPrime (i+i) (n+1)
                else showPrime (i+1) n

digitGroup :: Int -> String
digitGroup = intercalate "," . reverse . map show . unfoldr (\n -> guard (n /= 0) >> pure (n `mod` 1000, n `div` 1000))

display :: (Int, Int) -> String
display (i, p) = show i ++ " " ++ digitGroup p

main = mapM_ (putStrLn . display) $ take 42 $ showPrime 42 1