Primos circulares
Un primo circular es un número tal que todas las rotaciones de sus dígitos producen números primos. Por ejemplo, 195 es un primo circular ya que las rotaciones de sus dígitos son 197, 971 y 719 y los tres números son primos.
Definir la constante
circulares :: [Integer]
cuyo valor es la lista de los números primos circulares. Por ejemplo,
take 12 circulares == [2,3,5,7,11,13,17,31,37,71,73,79] circulares !! 50 == 939193
Soluciones
import Data.Numbers.Primes circulares :: [Integer] circulares = filter esCircular primes -- (esCircular n) se verifica si n es un número circular. Por ejemplo, -- esCircular 197 == True -- esCircular 157 == False esCircular :: Integer -> Bool esCircular = all (isPrime . read) . rotaciones . show -- (rotaciones xs) es la lista de las rotaciones obtenidas desplazando -- el primer elemento xs al final. Por ejemplo, -- rotaciones [2,3,5] == [[2,3,5],[3,5,2],[5,2,3]] rotaciones1 :: [a] -> [[a]] rotaciones1 xs = reverse (aux (length xs) [xs]) where aux 1 yss = yss aux n (ys:yss) = aux (n-1) (rota ys : ys :yss) -- 2ª definición de rotaciones (con iterate) rotaciones2 :: [a] -> [[a]] rotaciones2 xs = take (length xs) (iterate rota xs) -- En lo sucesivo usaremos la 2ª definición rotaciones :: [a] -> [[a]] rotaciones = rotaciones2 -- (rota xs) es la lista añadiendo el primer elemento de xs al -- final. Por ejemplo, -- rota [3,2,5,7] == [2,5,7,3] rota :: [a] -> [a] rota (x:xs) = xs ++ [x] -- (rotacionesNumero n) es la lista de las rotaciones obtenidas desplazando -- el primer dígito de n al final. Por ejemplo, -- rotacionesNumero 325 == [325,253,532] rotacionesNumero :: Integer -> [Integer] rotacionesNumero n = map read (rotaciones (show n)) -- Se pueden eliminar los argumentos rotacionesNumero2 :: Integer -> [Integer] rotacionesNumero2 = map read . rotaciones . show -- 2ª definición -- ============= -- Nota. La 2ª definición es una mejora observando que para que n sea un -- número primo circular es necesario que todos los dígitos de n sean -- impares. circulares2 :: [Integer] circulares2 = filter esCircular2 primes -- (esCircular2 n) se verifica si n es un número circular. Por ejemplo, -- esCircular2 197 == True -- esCircular2 157 == False esCircular2 :: Integer -> Bool esCircular2 n = digitosImpares n && all (isPrime . read) (rotaciones (show n)) -- (digitosImpares n) se verifica si todos los dígitos de n son -- impares. Por ejemplo, -- digitosImpares 7351 == True -- digitosImpares 7341 == False digitosImpares :: Integer -> Bool digitosImpares n = all (`elem` "135679") (show n) -- Comparación de eficiencia -- λ> circulares !! 45 -- 319993 -- (6.33 secs, 3322708864 bytes) -- -- λ> circulares2 !! 45 -- 331999 -- (0.96 secs, 448282368 bytes)