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
242424 ==> 18 ==> 9
Análogamente, si n es 4 y x es 7988 las transformaciones son
(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
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]]
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]]
sumaReducidaDigitosRepeticiones ::Integer->Integer->Integer
sumaReducidaDigitosRepeticiones x n =until(<10) sumaCifras $ sumaCifras n * x
where sumaCifras =toInteger . sum . map digitToInt . show
sumaReducidaDigitosRepeticiones :: Integer -> Integer -> Integer
sumaReducidaDigitosRepeticiones x n = until (< 10) sumaCifras $ sumaCifras n * x
where sumaCifras = toInteger . sum . map digitToInt . show
import Graphics.Gnuplot.Simple
lista ::[Integer]
lista =[sumaReducidaDigitosRepeticiones x x | x<-[1..]]
grafica ::Integer->IO()
grafica n= plotList [Key Nothing](take(fromInteger n) lista)
import Graphics.Gnuplot.Simple
lista :: [Integer]
lista = [sumaReducidaDigitosRepeticiones x x | x<-[1..]]
grafica :: Integer -> IO ()
grafica n= plotList [Key Nothing] (take (fromInteger n) lista)
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)
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)
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]]
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]]
/* 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 */
/* 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 */
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.
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)
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)
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: