Ir al contenido principal

Número primo de Sheldon

En el episodio número 73 de la serie The Big Bang Theory, Sheldon Cooper enuncia lo siguiente:

«El mejor número es el 73. El 73 es el 21-ésimo número primo. Al invertir sus cifras obtenemos 37, que es el primo número 12. Y al invertir este obtenemos 21, que es el producto de ─agarraos fuerte─ 7 y 3.»

Se define un número primo de Sheldon como: el n-ésimo número primo p(n) será un primo de Sheldon si cumple que el producto de sus dígitos es n y si, además, el número que se obtiene al invertir sus cifras, rev(p(n)), es el rev(n)-ésimo número primo; es decir, si rev(p(n)) = p(rev(n)).

Definir la función

esPrimoSheldon :: Int -> Bool

tal que (esPrimoSheldon x) se verifica si x un primo de Sheldon. Por ejemplo,

esPrimoSheldon 73  ==  True
esPrimoSheldon 79  ==  False

Comprobar con QuickCheck que 73 es el único primo de Sheldon.

Nota: Este ejercicio está basado en la noticia Descubierta una nueva propiedad de los números primos gracias a The Big Bang Theory donde podéis leer más información sobre el tema, entre ello la prueba de que el 73 es el único número primo de Sheldon.


Soluciones

import Data.Char           (digitToInt)
import Data.List           (elemIndex)
import Data.Maybe          (fromJust)
import Data.Numbers.Primes (isPrime, primes)
import Test.QuickCheck     (Property, (==>), quickCheck)

-- 1ª definición
-- =============

esPrimoSheldon :: Int -> Bool
esPrimoSheldon x =
     n > 0
  && x == primes !! (n - 1)
  && inverso x == primes !! (inverso n - 1)
  where n = productoDigitos x

-- (productoDigitos x) es el producto de los dígitos de x. Por ejemplo,
--    productoDigitos 73  ==  21
productoDigitos :: Int -> Int
productoDigitos x = product (map digitToInt (show x))

-- (inverso x) es el número obtenido invirtiendo el orden de los dígitos
-- de x. Por ejemplo,
--    inverso 735  ==  537
inverso :: Int -> Int
inverso x = read (reverse (show x))

-- 2ª definición
-- =============

esPrimoSheldon2 :: Int -> Bool
esPrimoSheldon2 x =
     n > 0
  && x == primes !! (n - 1)
  && inverso2 x == primes !! (inverso2 n - 1)
  where n = productoDigitos2 x

-- (productoDigitos2 x) es el producto de los dígitos de x. Por ejemplo,
--    productoDigitos2 73  ==  21
productoDigitos2 :: Int -> Int
productoDigitos2 = product . map digitToInt . show

-- (inverso2 x) es el número obtenido invirtiendo el orden de los dígitos
-- de x. Por ejemplo,
--    inverso2 735  ==  537
inverso2 :: Int -> Int
inverso2 = read . reverse . show

-- 3ª definición
-- =============

esPrimoSheldon3 :: Int -> Bool
esPrimoSheldon3 n = isPrime n && p1 && p2
  where p  = primes
        i1 = fromJust (elemIndex n p) + 1
        i2 = read (reverse (show i1))
        p1 = i1 == product (map digitToInt (show n))
        p2 = read (reverse (show n)) == p !! (i2 - 1)

-- Propiedad de primo de Sheldon
-- =============================

-- La propiedad es
prop_primoDeShelldon :: Int -> Property
prop_primoDeShelldon x =
  x >= 0 ==> esPrimoSheldon x == (x == 73)

-- La comprobación es
--    λ> quickCheck prop_primoDeShelldon
--    +++ OK, passed 100 tests.