import Control.Lens ((.~), ix, (&)) import Data.Numbers.Primes (isPrime) import Data.List (find, intercalate) import Data.Char (intToDigit) import Data.Maybe (mapMaybe) import Data.List.Split (chunksOf) import Text.Printf (printf) isUnprimable :: Int -> Bool isUnprimable = all (not . isPrime) . swapdigits swapdigits :: Int -> [Int] swapdigits n = map read $ go $ pred $ length digits where digits = show n go (-1) = [] go n'' = map (\x -> digits & (ix n'') .~ intToDigit x) [0..9] <> go (pred n'') unPrimeable :: [Int] unPrimeable = filter isUnprimable [1..] main :: IO () main = do printf "First 35 unprimeable numbers:\n%s\n\n" $ show $ take 35 unPrimeable printf "600th unprimeable number: %d\n\n" $ unPrimeable !! 599 mapM_ (uncurry (printf "Lowest unprimeable number ending with %d: %10s\n")) $ mapMaybe lowest [0..9] where thousands = reverse . intercalate "," . chunksOf 3 . reverse lowest n = do x <- find (\x -> x `mod` 10 == n) unPrimeable pure (n, thousands $ show x)