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
1 |
242424 ==> 18 ==> 9 |
Análogamente, si n es 4 y x es 7988 las transformaciones son
1 |
7988798879887988 ==> 128 ==> 11 ==> 2 |
Definir las funciones
1 2 |
sumaReducidaDigitosRepeticiones :: Integer -> Integer -> Integer grafica :: Integer -> IO () |
tales que
- (sumaReducidaDigitosRepeticiones n x) es la suma reducida de n repeticiones de x. Por ejemplo
1 2 3 |
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
Soluciones
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
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]] |
Completo tu definición añadiéndole la gráfica
Sería necesario añadir el caso trivial, es decir:
En caso contrario al pedirle este caso te da 9 lo cual es claramente incorrecto.
λ> sumaReducidaDigitosRepeticiones 0 2
9
En Maxima:
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.
Después de pensar un rato sobre el ejercicio propuesto, se me ha ocurrido, en Maxima, una definición mucho más eficiente: