Ver Mensaje Individual
  #40 (permalink)  
Antiguo 28/11/2014, 16:37
Avatar de leosansan
leosansan
 
Fecha de Ingreso: mayo-2012
Ubicación: GRAN CANARIA
Mensajes: 194
Antigüedad: 11 años, 10 meses
Puntos: 49
Respuesta: Petando la pila. Problemas y retos usando recursividad.

Cita:
Iniciado por Pantaláimon Ver Mensaje
¡Viernes otra vez! Así que os traigo dos problemas más.

1) ¡No te repitas!


2) Números vampiros

Dentro de la fauna de números encontramos unos que tienen colmillos. Son los números vampiros. Los números vampiros son aquellos que son resultado del producto de dos números con el mismo número de dígitos, llamados colmillos. Además, el conjunto de dígitos de los dos colmillos ha de ser el mismo conjunto que los digitos del número vampiro. Es decir, 1260 es vampiro porque es el producto de 21*60 y, 21 y 60 en conjunto está formado por los mismos digitos que 1260.
Lo mismo ocurre con 1395 que es producto de 93*15.

Los números tal como los he definido anteriormente son vampiros salvo cierta excepción: un número no es vampiro si solamente se puede contruir como el producto de dos colmillos que ambos acaben en 0. 1260, como decíamos es vampiro, pero 126000 no lo es porque, no hay colmillos que lo construyan sin ser ambos acabados en 0. 126000 = 210 * 600.

El segundo problema consistirá en contruir una función esVampiro que retorne 1 si un número es vampiro ó 0 si no lo es. Prototipo de la función:
Código C:
Ver original
  1. int esVampiro(int num);

Y ahora... ¡A petar la pila!
¡¡¡ A petarla ¡¡¡

Reconozco que la primera idea ha sido la de usar a la de usar bruta, pero me he contenido y he preferido dejarlo para otra ocasión Así que he optado por un camino más rebuscado, sencillamente a lo que a primera vista invita el reto.

Y es que si un número es de, por ejemplo seis cifras, tan sólo hay un número de variaciones de 6^3 variaciones tomadas las cifras de tres en tres, lo que da tan solo 216 casos posibles. Una vez obtenidas tan solo hay que ir multiplicándolas entre sí a ver si sale el número original,

Las dificultades inherentes ha sido obtener las variaciones y "bambolear" el array de cifras de una función a otra.

Cumple los cometidos encomendados, no valen dos grupos de cifras terminados ambos en cero y filtro aquellos que empiecen por cero por ser en realidad números de dos cifras.

Con estas ideas básicas sale el siguiente código:

Código C++:
Ver original
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. int esVampiro ( int num ) ;
  6. void variaciones_sin_repe ( char numero [ ] , int tam , int permutacioneS , char aux [ ] , char Npermutacion [ permutacioneS ][ tam + 1 ] , int n0 , int n ) ;
  7.  
  8. int main( void ) {
  9.   int num = 939658 ;
  10.   return printf ( "\n!!! Como lo quiere Pantalaimon ( 0 - 1 ) !!! ==> : [%d]\n\n" , esVampiro ( num ) ) , 0 ;
  11. }
  12.  
  13. int esVampiro (  num ) {
  14.   int i , j , n , tam , permutacioneS = 1 , num0 = num ;
  15.   for ( tam = 1 ; num0 ; tam++ , num0 /= 10 ) ;
  16.   char numero [ tam + 1 ] ;
  17.   if ( tam %2 == 0 )
  18.     return puts ( "NO ES VAMPIRO por numero impar de cifras." ) , 0 ;
  19.   itoa ( num , numero , 10 ) ;
  20.   n = tam / 2 ;
  21.   for( i = 1 , permutacioneS *= (tam-1) ; i <  n ; ++i , permutacioneS *= (tam-1));
  22.   char aux [ tam + 1 ] , Npermutacion [ permutacioneS ][ tam + 1 ] ;
  23.   variaciones_sin_repe ( numero , tam , permutacioneS , aux , Npermutacion , n, n ) ;
  24.   for( i = 0 ; i < permutacioneS ; i++ )
  25.     for( j = 0 ; j < permutacioneS ; j++ )
  26.       if ( ( Npermutacion [ i ][ tam ] == 0 && Npermutacion [ i ][ tam ] == 0 ) || ( Npermutacion [ i ][ 0 ] == 0 && Npermutacion [ i ][ 0 ] == 0 ) )
  27.         continue ;
  28.       else if ( atoi ( Npermutacion [ i ] ) * atoi ( Npermutacion [ j ] ) == num  ) {
  29.         return printf ( "\nES VAMPIRO: %d = %d * %d\n" , atoi ( Npermutacion [ i ] ) * atoi ( Npermutacion [ j ] ) , atoi ( Npermutacion [ i ] ) , atoi ( Npermutacion [ j ] ) ) , 1 ;
  30.   }
  31.   return puts ( "NO ES VAMPIRO" ) , 0 ;
  32. }
  33.  
  34. void variaciones_sin_repe( char numero [ ] , int tam , int permutacioneS , char aux [ ] , char Npermutacion [ permutacioneS ][ tam + 1 ] , int n0 , int n ){
  35.   int  i ;
  36.   static int j = 0 , permutaciones = 1  ;
  37.   if( n != 0 )
  38.     for( i = 0 ; i < tam - 1 ; ++i ) {
  39.       aux [ j ] = numero [ i ] ;
  40.       ++j ;
  41.       variaciones_sin_repe ( numero , tam , permutacioneS , aux, Npermutacion , n0 , n - 1 );
  42.       --j;
  43.     }
  44.   else {
  45.     aux [ n0 ] = '\0' ;
  46.     strcpy ( Npermutacion [ permutaciones - 1 ] , aux ) ;
  47.     permutaciones++ ;
  48.   }
  49. }

Ha sido rapidito y queda a expensas de mejoras, pero me quería adelantar por una vez.

Se puede comprobar que 126000 lo da como no vampiro, pero si desactivas el if de los números que termina en cero, dará lógicamente que sí lo es. Pero como no es vampiro no lo da como tal.

Espero que la originalidad de la idea sea merecedora de los tan apreciados usuarios.

A la espera de las críticas y/o correcciones quedo.

P.D: amchacon no me he olvidado de tí. A ver si mañana mismo te mando un mp.

¡¡¡Saluditos!!!



Puntitos Puntitos
Me gusta me gusta

Última edición por leosansan; 28/11/2014 a las 16:56