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.


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.