Autor Tema: Múltiplos de 7 con recursión en Python

0 Usuarios y 1 Visitante están viendo este tema.

21 Junio, 2020, 05:05 pm
Leído 699 veces

gorkam

  • Junior
  • Mensajes: 27
  • País: es
  • Karma: +0/-0
  • Sexo: Masculino
Buenas tardes, tengo el siguiente enunciado:
Un número natural n de varios dígitos es múltiplo de
7 si y solo si al restar al número sin el dígito de las unidades el doble de dicho dígito se obtiene un múltiplo
de 7. Por ejemplo, n = 1946 es múltiplo de 7 porque 194−12 es igual a 182, que a su vez es múltiplo de
7 porque 18−4= 14. Sin embargo, n= 5219 no es múltiplo de 7 porque 521−18 es igual a 503, que no es
múltiplo de 7 porque 50−6= 44.
El código iterativo me funciona bien pero no se como sacar el código recursivo. He pensado algo asi, pero no me funciona:
Código: [Seleccionar]
def div7rec(n):
    if n==0:
        return True
    else:
        return div7rec((n//10) - ((n%10*2))

Si alguien pudiera echarme una mano, lo agradecería. Si tenéis algún truco o algo para dominar y entender mejor recursividad también lo agradecería. Muchas gracias.

21 Junio, 2020, 10:00 pm
Respuesta #1

feriva

  • Matemático
  • Mensajes: 9,067
  • País: es
  • Karma: +1/-0
  • Sexo: Masculino
  • No soy matemático, eso es una etiqueta.
No sé, yo creo que lo que necesitas es algo así metido en bucle

Código: [Seleccionar]
s=str (n) # S es n convertido a cadena

Ucifra = int (s[-1:] ) # cifra del final convertida a entero.

dobleU = 2 * (Ucifra)  # El doble de la cifra del final.

Dcifras = int (s[:-1]) # Primeras cifras convertidas a entero.

R = Dcifras - dobleU  # Diferencia


Y a partir de ahí que R haga de nuevo número y se repita. Si es múltiplo de siete, llegará a 0 ó a 7 ó -7 y -14 (funcionará con números que tengan al menos dos cifras).

Saludos.


21 Junio, 2020, 10:15 pm
Respuesta #2

gorkam

  • Junior
  • Mensajes: 27
  • País: es
  • Karma: +0/-0
  • Sexo: Masculino
Es que no me dejan meter bucles, nos han dicho que en recursividad usemos condicionales....

21 Junio, 2020, 10:56 pm
Respuesta #3

Gustavo

  • Moderador Global
  • Mensajes: 1,803
  • País: co
  • Karma: +0/-0
Hola. La estructura de la recursión está bien, lo que hay que arreglar son los casos base. Nota que tu programa no tiene ningún retorno para números que no son múltiplos de 7 (en ningún lado hay un False), ni tiene buen retorno para algunos múltiplos de 7, como por ejemplo el 49 que retorna 4-9*2=-14. Mi sugerencia es que apliques el algoritmo (a mano) a múltiplos de 7 de dos cifras y notes que todos llegan a 0,-7 o -14. El resto de números llegan a un negativo distinto a los tres ya mencionados.

PD. Por favor no uses sólo mayúsculas en los títulos. Lo he cambiado.

21 Junio, 2020, 11:08 pm
Respuesta #4

feriva

  • Matemático
  • Mensajes: 9,067
  • País: es
  • Karma: +1/-0
  • Sexo: Masculino
  • No soy matemático, eso es una etiqueta.
Es que no me dejan meter bucles, nos han dicho que en recursividad usemos condicionales....

Bueno, quien dice un bucle dice una llamada dentro de la función; pero tendrás que usar el if algunos or para los distintos casos.

Saludos.

22 Junio, 2020, 10:56 am
Respuesta #5

feriva

  • Matemático
  • Mensajes: 9,067
  • País: es
  • Karma: +1/-0
  • Sexo: Masculino
  • No soy matemático, eso es una etiqueta.
Prueba éste, gorkam, a ver qué tal te va.

Código: [Seleccionar]
try:
def f(n):
if n == 0 or n == 7 or n == -7 or n == -14:
print ("n SI es multiplo de 7")
else:
s=str (n)
Ucifra = int (s[-1:] )
dobleU = 2 * (Ucifra) 
Dcifras = int (s[:-1])
n = Dcifras - dobleU
return f(n)
n = int (input ("introduce un entero positivo n de entrada: "))
f(n)
except:
print ("n NO es multiplo de 7 y/o no es positivo")

Editado

Saludos.

22 Junio, 2020, 06:06 pm
Respuesta #6

ingmarov

  • Moderador Global
  • Mensajes: 4,798
  • País: hn
  • Karma: +0/-0
  • Sexo: Masculino
Hola có digo corregido

Interesante solución feriva, aprovechando el error en la función int() para detener el ciclo.

Pongo otra forma, hice un poco de trampa porque estoy utilizando al final la función módulo. La utilizo cuando se ve fácil que es múltiplo de siete.

Código: [Seleccionar]
def prueba(n):
   a=n%10
    r=int((n-a)/10)
    resta=r-2*a
    if resta%100!=resta:
        print(resta)
        prueba(resta)
    else:
        print(resta)
        if resta%7==0:
            print("El número es múltiplo de siete porque {} lo es.".format(resta))
            return
        else:
            print("El número no es múltiplo de siete porque {} no lo es.".format(resta))
            return

prueba(int(input("ingresé un número entero mayor que 100: ")))
       


Saludos

No te confíes, revisa lo que escribo. Yo también me equivoco.
Odio el autocorrector de Android...

22 Junio, 2020, 09:15 pm
Respuesta #7

feriva

  • Matemático
  • Mensajes: 9,067
  • País: es
  • Karma: +1/-0
  • Sexo: Masculino
  • No soy matemático, eso es una etiqueta.
Hola, Ingmarov.

Hola código corregido
Pongo otra forma

Me da problemas con algunos números; si abajo invoco la función con, por ejemplo, prueba(38) produce un error en bucle; y con otros números, con 24, 35... con varios que he probado (no sé si soy yo o mi ordenador).

Saludos.

22 Junio, 2020, 09:40 pm
Respuesta #8

ingmarov

  • Moderador Global
  • Mensajes: 4,798
  • País: hn
  • Karma: +0/-0
  • Sexo: Masculino
Hola, Ingmarov.

Hola código corregido
Pongo otra forma

Me da problemas con algunos números; si abajo invoco la función con, por ejemplo, prueba(38) produce un error en bucle; y con otros números, con 24, 35... con varios que he probado (no sé si soy yo o mi ordenador).

Saludos.
Es verdad, debe dar error, porque para 38 se tiene
resta=-13

Y.  -13%10=7 por lo que para el primer bloque if la condición propuesta es verdadera. Cuando deseamos que sea falsa.

Creo que gorkam ya tiene una solución, espero intenté corregir mi error y así beneficie más a su formación.

Saludos
No te confíes, revisa lo que escribo. Yo también me equivoco.
Odio el autocorrector de Android...

23 Junio, 2020, 12:54 am
Respuesta #9

feriva

  • Matemático
  • Mensajes: 9,067
  • País: es
  • Karma: +1/-0
  • Sexo: Masculino
  • No soy matemático, eso es una etiqueta.

Es verdad, debe dar error, porque para 38 se tiene
resta=-13

Y.  -13%10=7 por lo que para el primer bloque if la condición propuesta es verdadera. Cuando deseamos que sea falsa.

Gracias, Ingmarov; todavía tengo que pensar del todo cómo funciona la línea del if resta%100!=resta, pero lo dejo para mañana, que ahora estoy un poco dormido (y, si no, ya me lo explicas un poco).

En mi código, sí, el error que manda está relacionado con el int y no sé qué más de la base 10, según informa. Pero éste error se produce por una razón entendible: el valor “n” en el bucle interno de la función va siendo cada vez menor hasta que llega a un primer número que ya tiene una sola cifra (un carácter en la cadena); si ese número no es 0,7 ó -7, el bucle no se para, sigue y al llegar aquí ( s[:-1]) no extrae el carácter de la izquierda, porque no existe, no está definido; de ahí que produzca el fallo al intentar convertirlo en int. El que está definido, en caso de un sólo carácter en la cadena, es el de la derecha s[-1:]. En caso de que el número fuera negativo, la cadena tiene dos caracteres, con lo cual intenta convertir a entero el signo “-” y entonces da error también; concretamente indica el signo menos al final:

ValueError: invalid literal for int() with base 10: '-'

Saludos.

23 Junio, 2020, 01:40 am
Respuesta #10

ingmarov

  • Moderador Global
  • Mensajes: 4,798
  • País: hn
  • Karma: +0/-0
  • Sexo: Masculino

Es verdad, debe dar error, porque para 38 se tiene
resta=-13

Y.  -13%10=7 por lo que para el primer bloque if la condición propuesta es verdadera. Cuando deseamos que sea falsa.

Gracias, Ingmarov; todavía tengo que pensar del todo cómo funciona la línea del if resta%100!=resta, pero lo dejo para mañana, que ahora estoy un poco dormido (y, si no, ya me lo explicas un poco).

Te explico, la intensión de esa línea es terminar la sucesión de restas, y nos garantiza que está resta sea menor que cien, valores para los cuales creo es fácil saber si son múltiplos de siete o no. Mientras resta sea distinta (mayor) que resta%100 se repetirá el llamado a la función.
Por desgracia, el programa no funciona para todos los casos.

Quizás si cambiamos, en esa línea, != por <, se corrija el error.


En mi código, sí, el error que manda está relacionado con el int y no sé qué más de la base 10, según informa. Pero éste error se produce por una razón entendible: el valor “n” en el bucle interno de la función va siendo cada vez menor hasta que llega a un primer número que ya tiene una sola cifra (un carácter en la cadena); si ese número no es 0,7 ó -7, el bucle no se para, sigue y al llegar aquí ( s[:-1]) no extrae el carácter de la izquierda, porque no existe, no está definido; de ahí que produzca el fallo al intentar convertirlo en int. El que está definido, en caso de un sólo carácter en la cadena, es el de la derecha s[-1:]. En caso de que el número fuera negativo, la cadena tiene dos caracteres, con lo cual intenta convertir a entero el signo “-” y entonces da error también; concretamente indica el signo menos al final:

ValueError: invalid literal for int() with base 10: '-'

Sí, me costó un poco darme cuenta.

También había pensado utilizar str() e int() como lo has hecho... Me pregunto si la máquina trabaja más o menos usando texto. Aunque para un programa tan pequeño, esa diferencia de trabajo no es perceptible, ni creo tenga mucha importancia.

Saludos sempai

No te confíes, revisa lo que escribo. Yo también me equivoco.
Odio el autocorrector de Android...

23 Junio, 2020, 08:45 am
Respuesta #11

feriva

  • Matemático
  • Mensajes: 9,067
  • País: es
  • Karma: +1/-0
  • Sexo: Masculino
  • No soy matemático, eso es una etiqueta.

Te explico, la intensión de esa línea es terminar la sucesión de restas, y nos garantiza que está resta sea menor que cien, valores para los cuales creo es fácil saber si son múltiplos de siete o no. Mientras resta sea distinta (mayor) que resta%100 se repetirá el llamado a la función.
Por desgracia, el programa no funciona para todos los casos.

Quizás si cambiamos, en esa línea, != por <, se corrija el error.


Ah, que es que no me había dado cuenta de que pones que hay que meter números mayores que cien; no había visto la última línea porque tengo la pantalla con una letra muy grande y había que bajar la barra de scroll.

Citar
También había pensado utilizar str() e int() como lo has hecho... Me pregunto si la máquina trabaja más o menos usando texto. Aunque para un programa tan pequeño, esa diferencia de trabajo no es perceptible, ni creo tenga mucha importancia.
Saludos sempai

Sí, puede con números muy grandes para manipular cadenas; yo lo he usado con los RSA, con algunos de más de 200 cifras, para obtener cada uno de los dígitos y convertirlos a int, por ejemplo.

Muchas gracias por la aclaración, Ingmarov.

Saludos.

24 Junio, 2020, 12:06 am
Respuesta #12

gorkam

  • Junior
  • Mensajes: 27
  • País: es
  • Karma: +0/-0
  • Sexo: Masculino
Ya he conseguido solucionar el problema. Muchas gracias a todos, vuestros mensajes han sido de gran utilidad. Muchas gracias.

24 Junio, 2020, 02:05 am
Respuesta #13

ingmarov

  • Moderador Global
  • Mensajes: 4,798
  • País: hn
  • Karma: +0/-0
  • Sexo: Masculino
Ya he conseguido solucionar el problema. Muchas gracias a todos, vuestros mensajes han sido de gran utilidad. Muchas gracias.

Compártenos tu código, así aprendemos todos.

Saludos
No te confíes, revisa lo que escribo. Yo también me equivoco.
Odio el autocorrector de Android...

25 Junio, 2020, 01:48 pm
Respuesta #14

gorkam

  • Junior
  • Mensajes: 27
  • País: es
  • Karma: +0/-0
  • Sexo: Masculino
Aquí dejo el código. Mi código se ajusta a lo que me pide mi enunciado.
Código: [Seleccionar]
def div7rec(n):
    if cantidadDigitosRec(n) <= 2:
        return (n%7==0)
    else:
        return div7rec((n//10) - ((n%10*2)))

def cantidadDigitosRec(n):
    if (n<10):
        return 1
    else:
        return 1+cantidadDigitosRec(n//10)


Gracias a todos. Saludos.