Menu Close

Suma de los dígitos de las repeticiones de un número

Dados dos números naturales n y x, su suma reducida se obtiene a partir del número obtenido repitiendo n veces el x sumando sus dígitos hasta obtener un número con sólo un dígito. Por ejemplo, si n es 3 y x es 24 las transformaciones son

   242424 ==> 18 ==> 9

Análogamente, si n es 4 y x es 7988 las transformaciones son

   7988798879887988 ==> 128 ==> 11 ==> 2

Definir las funciones

   sumaReducidaDigitosRepeticiones :: Integer -> Integer -> Integer
   grafica                         :: Integer -> IO ()

tales que

  • (sumaReducidaDigitosRepeticiones n x) es la suma reducida de n repeticiones de x. Por ejemplo
     sumaReducidaDigitosRepeticiones 3 24                    ==  9
     sumaReducidaDigitosRepeticiones 4 7988                  == 2
     sumaReducidaDigitosRepeticiones (12^(10^7)) (12^(10^7)) == 9
  • (grafica n) dibuja la gráfica de los n primeros elementos de la sucesión cuyo elementos k-ésimo es (sumaReducidaDigitosRepeticiones k k). Por ejemplo, (grafica 50) dibuja
    Suma_de_los_digitos_de_las_repeticiones_de_un_numero50

Soluciones

import Data.List (genericReplicate)
import Graphics.Gnuplot.Simple
import Test.QuickCheck
 
-- 1ª solución
-- ===========
 
sumaReducidaDigitosRepeticiones :: Integer -> Integer -> Integer
sumaReducidaDigitosRepeticiones n x =
  sumaReducidaDigitos (repeticiones n x) 
 
-- (repeticiones n x) es el número obtenido repitiendo n veces el x. Por
-- ejemplo, 
--    repeticiones 3 24   ==  242424
--    repeticiones 4 325  ==  325325325325
repeticiones :: Integer -> Integer -> Integer
repeticiones n x = read (concat (genericReplicate n (show x)))
 
-- (sumaDigitos x) es la suma de los dígitos de x. Por ejemplo,
--    sumaDigitos 325  ==  10
sumaDigitos :: Integer -> Integer
sumaDigitos x | x < 10    = x
              | otherwise = b + sumaDigitos a
  where (a,b) = divMod x 10
 
-- (sumaReducidaDigitos x) es el número obtenido a partir de x
-- reiterando la suma de los dígitos hasta obtener un número con sólo un
-- dígito. Por ejemplo,
--    sumaReducidaDigitos 24   ==  6
--    sumaReducidaDigitos 325  ==  1
sumaReducidaDigitos :: Integer -> Integer
sumaReducidaDigitos x | x < 10    = x
                      | otherwise = sumaReducidaDigitos (sumaDigitos x)
 
-- 2ª solución
-- ===========
 
sumaReducidaDigitosRepeticiones2 :: Integer -> Integer -> Integer
sumaReducidaDigitosRepeticiones2 n x =
  sumaReducidaDigitos2 (n * sumaReducidaDigitos2 x) 
 
sumaReducidaDigitos2 :: Integer -> Integer
sumaReducidaDigitos2 0 = 0
sumaReducidaDigitos2 x | y == 0    = 9
                       | otherwise = y
  where y = x `mod` 9
 
-- Equivalencia de las definiciones
-- ================================
 
-- La propiedad es
prop_equiv :: Positive Integer -> Positive Integer -> Bool
prop_equiv (Positive n) (Positive x) =
  sumaReducidaDigitosRepeticiones n x == sumaReducidaDigitosRepeticiones2 n x 
 
-- La comprobación es
--    λ> quickCheck prop_equiv
--    +++ OK, passed 100 tests.
 
-- Comparación de eficiencia
-- =========================
 
--    λ> sumaReducidaDigitosRepeticiones (10^4) (10^4)
--    1
--    (2.00 secs, 574,667,384 bytes)
--    λ> sumaReducidaDigitosRepeticiones2 (10^4) (10^4)
--    1
--    (0.03 secs, 141,120 bytes)
 
-- Gráfica
-- =======
 
grafica :: Integer -> IO ()
grafica n =
  plotList [Key Nothing]
           [sumaReducidaDigitosRepeticiones2 k k | k <- [1..n]]
Medio

