Circular prime numbers

2020-04-20 12:52发布

I am trying to convert the following function which test the number if it's prime to another one that test if the integer is a circular prime. eg. 1193 is a circular prime, since 1931, 9311 and 3119 all are also prime. So i need to rotate the digits of the integer and test if the number is prime or not. any ideas? note: I am new to Haskell Programming

isPrime ::  Integer -> Bool

isPrime 1 = False
isPrime 2 = True
isPrime n 
 | (length [x | x <- [2 .. n-1],  n  `mod` x == 0]) > 0 = False
 | otherwise = True 


isCircPrime ::  Integer -> Bool

2条回答
放荡不羁爱自由
2楼-- · 2020-04-20 13:19

Referencing your question here, you can achieve what you want by adding a single new function:

check :: Integer -> Bool
check n = and [isPrime (stringToInt cs) | cs <- circle (intToString n)]

This is to add an easier to understand solution from where you already were in your specific code, as I can see you were asking for that specifically. Usage:

*Main> check 1931
True

*Main> check 1019
False

Mind you, I have made some type-changes. I assume you want each function to be type-specific, due to their names. Full code, taken from your example:

circle :: String -> [String]
circle xs = take (length xs) (iterate (\(y:ys) -> ys ++ [y]) xs)

stringToInt :: String -> Integer
stringToInt x = read (x) :: Integer

intToString :: Integer -> String
intToString x = show x

isPrime :: Integer -> Bool
isPrime 1 = False
isPrime 2 = True
isPrime n
    | (length [x | x <- [2 .. n-1], n `mod` x == 0]) > 0 = False
    | otherwise = True

check :: Integer -> Bool
check n = and [isPrime (stringToInt cs) | cs <- circle (intToString n)]
查看更多
Fickle 薄情
3楼-- · 2020-04-20 13:45

You can improve the efficiency and elegance of your isPrime function easily by implementing it as:

isPrime ::  Integral i => i -> Bool
isPrime 1 = False
isPrime n = all ((/=) 0 . mod n) (takeWhile (\x -> x*x <= n) [2..])

In order to rotate numbers, we can make use of two helper functions here: one to convert a number to a list of digits, and one to convert a list of digits to a number, we do this in reverse, since that is more convenient to implement, but will not matter:

num2dig :: Integral i => i -> [i]
num2dig n | n < 10 = [n]
          | otherwise = r : num2dig q
    where (q, r) = quotRem n 10


dig2num :: (Foldable t, Num a) => t a -> a
dig2num = foldr ((. (10 *)) . (+)) 0

Now we can make a simple function to generate, for a list of items, all rotations:

import Control.Applicative(liftA2)
import Data.List(inits, tails)

rots :: [a] -> [[a]]
rots = drop 1 . liftA2 (zipWith (++)) tails inits

So we can use this to construct all rotated numbers:

rotnum :: Integral i => i -> [i]
rotnum = map dig2num . rots . num2dig

For example for 1425, the rotated numbers are:

Prelude Control.Applicative Data.List> rotnum 1425
[5142,2514,4251,1425]

I leave using isPrime on these numbers as an exercise.

查看更多
登录 后发表回答