Dos números hermanos
Resuelto
yassine
-
[Dal] Mensajes publicados 6122 Fecha de registro Estado Colaborador Última intervención -
[Dal] Mensajes publicados 6122 Fecha de registro Estado Colaborador Última intervención -
Hola,
Dos enteros N1 y N2 se dicen hermanos si cada dígito de N1 aparece al menos una vez en N2 y viceversa.
Escribe un programa en C que lea dos enteros N1 y N2, verifique y muestre si son hermanos o no.
sin tablas, cadenas o listas.
Dos enteros N1 y N2 se dicen hermanos si cada dígito de N1 aparece al menos una vez en N2 y viceversa.
Escribe un programa en C que lea dos enteros N1 y N2, verifique y muestre si son hermanos o no.
sin tablas, cadenas o listas.
2 respuestas
Hola,
No haremos tu ejercicio por ti.
Gracias por describir con precisión tu problema y por pegar el código ya realizado.
Haz clic aquí para consejos sobre cómo redactar mensajes y aquí sobre deberes escolares o PFE.
Para pegar tu código, por favor recuerda la coloración syntaxique.
--
Es muy difícil atrapar a un gato negro en una habitación oscura.
Sobre todo cuando no está allí...
No haremos tu ejercicio por ti.
Gracias por describir con precisión tu problema y por pegar el código ya realizado.
Haz clic aquí para consejos sobre cómo redactar mensajes y aquí sobre deberes escolares o PFE.
Para pegar tu código, por favor recuerda la coloración syntaxique.
--
Es muy difícil atrapar a un gato negro en una habitación oscura.
Sobre todo cuando no está allí...
Hola,
Por defecto habría respondido como baladur13, pero como el ejercicio no es tan fácil, creo que al menos podemos darte un punto de partida y luego nos muestras lo que has hecho, dónde vas y lo que te bloquea.
Como no tienes permitido usar cadenas, tendrás que trabajar únicamente con estos dos enteros y recuperar uno por uno los dígitos que los componen.
La aproximación natural (fuera de tema)
Tu ejercicio si representas tus dos enteros en una cadena de caracteres en O(N1+N2), apoyándote en una tabla auxiliar (aquí tab) que permite llevar el rastro de los dígitos encontrados en N1 y N2:
[ejemplo de código en C]
A modo de nota, en lenguajes de más alto nivel (como Python) esto se escribe aún más fácilmente/natural:
[ejemplo de código en Python]
Vuelta a tu ejercicio
Qué mala suerte, si respondes así estás fuera de tema mwahahaha :D Efectivamente, se utilizan tablas y cadenas.
En resumen, tendrás que tomar un camino desviado (y ahí empezarás a mostrar tus habilidades de programación :p). En resumen hay que recuperar cada dígito, digamos de n1, haciendo divisiones euclidianas para cada potencia de 10 (por ejemplo 123 == 1 * 100 + 2 * 10 + 3 * 1). Te aconsejo empezar por las unidades, luego las decenas, las centenas, etc., y parar cuando hayas descompuesto totalmente el número. Para ello habrá que usar una variable auxiliar que indique en qué punto estás. Por ejemplo, si ya has extraído las unidades y las decenas, has consumido 23 != 123, por lo que hay que continuar. En C la división euclidiana se hace con el operador / y el resto se obtiene con % (por ejemplo 13 / 3 == 4 y 13 % 3 == 1 porque 13 == 3 * 4 + 1).
Cada vez que extraigas un dígito (en mi ejemplo, 3, luego 2, luego 1) hay que recorrer n2 según el mismo principio y ver si se encuentra. Esto que acabo de describir permite verificar que los dígitos de n1 están incluidos en n2, pero también hay que hacer la prueba en el otro sentido para asegurar que n1 y n2 son hermanos.
Buena suerte
Por defecto habría respondido como baladur13, pero como el ejercicio no es tan fácil, creo que al menos podemos darte un punto de partida y luego nos muestras lo que has hecho, dónde vas y lo que te bloquea.
Como no tienes permitido usar cadenas, tendrás que trabajar únicamente con estos dos enteros y recuperar uno por uno los dígitos que los componen.
La aproximación natural (fuera de tema)
Tu ejercicio si representas tus dos enteros en una cadena de caracteres en O(N1+N2), apoyándote en una tabla auxiliar (aquí tab) que permite llevar el rastro de los dígitos encontrados en N1 y N2:
[ejemplo de código en C]
A modo de nota, en lenguajes de más alto nivel (como Python) esto se escribe aún más fácilmente/natural:
[ejemplo de código en Python]
Vuelta a tu ejercicio
Qué mala suerte, si respondes así estás fuera de tema mwahahaha :D Efectivamente, se utilizan tablas y cadenas.
En resumen, tendrás que tomar un camino desviado (y ahí empezarás a mostrar tus habilidades de programación :p). En resumen hay que recuperar cada dígito, digamos de n1, haciendo divisiones euclidianas para cada potencia de 10 (por ejemplo 123 == 1 * 100 + 2 * 10 + 3 * 1). Te aconsejo empezar por las unidades, luego las decenas, las centenas, etc., y parar cuando hayas descompuesto totalmente el número. Para ello habrá que usar una variable auxiliar que indique en qué punto estás. Por ejemplo, si ya has extraído las unidades y las decenas, has consumido 23 != 123, por lo que hay que continuar. En C la división euclidiana se hace con el operador / y el resto se obtiene con % (por ejemplo 13 / 3 == 4 y 13 % 3 == 1 porque 13 == 3 * 4 + 1).
Cada vez que extraigas un dígito (en mi ejemplo, 3, luego 2, luego 1) hay que recorrer n2 según el mismo principio y ver si se encuentra. Esto que acabo de describir permite verificar que los dígitos de n1 están incluidos en n2, pero también hay que hacer la prueba en el otro sentido para asegurar que n1 y n2 son hermanos.
Buena suerte
Hola mamiemando,
También habría que acomodarse con la restricción mencionada por Yassine “sin tablas, cadenas o listas”, en particular el sin “tablas” y entender qué significa esa prohibición.
Por ejemplo, ¿eso quiere decir que podríamos almacenar los datos de trabajo en un espacio de memoria asignado con malloc, pero que nos prohibiríamos acceder a él usando el operador
También habría que acomodarse con la restricción mencionada por Yassine “sin tablas, cadenas o listas”, en particular el sin “tablas” y entender qué significa esa prohibición.
Por ejemplo, ¿eso quiere decir que podríamos almacenar los datos de trabajo en un espacio de memoria asignado con malloc, pero que nos prohibiríamos acceder a él usando el operador
[]y que solo podríamos acceder mediante aritmética de punteros?
Creo que también, en tu código, se puede reemplazar:
por:
ya que el arreglo no tiene que ser reinicializado dentro de la función.
Si resulta que, en su ejercicio, no puede usar un tipo de arreglo sino solo punteros y aritmética de punteros, entonces para inicializar la memoria asignada a 0, siempre podrá usar calloc() que hará las dos cosas: asignación y inicialización a cero.
https://www.cplusplus.com/reference/cstdlib/calloc/
bool tab[10]; memset(&tab[0], 0, sizeof(bool) * 10);
por:
bool tab[10] = { 0 }; ya que el arreglo no tiene que ser reinicializado dentro de la función.
Si resulta que, en su ejercicio, no puede usar un tipo de arreglo sino solo punteros y aritmética de punteros, entonces para inicializar la memoria asignada a 0, siempre podrá usar calloc() que hará las dos cosas: asignación y inicialización a cero.
https://www.cplusplus.com/reference/cstdlib/calloc/
Hola [Dal],
Gracias por tu respuesta.
En cuanto a tus observaciones:
De todas formas, no tengo la impresión de que haga falta perder más tiempo en esta cuestión esperando a que Yassine se manifieste.
Que tengas un buen día
Gracias por tu respuesta.
En cuanto a tus observaciones:
- Toda la primera parte está claramente fuera de tema (y marcada como tal :p). Está ahí únicamente para mostrar cómo se podría haber resuelto este ejercicio con una complejidad mínima (lo cual, en sí, tiene un interés pedagógico, aunque no sea el de este ejercicio). Por eso también di un código listo para usar: está fuera de tema, y ese querido Yassine también tendrá trabajo por hacer.
- En cuanto a la inicialización de la que hablas, no conozco esa sintaxis. Yo habría dicho que hay que escribir más bien
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}. Pero como contraria a las reglas no es muy importante. - La segunda parte de mi mensaje (ver "retorno a tu ejercicio") propone tomar un camino radicalmente distinto, sin tabla / cadena / lista. En sí, es interesante mostrar en un ejercicio que no siempre hace falta recurrir a conceptos "avanzados" para responder a un problema. Sin embargo aquí, está mal hecho, ya que se hace en detrimento de la complejidad algorítmica (porque pasamos de un algoritmo en tiempo lineal a uno en tiempo cuadrático), sin mencionar el código extremamente laborioso que eso conllevará. En ese sentido, el ejercicio no está muy bien pensado y es un poco sádico.
De todas formas, no tengo la impresión de que haga falta perder más tiempo en esta cuestión esperando a que Yassine se manifieste.
Que tengas un buen día
Hola mamiemando,
Sí, he entendido tu enfoque, y siento si mi comentario sobre la inicialización del arreglo no tenía como objetivo ser útil en este ejercicio; el uso de arreglos parece efectivamente prohibido. Solo quería señalar una forma más práctica de hacer lo que escribes.
La sintaxis
of an aggregate, or fewer characters in a string literal used to initialize an array of known
size than there are elements in the array, the remainder of the aggregate shall be
initialized implicitly the same as objects that have static storage duration. En claro, si el número de elementos proporcionados para la inicialización es menor que los elementos que puede contener el agregado (aquí un arreglo) el resto de los elementos se inicializa implícitamente de la misma manera que las variables con almacenamiento estático (es decir, a 0). Es muy práctico en la vida diaria y se puede prescindir de memset(), que se puede usar en más si la función debe volver a 0 el contenido durante su ejecución. Sobre el tema y su interpretación... Con tus explicaciones adicionales, entiendo que tu interpretación de la restricción es que los valores recuperados no pueden tampoco almacenarse temporalmente en un espacio de memoria asignado con malloc (y accedidos sin usar el operador [] con la aritmética de punteros como mencionaba), y que el único almacenamiento temporal sería el del dígito actual recuperado en una variable simple (un
bool tab[10] = { 0 }; en lugar de bool tab[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; es equivalente según el estándar del C.
En el estándar C99 esto se encuentra en 6.7.8 Initialization, § 21, pero existe desde C89 :-)
21 If there are fewer initializers in a brace-enclosed list than there are elements or membersof an aggregate, or fewer characters in a string literal used to initialize an array of known
size than there are elements in the array, the remainder of the aggregate shall be
initialized implicitly the same as objects that have static storage duration. En claro, si el número de elementos proporcionados para la inicialización es menor que los elementos que puede contener el agregado (aquí un arreglo) el resto de los elementos se inicializa implícitamente de la misma manera que las variables con almacenamiento estático (es decir, a 0). Es muy práctico en la vida diaria y se puede prescindir de memset(), que se puede usar en más si la función debe volver a 0 el contenido durante su ejecución. Sobre el tema y su interpretación... Con tus explicaciones adicionales, entiendo que tu interpretación de la restricción es que los valores recuperados no pueden tampoco almacenarse temporalmente en un espacio de memoria asignado con malloc (y accedidos sin usar el operador [] con la aritmética de punteros como mencionaba), y que el único almacenamiento temporal sería el del dígito actual recuperado en una variable simple (un
intaquí). Si es así, el ejercicio es muy retorcido. Quizás Yassine debería verificar esto con su profesor, porque si puede descomponer números (como propones mediante división euclidiana) y almacenar los dígitos recuperados en memoria para tratarlos una vez que los haya obtenido, eso cambia bastante las cosas... ¡Que tengas un buen día también! P.S. : no te sientas obligada a responder a este post, pienso, como tú, que Yassine debe expresarse ahora :-)