Ver Mensaje Individual
  #71 (permalink)  
Antiguo 03/12/2014, 02:29
Avatar de HackmanC
HackmanC
 
Fecha de Ingreso: enero-2008
Ubicación: Guatemala
Mensajes: 1.817
Antigüedad: 16 años, 9 meses
Puntos: 260
Sonrisa Respuesta: Petando la pila. Problemas y retos usando recursividad.

Hola,

Cita:
Iniciado por leosansan Ver Mensaje
En realidad no se trata de permutaciones sino de variaciones. ...
Entre que son peras y son manzanas me tire por las conjugatorias. Ya en serio, el concepto teórico de las permutaciones, variaciones y combinaciones, sin y con repetición, y sin y con orden lo tengo claro. El problema es que no encuentro la forma de generar la secuencia exacta de una forma optimizada, es decir, sin usar ciclos o mas recursiones/comparaciones de las necesarias.

Cita:
Iniciado por Pantaláimon Ver Mensaje
... Dejo este código por si queréis hacer tests: ...
Gracias, me sirvió bastante para hacer algunas pruebas. Aunque ahora pude comprobar que la secuencia de permutaciones es correcta, y los números los comprueba bien, todavía me queda la duda que tenga algún error.


Bueno, entonces así que las permutaciones serán, con el problema que seguramente la mitad de las operaciones las va a realizar de nuevo al transponer los dígitos al otro bando, por ejemplo, 123x456 y 456x123. Al final se generan n! permutaciones, basado el algoritmo de Heap, aunque se generan mas del doble de recursiones.
Código C:
Ver original
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int count(const int value, const int i) {
  5.     return value == 0 ? i : count(value / 10, i + 1);
  6. }
  7.  
  8. void split(const int value, int dst[], const int i) {
  9.     if (value > 0 && i >= 0) {
  10.         dst[i] = value % 10;
  11.         split(value / 10, dst, i - 1);
  12.     }
  13. }
  14.  
  15. int join(int value, const int src[], const int end, const int begin, const int dec) {
  16.     if (end >= begin) {
  17.         value += src[end] * dec;
  18.         return join(value, src, end - 1, begin, dec * 10);
  19.     }
  20.     return value;
  21. }
  22.  
  23. void swap(int dst[], const int a, const int b) {
  24.     int t = dst[b]; dst[b] = dst[a]; dst[a] = t;
  25. }
  26.  
  27. int esvampiro3(const int value, int src[], const int digits) {
  28.     int value1 = join(0, src, (digits / 2) - 1, 0, 1);
  29.     int value2 = join(0, src, digits - 1, (digits / 2), 1);
  30.  
  31.     printf("%.4d x %.4d\n", value1, value2);
  32.  
  33.     if (value1 * value2 == value && !(value1 % 10 == 0 && value2 % 10 == 0)) {
  34.         return 1;
  35.     }
  36.  
  37.     return 0;
  38. }
  39.  
  40. int esvampiro2(const int value, int src[], int c[], const int digits, int i) {
  41.     if(i < digits) {
  42.         if (c[i] < i) {
  43.             swap(src, i, i % 2 ? c[i] : 0);
  44.             if (esvampiro3(value, src, digits)) {
  45.                 return 1;
  46.             }
  47.             c[i]++;
  48.             i = 1;
  49.         } else {
  50.             c[i] = 0;
  51.             i++;
  52.         }
  53.         return esvampiro2(value, src, c, digits, i);
  54.     }
  55.     return 0;
  56. }
  57.  
  58. int esvampiro(const int value, int src[], int c[], const int digits, int i) {
  59.     if (esvampiro3(value, src, digits)) {
  60.         return 1;
  61.     }
  62.     return esvampiro2(value, src, c, digits, i);
  63. }
  64.  
  65. int esVampiro(int num) {
  66.     int i;
  67.     int digits = count(num, 0);
  68.     int n[digits];
  69.     int c[digits];
  70.  
  71.     split(num, n, digits - 1);
  72.     for (i = 0; i < digits; i++) {
  73.         c[i] = 0;
  74.     }
  75.  
  76.     if (digits % 2 == 0) {
  77.         return esvampiro(num, n, c, digits, 1);
  78.     }
  79.  
  80.     return 0;
  81. }
  82.  
  83. int main(int argc, char** argv) {
  84.     printf("%d\n", esVampiro(939658));
  85.     return (EXIT_SUCCESS);
  86. }
Saludos,

ps:

Aparte de que, al parecer, me estoy quedando medio cegatón, anteriormente mencioné que la había comprobado contra la base de datos, lo volví a comprobar y el resultado era 120, no 720 como había indicado anteriormente. Por eso no se salían las cuentas. Ya mas despacio use el formato condicional de Excel para comprobar que los números no se repetían, en lugar de la base de datos.