9 soluciones de “Suma de los dígitos de las repeticiones de un número

  1. antnavoro
    sumaReducidaDigitosRepeticiones :: Integer -> Integer -> Integer
    sumaReducidaDigitosRepeticiones x n = until (< 10) sumaCifras $ sumaCifras n * x
    where sumaCifras = toInteger . sum . map digitToInt . show
    • alerodrod5

      Completo tu definición añadiéndole la gráfica

      import Graphics.Gnuplot.Simple
       
      lista :: [Integer] 
      lista = [sumaReducidaDigitosRepeticiones x x | x<-[1..]]
       
      grafica                         :: Integer -> IO ()
      grafica n= plotList [Key Nothing] (take (fromInteger n) lista)
  2. jaibengue
    sumaReducidaDigitosRepeticiones :: Integer -> Integer -> Integer
    sumaReducidaDigitosRepeticiones a b | p == 0 = 9
                                        | otherwise = p
      where m = (a `mod` 9)
            n = (b `mod` 9)
            p = ((m*n) `mod` 9)
    • pabhueacu

      Sería necesario añadir el caso trivial, es decir:

      sumaReducidaDigitosRepeticiones 0 _ = 0

      En caso contrario al pedirle este caso te da 9 lo cual es claramente incorrecto.
      λ> sumaReducidaDigitosRepeticiones 0 2
      9

  3. agumaragu1
    import Graphics.Gnuplot.Simple
     
    sumaReducidaDigitosRepeticiones :: Integer -> Integer -> Integer
    sumaReducidaDigitosRepeticiones n x = aux (n * aux x)
      where aux a = until (<10) sumaD a
            sumaD y = sum [read [z] | z <- show y]
     
    grafica :: Integer -> IO ()
    grafica n = plotList [] [sumaReducidaDigitosRepeticiones k k | k <- [1..n]]
  4. carbremor

    En Maxima:

    /* nDigitos(n) es el número de dígitos de n. Por ejemplo,
          nDigitos(1492);
          4
     */
    nDigitos(n) := 1 + floor(log_10(n))$
     
    log_10(n) := log(n) / log(10)$
     
    /* repetirDigitos(n,k) es la cadena obtenida repitiendo k veces el
       número n. Por ejemplo, 
          repetirDigitos(24,3);
          "242424"
     */
    repetirDigitos(n,k) := block( 
        num: "", 
        for i:1 thru k  do 
            num : sconcat(num, n),   
        num)$
     
    /* La función sconcat concatena sus argumentos para producir una cadena. */
     
    /* sumaDigitos(n) es la suma de los dígitos del número n. Por ejemplo,
          sumaDigitos(369870);
          33
    */
    sumaDigitos(n):= block(
        istream : make_string_input_stream(sconcat("",n)),
            sum:"",
        sum:"",
        while (c : readchar(istream)) # false do 
            sum: sconcat(sum, "+", c),
        close(istream),
        eval_string(sum)    
    )$
     
    sumaReducidaDigitosRepeticiones(n,k) :=  block([k:k],
      unless nDigitos(n) * k = 1 do
        ( n : sumaDigitos(repetirDigitos(n,k)),
          k : 1),
      n)$
     
    /* Ejemplos: 
       (%i2) showtime : true$
       Evaluation took 0.0000 seconds (0.0000 elapsed)
       (%i3) sumaReducidaDigitosRepeticiones(24,3);
       Evaluation took 0.0900 seconds (1.0100 elapsed)
       (%o3) 9
       (%i4) sumaReducidaDigitosRepeticiones(4,7988);
       Evaluation took 7.5700 seconds (8.0100 elapsed)
       (%o4) 2
    */
     
    /* Para más información sobre las funciones
       http://maxima.sourceforge.net/docs/manual/maxima.html */
    • carbremor

      Explicación:

      La función make_string_input_stream devuelve un flujo de entrada que contiene partes de string junto con el carácter de final de fichero.

      La función close(istream) cierra el flujo de datos stream y devuelve true si stream había sido abierto. Un stream permite recorrer y recoger los datos simultáneamente.

      La función eval_string analiza sintácticamente la cadena str como una expresión de Maxima y la evalúa. Sólo se analiza la primera expresión si hay más de una.

      ==========

      En la función sumaDigitos creo un stream con el string del numero (para ello cojo el int y le concateno una cadena vacia sconcat(“”,n))

      Recorro el stream y para cada caracter, voy añadiendo al string sum un string ” + ” que sea la operacion de sumar digitos para que cuando acabe el while quede: 3 + 4 + 5 + 3 + 6

      Y despues uso eval_string para evaluar esa cadena suma y que de el resultado.

    • carbremor

      Después de pensar un rato sobre el ejercicio propuesto, se me ha ocurrido, en Maxima, una definición mucho más eficiente:

      (%i1)   sumaReducidaDigitosRepeticiones(n,k) :=
            if mod(n*k, 9) = 0  then 9
            else mod(n*k,9)$
       
      (%i2)   sumaReducidaDigitosRepeticiones(3,24);
          sumaReducidaDigitosRepeticiones(4,7988);
          sumaReducidaDigitosRepeticiones(12^(10^7), 12^(10^7));
          showtime : true$
      (%o2)   9
      (%o3)   2
      (%o4)   9
      Evaluation took 0.0000 seconds (0.0000 elapsed)
  5. albcarcas1
     
    import Graphics.Gnuplot.Simple
     
    sumaReducidaDigitosRepeticiones :: Integer -> Integer -> Integer
    sumaReducidaDigitosRepeticiones n x = aux (n*(sum(cifras x)))
       where aux a |a < 10 = a
                   |otherwise = aux (sum(cifras a))                         
    digitosRepeticiones :: [Integer]
    digitosRepeticiones = [sumaReducidaDigitosRepeticiones k k | k <- [1..]]
    grafica :: Integer -> IO ()
    grafica n = plotList [Key Nothing] (take (fromInteger n) digitosRepeticiones)

Escribe tu solución

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.