elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Recopilación Tutoriales y Manuales Hacking, Seguridad, Privacidad, Hardware, etc


  Mostrar Mensajes
Páginas: 1 [2] 3 4 5 6 7 8 9 10 11
11  Programación / Programación C/C++ / Re: AYUDA PROBLEMA C++ en: 17 Junio 2020, 21:56 pm
...
Claro que teniendo desde el principio en cuenta la otra condición de unicidad de los dígitos se puede exprimir mucho más el problema y llegar a una solución como la que muestras (que cuando tenga más tiempo le daré unas vueltecillas porque a mí no se me habría ocurrido hacerlo así  :xD)

He arreglado la respuesta que compuse en https://foro.elhacker.net/programacion_cc/c_divisibilidad_por_primos_de_un_numero_por_partes-t505293.0.html;msg2223708#msg2223708

Echale un vistazo, esta mas clara,.
12  Programación / Programación C/C++ / Re: AYUDA PROBLEMA C++ en: 15 Junio 2020, 13:19 pm
Lo primero, El_lentejas, cambia el titulo por algo m'as sugerente en vez de AYUDA PROBLEMA C++...

Esto no ayuda a los buscadores a indexar la respuesta...

Pon , "digitos y divisibilidad por primos, por ejemplo@...


...
Si te fijas, al principio del enunciado hay otro comentario:Es cierto que hay dos números que cumplen con las condiciones recuadradas y estos son:
Código:
Numero valido: 4130952867
Numero valido: 4130959493
...

EDIT


He decidido cambiar la respuesta, para editar un caso con mejor codigo y salida formateada.
He generalizado el problema a sacar todos los numeros especiales desde 0(10 veces)0 hasta 999(10 veces)9.
Sigue siendo de complejidad O(1), porque solo tratamos la base 10... para tratar en base N, con N arbitrariamente grande, tendriamos que hacernos con N-3 primos, cosa que, como se sabe, es muy costosa...Fundamento de  algoritmos de criptografia.

Código:
1406357289
d1d2d3 = 406 --> 406 / 2 = 203
d2d3d4 = 063 --> 063 / 3 = 21
d3d4d5 = 635 --> 635 / 5 = 127
d4d5d6 = 357 --> 357 / 7 = 51
d5d6d7 = 572 --> 572 / 11 = 52
d6d7d8 = 728 --> 728 / 13 = 56
d7d8d9 = 289 --> 289 / 17 = 17
----------
1430952867
d1d2d3 = 430 --> 430 / 2 = 215
d2d3d4 = 309 --> 309 / 3 = 103
d3d4d5 = 095 --> 095 / 5 = 19
d4d5d6 = 952 --> 952 / 7 = 136
d5d6d7 = 528 --> 528 / 11 = 48
d6d7d8 = 286 --> 286 / 13 = 22
d7d8d9 = 867 --> 867 / 17 = 51
----------
1460357289
d1d2d3 = 460 --> 460 / 2 = 230
d2d3d4 = 603 --> 603 / 3 = 201
d3d4d5 = 035 --> 035 / 5 = 7
d4d5d6 = 357 --> 357 / 7 = 51
d5d6d7 = 572 --> 572 / 11 = 52
d6d7d8 = 728 --> 728 / 13 = 56
d7d8d9 = 289 --> 289 / 17 = 17
----------
4106357289
d1d2d3 = 106 --> 106 / 2 = 53
d2d3d4 = 063 --> 063 / 3 = 21
d3d4d5 = 635 --> 635 / 5 = 127
d4d5d6 = 357 --> 357 / 7 = 51
d5d6d7 = 572 --> 572 / 11 = 52
d6d7d8 = 728 --> 728 / 13 = 56
d7d8d9 = 289 --> 289 / 17 = 17
----------
4130952867
d1d2d3 = 130 --> 130 / 2 = 65
d2d3d4 = 309 --> 309 / 3 = 103
d3d4d5 = 095 --> 095 / 5 = 19
d4d5d6 = 952 --> 952 / 7 = 136
d5d6d7 = 528 --> 528 / 11 = 48
d6d7d8 = 286 --> 286 / 13 = 22
d7d8d9 = 867 --> 867 / 17 = 51
----------
4160357289
d1d2d3 = 160 --> 160 / 2 = 80
d2d3d4 = 603 --> 603 / 3 = 201
d3d4d5 = 035 --> 035 / 5 = 7
d4d5d6 = 357 --> 357 / 7 = 51
d5d6d7 = 572 --> 572 / 11 = 52
d6d7d8 = 728 --> 728 / 13 = 56
d7d8d9 = 289 --> 289 / 17 = 17
----------
A falta de un criterio de divisbilidad para cualquier numero primo, no tenemos mas remedio que practicar la division y ver el resultado, lo que se traduce en una ténica de "fuerza bruta" o "backtraking".

El backtraking consiste en explorar todas las posibildades de un arbol de decision... Ensayamos en primer lugar el 0, depues cualquier numero menos el 0, que puedeser el {1,2,3,4,5,6,7,8,9}... Si cogemos el 1, entonces para la tercera cifra dispondremos de {2,3,4,5,6,7,8,9}. Pero si cogemos el 2 entonces tendermso {1,3,4,5,6,7,8,9}... Como se puede intuir, algo por lo menos exponencial. 10^10.
un 10 seguido de 10 ceros...

Se puede recortar computos marcando los digitos que ya se han usado, para asi no volverlos a usar... (podar el espacio de soluciones...) Si procedemos con una busqueda por profundidad, la recursion nos proporciona gratis la estructura de pila necesaria para hacer el recorrido...

Bueno,... miraros los esquemas de programacion "vuelta atras" y sabreis a lo que me refiero.

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <assert.h>
  4.  
  5. #define MAX 10
  6. const int N = MAX ;   // i.e O(1)
  7. static  int d[MAX];
  8. static const  int primes[MAX-3]={2,3,5,7,11,13,17}; // N primes is very hard to compute.
  9.  
  10.  
  11.  
  12. void print_solution(const int d[])
  13. {
  14.  for(int n=0;n<10;n++) printf("%d",d[n]);
  15.  printf("\n");
  16.  for(int n=1;n<8;n++)
  17.    {
  18.      char s[4];
  19.      sprintf(s,"%d%d%d",d[n],d[n+1],d[n+2]);
  20.      int num=atoi(s);
  21.      printf("d%dd%dd%d = %03d --> %03d / %d = %d\n",n,n+1,n+2,num,num,primes[n-1],num/primes[n-1]);
  22.    }
  23.  printf("----------\n");
  24.  return;
  25. }
  26.  
  27. /* O(1) Specialzer.*/
  28. void primeG(const int k, const int part,const int N)
  29. {
  30.  static int free[MAX]={1,1,1,1,1,1,1,1,1,1};
  31.  
  32.  //  printf("%d\n",k);
  33.  if (k==N)
  34.    {
  35.      print_solution(d);
  36.      return;
  37.    }
  38.  else
  39.    for(int c=0; c<10; c++)
  40.    {
  41.      if (!free[d[k]=c]) continue;
  42. #define DDD (10*part + c)
  43.      if ((k>2) && (DDD%primes[k-3])) continue;
  44.      free[c]=0;
  45.      primeG(k+1,DDD%100,MAX);
  46.      free[c]=1;
  47.    }
  48.  return;
  49. }
  50.  
  51.  
  52.  
  53.  
  54.  
  55. int main(int argc, char *args)
  56. {
  57.  // Call Specializer.
  58.  primeG(0,0,MAX);
  59.  return 0;
  60. }
  61.  


13  Programación / Programación C/C++ / Re: Problema al usar while en: 25 Mayo 2020, 21:12 pm
¿dijsktra?

¿Puede ser que estés haciendo tu tributo jugando con el nombre del homenajeado?

https://www.britannica.com/biography/Edsger-Dijkstra



El mismo. Una figura apasionante. Con el (y otros más=, la programación pasó a tener rando de disciplina científica.

¿ Te interesa saber algo de él?
Entre otras cosas, te diré que fue un poco "tecnofobo", todos sus artículos los escrbía a manuscrito, ideo un método de sintésis de programas sistemático, conocido como la "derivación de programas".... Se oponía  a la programación con GOTOS, siendo el primer apóstol de la promgramación estructurada.

Tampoco le gustaba mucho la programación orientada a objetos, que consideraba "una aberración propia de Sillicon Valley..."

Solía decir. "Si depurar es el acto de encontrar fallos en un programa, entonces programar debe consistir en el acto de ponerlos dentro"...

Una vida apasionante....

https://www.youtube.com/watch?v=nVyqbfzOGI8


14  Programación / Programación C/C++ / Re: Problema al usar while en: 25 Mayo 2020, 19:07 pm
Mas sencillo.
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4.  
  5. int main(int argc, char *args)
  6. {
  7.  int n,acum,many;
  8.  many=acum=0;
  9.  while (scanf("%d",&n)==1)
  10.    {
  11.      acum +=n;
  12.      many++;
  13.    }
  14.  if (ferror(stdin))
  15.    {
  16.      perror("scanf");
  17.      exit(1);
  18.    }
  19.  printf("\n%d %d\n",many,acum);
  20.  return 0;
  21. }
  22.  

Pruebas
Código:
 gcc stream.c -o main && ./main
10 20 30 40 50 n

5 150
15  Programación / Programación C/C++ / Re: [ALGEBRA DE MATRICES] Matriz triangular INFERIOR DESCENDIENTE en C. en: 19 Mayo 2020, 21:18 pm
Bueno, ya va siendo hora que vaya dando una respuesta a este tema... ME VA A QUEDAR UN MENSAJE LARGO, pero a lo mejor a la posteridad le sirve de ayuda.
Recordemos que las condiciones para resolverlo eran
  • sin cambiar la codificacion de los parametros, esto es, entra const int **A, no const int *A
  • una sola variable de control, n, (aparte de los parametros, A, N)
  • Un solo bucle. No he podido, me he cansado!! (Se puede, no obstante)

Código:
i := 1
MIENTRAS i <= (N*(N-1)/2) and i != 0 ENTONCES
    i = (A[f(i)][g(i)] == 0) * (i+1)
FIN MIENTRAS
RETURN i
Como se puede apreciar falta definir las funciones f() y g() que determinen la fila y columna del siguiente elemento en función de i.Si alguien se quiere animar a intentar seguir o a exponer su razonamiento... :rolleyes: :rolleyes:

Ni mucho menos es tan simple. En https://en.wikipedia.org/wiki/Pairing_function y en http://szudzik.com/ElegantPairing.pdf se describen algunos esquemas de recorrido de una matriz, proyectando dos dimensiones en uno y viceversa. No viene la tuya, pero para otras mas sencillas quedan expresiones muy complejas que trascienden el uso basico de % y /.... Un horror, vamos porque nosotros queremos no pasar de % y /.

Yo sabia que se podía, porque un resultado clásico de computabilidad dice:

Citar
 todo lo que se puede computar con programa estilo "while" y N variables se puede hacer con 1 variable.

La contrapartida será, por supuesto,

  • la legibilidad, No tiene interes pr'actico, pero si t'eorico, pues se puede hacer lo mismo con una variable que con N, (tesis de turing-Church)
  • la eficiencia.Los programas consumen más tiempo de ejecución, aunque sin dejar de ser tratable polinomialmente (Tesis de Cook)  
Esta  es la estretegia:

Código:
En una variable se pueden codificar el estado de N variables, sin más que adoptar en esa variable el producto de los primeros N numeros primos elevados al valor de cada variable respectiva.

Eso quiere decir que para codificar

Código:
x,y = 3, 1

Damos el valor a n de.
Código:
n = (2^3)*(3^1)=8*3=24

Que por el teorema de la Aritmetica, denota univocamente unico numero o valor para n. La forma para recuperar x, (y) será el  exponente de la mayor potencia de 2, (3) que todavia haga divisible a n entre ella.

Código:
x = max { k | \exists z n=2^k*z } = 3, ya que 2^4=32 no divide a 24
y = max { k | \exists z n=3^k*z } = 1 ya que 3^2=9 no divide a 24

Pero recordemos que no podemos usar m'as que una variable, luego es ilegal llamar a funciones f(n) g(n), porque estas har'ian uso de pilas y variables, y eso es trampa... Da la casualidad de que esas funciones SI SE PUEDEN COMPUTAR SOLO CON % Y /.

Este es el codigo que quier implementar de partida.

Código
  1. int lowerTriangleDesc(const int **A, const int N)
  2. {
  3.  int i, j ;
  4.  for(i = 0, j=i+1; i < N-1 && !A[i][j]; )
  5.    if (j==N-1) { i++; j = i + 1 ;}
  6.    else j++;
  7.  return i==N-1;
  8. }

Fijemonos en como se realizan las instrucciones post decremento post incremento

Código
  1. #define DEC(id)         n/=id
  2. #define INC(id)         n*=id

Esto es asi, ya que sumar 1 a la n'esima variable equivalea multiplicar el numero por el n-esimo factor primo.

M'as dificil...
Como poder evaluar i < N - 1, cuando en nuestra unica variable solo esta almacenado n=2^i*3^j ?

La estrategia sera cargar en una variable auxiliar-virtual k,n=2^i*3^j*5^k el valor de N-1-i y ver si es mayor que cero
  •   el exponente k(5) tiene que ser  igual a N, lo  que solo se puede llevar a cabo al multiplicar tantas veces por 5 como unidades tenga N
  • Como esto solo se puede saber decrementando N una unidad hasta que queda 0...al punto que multiplicamos por 5, multiplicamos por 7 (otra variable virtual l) para no perder la referencia de N en posteriores computos (que rollo!)
  • A continuacion, restauramos N, haciendo la operacion inversa, dividiendo por 7, hasta que no se pueda mas. esto es n%7==0,  ycada vez se suma 1  a N
  • Despues restamos a k (5), 1, dividiendo por 5.
  • Despues restamos i(2) a k(5), con cuidado de guardar copia en l(7) de lo que vale i  (Otra vez Un rollo!!!)
  • Restauramos en i(2), previamente guardado en el exponente de l(7)
  • Finalmente, vemos el resultado k(5) a ver si es mayor que cero. Esto ocurre si el numero n%5==0, en otro caso, k(5) es igual a 0. Convencete con n=(2^1)*(3^3)*5(^1). Ves que el resto entre 5(k) es 0, lo que no pasa con n=(2^1)*(3^3)*5(^0), cuyo resto entre 5(k) no es 0

Código
  1. // Expressions
  2. #define NON_ZERO(id)    !(n % id)
  3. #define ZERO(id)        (n%id)

Con un poco de paciencia, se puede entender el razonamiento.

  • Como es tan tedioso y proclve a errores me he creado una especie de "compilador" con las directivas de preprocesador C.
  •  El monstruo ha quedado notablemente m'as complejo que el programa anterior, pero era lo esperado... ya que, como se puede ver, solo se usa UNA variable, n)

Código
  1.  
  2. int debug(const char *s, int n, const int i)
  3. {
  4. #ifdef DEBUG  
  5.  int c;
  6.  for( c=0; !(n%i) ; n/=i) c++;
  7.  printf("debug STATE %s : -> %d \n",s,c);
  8.  return c;
  9. #endif  
  10. }
  11.  
  12.  
  13. // N Constant
  14. #define ASSIGN_N(id1,N,id2)  for( ;N;N--) n*=id1*id2
  15. #define RESTORE_N(N,id) for( ; !(n%id);n/=id) N++
  16.  
  17. // Restoring
  18. #define RESTORE(id2,id3)    for( ; !(n%id3);n/=id3)  n*=id2
  19.  
  20. // Ordinary vars.
  21. #define DEC(id)         n/=id
  22. #define INC(id)         n*=id
  23. #define SUBS(id1,id2,id3)   for( ; !(n%id2);n/=id2) { n/=id1; n*=id3 ;}
  24. #define RESET(id)       for( ; !(n%id);n/=id)
  25. #define ASSIGN(id1,id2,id3)   for( ; !(n%id2);n/=id2) n*=id1*id3
  26. #define NEG(id)           if (n%id) n*=id; else  for( ; !(n%id);n/=id)
  27.  
  28. // Expressions
  29. #define NON_ZERO(id)    !(n % id)
  30. #define ZERO(id)        (n%id)
  31.  
  32. // Indirect pointers;
  33. #define INC_POINTER(A,id1,id2) for( ; !(n%id1); n/=id1 ) { A++; n*=id2 ; }
  34. #define INC_POINTER_POINTER(A,id1,id2) for( ; !(n%id1); n/=id1 ) { (*A)++; n*=id2;  }
  35.  
  36. #define DEC_POINTER_POINTER(A,id1,id2) for( ; !(n%id1); n/=id1 ) { (*A)--; n*=id2;  }
  37. #define DEC_POINTER(A,id1,id2)    for( ; !(n%id1); n/=id1 ) { A--; n*=id2 ; }
  38.  
  39. int lowerTriangleDesc(const int **A, int N)
  40. {
  41.  int n=1;
  42.  // i,j,k : 2,3,5    l : 7
  43.  n=3;  // i,j,k,l=0,1,0,0
  44.  ASSIGN_N(5,N,7);
  45.  RESTORE_N(N,7);
  46.  DEC(5);
  47.  SUBS(5,2,7);
  48.  RESTORE(2,7);
  49.  if (NON_ZERO(5))  // if (N-1-i>0), i.e i<N-1
  50.    {
  51.      INC_POINTER(A,2,7); // A[i]
  52.      RESTORE(2,7) ;
  53.      INC_POINTER_POINTER(A,3,7); // A[i][j]
  54.      RESTORE(3,7) ;
  55.      if (**A)
  56. RESET(5);
  57.      DEC_POINTER_POINTER(A,3,7); // A[i][j]
  58.      RESTORE(3,7) ;
  59.      DEC_POINTER(A,2,7);
  60.      RESTORE(2,7) ;
  61.    } // k = k && !A[i][j]
  62.  debug("init i",n,2); debug("init j",n,3);
  63.  debug("B: loop i < N-1 && !A[i][j]",n,5);
  64.  for(; NON_ZERO(5); )
  65.    {
  66.      RESET(5);
  67.      ASSIGN_N(5,N,7);
  68.      RESTORE_N(N,7);
  69.      DEC(5);
  70.      SUBS(5,3,7); // N-1-j > 0 , j<N-1
  71.      RESTORE(3,7);
  72.      if (ZERO(5))
  73. {
  74.  INC(2); //i++
  75.  RESET(3);
  76.  ASSIGN(3,2,5);
  77.  RESTORE(2,5);
  78.  INC(3); //j++
  79. }
  80.      else INC(3);
  81.      debug("step i",n,2); debug("step j",n,3);
  82.      ASSIGN_N(5,N,7);
  83.      RESTORE_N(N,7);
  84.      DEC(5);
  85.      SUBS(5,2,7);
  86.      RESTORE(2,7);
  87.      if (NON_ZERO(5))  // if (N-1-i>0), i.e i<N-1
  88. {
  89.  INC_POINTER(A,2,7); // A[i]
  90.  RESTORE(2,7) ;
  91.  INC_POINTER_POINTER(A,3,7); // A[i][j]
  92.  RESTORE(3,7) ;
  93.  if (**A)
  94.    RESET(5);
  95.  DEC_POINTER_POINTER(A,3,7); // A[i][j]
  96.  RESTORE(3,7) ;
  97.  DEC_POINTER(A,2,7);
  98.  RESTORE(2,7) ;
  99. } // k = k && !A[i][j]
  100.      debug("B: loop i < N-1 && !A[i][j]",n,5);
  101.    }
  102.  ASSIGN_N(5,N,7);
  103.  RESTORE_N(N,7);
  104.  DEC(5);
  105.  SUBS(5,2,7);
  106.  RESTORE(2,7);
  107.  NEG(5);
  108.  debug("epilogue: i==N-1",n,5);
  109.  return NON_ZERO(5);
  110. }
  111.  

Los mensajes debug, por supuesto, son opcionales y no forman parte del codigo. Es para poder seguir mejor la codificacion de las variables en una sola.

Ah!, las pruebas de que va bien!

El codigo de IO esta en
https://foro.elhacker.net/programacion_cc/algebra_de_matrices_matriz_triangular_superior_desdendiente_en_c-t504451.0.html;msg2220794#msg2220794

Código:
$ ./main
1
1
debug STATE init i : -> 0
debug STATE init j : -> 1
debug STATE B: loop i < N-1 && !A[i][j] : -> 0
debug STATE epilogue: i==N-1 : -> 1
lowerTriangleDesc: 1
2
1 0
1 1
debug STATE init i : -> 0
debug STATE init j : -> 1
debug STATE B: loop i < N-1 && !A[i][j] : -> 1
debug STATE step i : -> 1
debug STATE step j : -> 2
debug STATE B: loop i < N-1 && !A[i][j] : -> 0
debug STATE epilogue: i==N-1 : -> 1
lowerTriangleDesc: 1
2
1 1
1 1
debug STATE init i : -> 0
debug STATE init j : -> 1
debug STATE B: loop i < N-1 && !A[i][j] : -> 0
debug STATE epilogue: i==N-1 : -> 0
lowerTriangleDesc: 0
3
1 0 0
1 1 0
1 1 1
debug STATE init i : -> 0
debug STATE init j : -> 1
debug STATE B: loop i < N-1 && !A[i][j] : -> 2
debug STATE step i : -> 0
debug STATE step j : -> 2
debug STATE B: loop i < N-1 && !A[i][j] : -> 3
debug STATE step i : -> 1
debug STATE step j : -> 2
debug STATE B: loop i < N-1 && !A[i][j] : -> 1
debug STATE step i : -> 2
debug STATE step j : -> 3
debug STATE B: loop i < N-1 && !A[i][j] : -> 0
debug STATE epilogue: i==N-1 : -> 1
lowerTriangleDesc: 1
3
1 0 0
1 1 1
1 1 1

debug STATE init i : -> 0
debug STATE init j : -> 1
debug STATE B: loop i < N-1 && !A[i][j] : -> 2
debug STATE step i : -> 0
debug STATE step j : -> 2
debug STATE B: loop i < N-1 && !A[i][j] : -> 3
debug STATE step i : -> 1
debug STATE step j : -> 2
debug STATE B: loop i < N-1 && !A[i][j] : -> 0
debug STATE epilogue: i==N-1 : -> 0
lowerTriangleDesc: 0

P.D
Si aun no te convence que es una variable...  aplica la siguiente linea en el compilador
para observar que solo existe la varaible "n" en la rutina...
Código:
gcc -E source.c -o source.hcp

el resultado es.

Código
  1. int lowerTriangleDesc(const int **A, int N)
  2. {
  3.  int n=1;
  4.  
  5.  n=3;
  6.  for( ;N;N--) n*=5*7;
  7.  for( ; !(n%7);n/=7) N++;
  8.  n/=5;
  9.  for( ; !(n%2);n/=2) { n/=5; n*=7 ;};
  10.  for( ; !(n%7);n/=7) n*=2;
  11.  if (!(n % 5))
  12.    {
  13.      for( ; !(n%2); n/=2 ) { A++; n*=7 ; };
  14.      for( ; !(n%7);n/=7) n*=2 ;
  15.      for( ; !(n%3); n/=3 ) { (*A)++; n*=7; };
  16.      for( ; !(n%7);n/=7) n*=3 ;
  17.      if (**A)
  18. for( ; !(n%5);n/=5);
  19.      for( ; !(n%3); n/=3 ) { (*A)--; n*=7; };
  20.      for( ; !(n%7);n/=7) n*=3 ;
  21.      for( ; !(n%2); n/=2 ) { A--; n*=7 ; };
  22.      for( ; !(n%7);n/=7) n*=2 ;
  23.    }
  24.  debug("init i",n,2); debug("init j",n,3);
  25.  debug("B: loop i < N-1 && !A[i][j]",n,5);
  26.  for(; !(n % 5); )
  27.    {
  28.      for( ; !(n%5);n/=5);
  29.      for( ;N;N--) n*=5*7;
  30.      for( ; !(n%7);n/=7) N++;
  31.      n/=5;
  32.      for( ; !(n%3);n/=3) { n/=5; n*=7 ;};
  33.      for( ; !(n%7);n/=7) n*=3;
  34.      if ((n%5))
  35. {
  36.  n*=2;
  37.  for( ; !(n%3);n/=3);
  38.  for( ; !(n%2);n/=2) n*=3*5;
  39.  for( ; !(n%5);n/=5) n*=2;
  40.  n*=3;
  41. }
  42.      else n*=3;
  43.      debug("step i",n,2); debug("step j",n,3);
  44.      for( ;N;N--) n*=5*7;
  45.      for( ; !(n%7);n/=7) N++;
  46.      n/=5;
  47.      for( ; !(n%2);n/=2) { n/=5; n*=7 ;};
  48.      for( ; !(n%7);n/=7) n*=2;
  49.      if (!(n % 5))
  50. {
  51.  for( ; !(n%2); n/=2 ) { A++; n*=7 ; };
  52.  for( ; !(n%7);n/=7) n*=2 ;
  53.  for( ; !(n%3); n/=3 ) { (*A)++; n*=7; };
  54.  for( ; !(n%7);n/=7) n*=3 ;
  55.  if (**A)
  56.    for( ; !(n%5);n/=5);
  57.  for( ; !(n%3); n/=3 ) { (*A)--; n*=7; };
  58.  for( ; !(n%7);n/=7) n*=3 ;
  59.  for( ; !(n%2); n/=2 ) { A--; n*=7 ; };
  60.  for( ; !(n%7);n/=7) n*=2 ;
  61. }
  62.      debug("B: loop i < N-1 && !A[i][j]",n,5);
  63.    }
  64.  for( ;N;N--) n*=5*7;
  65.  for( ; !(n%7);n/=7) N++;
  66.  n/=5;
  67.  for( ; !(n%2);n/=2) { n/=5; n*=7 ;};
  68.  for( ; !(n%7);n/=7) n*=2;
  69.  if (n%5) n*=5; else for( ; !(n%5);n/=5);
  70.  debug("epilogue: i==N-1",n,5);
  71.  return !(n % 5);
  72. }
  73.  

SE PUEDE HACER CON UN SOLO BUCLE

DE NUEVO, EL COSTE A PAGAR SERA UN CONTROL MAS COMPLEJO,

AQUI LO DEJO.
16  Programación / Programación C/C++ / Re: [ALGEBRA DE MATRICES] Matriz triangular INFERIOR DESCENDIENTE en C. en: 13 Mayo 2020, 11:45 am
...y ahora el pseudocódigo (que cualquiera puede traducir a cualquier lenguaje, ya que el problema no es un problema restrictivo a ningún lenguaje específico, es decir no es un problema de ningún lenguaje si no de algoritmia)...

Tengo que dejar claro que su idea es la que más me ha gustado.
Comentarios...
  • Mete  una variable mas, size, que no es m'as que ancho*ancho, luego se puede enmendar
  • No es programacion estructurada (return 0) pero eso es facilmente enmendable.Ojo!, no digo que no sea válida en C, digo que no es C-estructurada
  • La construccion "repeat until", no es la adecuada. De hecho para N=1, el algoritmo falla. Pero es facilmente enmendable

Con las ligeras enmiendas... El pseudocodigo de NEBIRE pasado a C, resulta
Código
  1. int upperTriangleDesc(const int *A, const int N)
  2. {
  3.  int i=N*N-N;
  4.  while (i && !A[i])
  5.    {
  6.      i += N + 1;
  7.      if (i > N*N)
  8. i = N*N - (N*(1 + (i%N)));
  9.    }
  10.  return !i;
  11. }
  12.  
Y algunos resultados (correctos, por supuesto)
Código:
1
1
upperTriangleDesc: 1
2
1 1
0 1
upperTriangleDesc: 1
3
1 2 3
0 1 2
0 0 1
upperTriangleDesc: 1
3
1 2 3
0 1 2
1 0 1
upperTriangleDesc: 0
Es encomiable el esfuerzo por hallar la ley que aplica al indice "i". Realmente es una función compleja...

Sin embargo... Hay un detalle no menor que puede echarse al traste....

SE HA CAMBIADO EL TIPO DE LA MATRIZ DE BIDIMENSIONAL A UNIDIMENSIONAL

Código
  1. const int **A;
  2. // Set by
  3. if  ((A=(int**)malloc(N*sizeof(int *)))==NULL)
  4.  {
  5.    perror("malloc");
  6.    exit(1);
  7.  }
  8. for(int n=0;n<N;n++)
  9.  {
  10.    if  ((A[n]=(int*)malloc(N*sizeof(int)))==NULL)
  11.      {
  12. perror("malloc");
  13. exit(1);
  14.      }
  15.  }
  16.  
por
Código
  1. const int *A;
  2.  
  3. if  ((A=(int*)malloc(N*N*sizeof(int)))==NULL)
  4.  {
  5.    perror("malloc");
  6.    exit(1);
  7.  }
  8.  

EDIT
Esto supone que se han cambiado las condiciones del problema original por otro que era equivalente, que lo emula ,pero con condiciones distintas (los datos de entrada se presuponen codificados de otro modo). As'i, con N=6, el resultado no es correcto cuando se le pasa un valor const int **A, malloc(N), ya que A[30] , esta fuera de memoria. (si lo esta const int *A, malloc(N*N)...)

Todavia no tengo la mia... tengo algnuas cosas todavía sin madurar.
17  Programación / Programación C/C++ / Re: [ALGEBRA DE MATRICES] Matriz triangular INFERIOR DESCENDIENTE en C. en: 6 Mayo 2020, 00:03 am
Hmm... Veo demasiada similitud con el otro tema.

Tienes razon. YreX-DwX... No me ha quedado bien.... :-( :-( Era muy similar al otro.... Y la solucion que pones es implecable...

Código
  1. int lowerTriangleDesc(const int **A, const int N){
  2.    int i, j = N;
  3.    for(i = 0; i < N-1 && j == N; ++i)
  4.        for(j = i+1; j < N && !A[i][j]; ++j);
  5.    return j == N;
  6. }

yo habia propuesto

Código
  1. int lowerTriangleDescBis(const int **A,
  2. const int N)
  3. {
  4.  int i,j;
  5.  for (i=N-1,j=N; i && (j==N); i-=(j==N))
  6.    for(j=i; j<N && !A[i-1][j];j++);
  7.  return !i;
  8. }

PD: Sigo pensando que hay alguna solución oculta sorprendente. No dormiré tranquilo hasta ver la solución. :xD

  VAMOS A HACERLO DIFICIL, PERO DIFICILISMO !

Todo el mundo ve que hay dos bucles y dos variables

ESTE ES EL RETO:


PROGRAMAR LA SOLUCION USANDO SOLO UN BUCLE Y UNA SOLA VARIABLE DE CONTROL, A PARTE DE LAS QUE SE DAN POR PARAMETRO

(Por supuesto, el programa sera mas dificil de legible, pero sera igualmente correcto....)


No me pidais la solucion en un dia que no se si tendre tiempo... Se que se puede, y tengo que hacerla...
y tu, YreX-DwX, m'as vale que duermas un poco...que te puedes volver tarumba... :rolleyes: :rolleyes:


18  Programación / Programación C/C++ / [ALGEBRA DE MATRICES] Matriz triangular INFERIOR DESCENDIENTE en C. en: 4 Mayo 2020, 22:24 pm
dijsktra deberías de poner mas retos como este  :P

Va por el fary !

 Nuestros hermanos de América puede que no sepan quien es el Fary... Es... el "más cantante de España",,,   https://www.youtube.com/watch?v=XLZO3DGRrfY
(Parodia de lo mal que hablan los "gallegos"!!)

A vueltas con las matrices... Se trata ahora de comprobar si una matriz es triangular inferior descendiente...


Yo lo he hecho de arriba a bajo. Es similar, pero es como si a un zurdo le mandaran escribir con la derecha, o a un diestro con la izquierda...

Vale el mismo código base de

https://foro.elhacker.net/programacion_cc/algebra_de_matrices_matriz_triangular_superior_desdendiente_en_c-t504451.0.html;msg2220794#msg2220794

Código
  1. int lowerTriangleDesc(const int **A,
  2.      const int N)
  3. {
  4.  // Start code here.
  5.  return 1;
  6. }

De nuevo, el que más simple/bonito lo hace, (no el que termine antes, como en los concursos) gana!

Ojo , YreX-DwX, no se te olivde que tienen que valer para matrices N>=1 columnas....

Ejemplos de entrada de casos son...
EN DOS DIAS PONGO LA SOLUCION
Código:
3
1 0 0
0 1 0
0 0 1
lowerTriangleDesc: 1
3
1 2 3
0 4 5
0 0 6
lowerTriangleDesc: 0
3
1 2 3
2 4 5
0 0 6
lowerTriangleDesc: 0
5
1 0 0 0 0
1 2 0 0 0
1 2 3 0 0
1 2 3 4 0
1 2 3 4 5
lowerTriangleDesc: 1
5
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
lowerTriangleDesc: 1
1
1
lowerTriangleDesc: 1
1
0
lowerTriangleDesc: 1

19  Programación / Programación C/C++ / Re: [ALGEBRA DE MATRICES] Matriz triangular superior desdendiente en C. en: 2 Mayo 2020, 22:44 pm
Estamos ansiosos de ver tu código dijsktra  :rolleyes: ¿Para qué retrasarlo más?  :laugh:

Allá va... Se aceptan criticas...

Con el buen trabajo que hicisteis al principio, había poco margen... De hecho, la tuya es muy dificil de superar, pero no es estructurada... tiene "saltos"... Y el heroe del cual tomo el pseudonimo, dijsktra, maldecia la programación "con saltos"... Esto podia hacer el software muy complejo de mantener, por lo menos en algoritmia, no en programacion de sistemas.

Lo que no todo el mundo sabe es que, sin cuidado, - sin la técnica de derivación- y sin un buen lenguaje -C no es el mejor para la algoritmia, porque le faltan asignaciones multiples y comandos guardados...- la programacion estructurada puede ser tan dificil de mantener ( o mas) que la no estructurada. Aunque en general, siguiendo las directrices de dijsktra (el original, no yo)  es m'as fácil.


La formalizacion que permite demostrarlo rigorusamente esta descrita en comnetarios, pero eso es para cursos avanzados.. Lo dejo para la posteridad que lo quiera conusltar en Internet...

Propongo dos versiones.. Va la primera...

Código
  1. int upperTriangleDesc(const int **A,
  2.      const int N)
  3. {
  4.  int i,j;
  5.  for (i=1,j=0;i<N && j==i-1; i++)
  6.    for(j=0; (j<i) && !A[i][j];j++);
  7.  return j==i-1 ;
  8. }
  9.  
  10. // Outer loop
  11. // I1: Q[N/i] and 1<=i<=M, 0<=j<i and ((j<i-1) -> A[i-1][j]!=0)
  12. // Q1: i = min n : 1 <= n <=N and (n<N->(j<n-1 && ->A[n-1][j]!=0))): n nad
  13. //     j = min m : 0 <= m < i and (m<i-1 -> A[i-1][m]!=0))): m
  14. // Quote1(N-i)>=0
  15. // Inner loop
  16. // I2: Q2[N/j] and 0 <= j <= i and i < N
  17. // Q2: i<N and j = min m : 0 <= m <=i and (m<i -> A[i][m]!=0): m
  18. // Quote2(N-j)>=0
  19.  
  20.  
Grosso modo, la idea es la siguiente...
Al principio, al final y entre vueltas del bucle externo, si j<i-1 entonces sabemos que hemos encontradoun elemento A[i-1][j] distingo de 0, en la zona prohibida... Es un invariante... Y acabamos si hemos llegado a i==N en el caso peor... luego en las anteriores a N, no lo encontrarmos... Aun en i==N podria ser, por loq eu evaluamos j==i-1 en el return... Es como una piedra en el calzado esa utlima linea...es lo que le perdio a
YreX-DwX .  Aun asi, se puede apreciar como los indices i,j se modifican naturalmente, con i++,j++

La segunda, mi favorita...
Código
  1. int upperTriangleDesc(const int **A,
  2.      const int N)
  3. {
  4.  int i,j;
  5.  for (i=1,j=0;i<N && !j; i+=!j)
  6.    for(j=i; j && !A[i][j-1];j--);
  7.  return i==N;
  8. }
  9.  
  10. // Outer loop
  11. // I1: Q[N/i] and 1<=i<=N, 0<=j<=i and ((j>0) -> (i<N and A[i][j-1]!=0))
  12. // Q1: i = min n : 1 <= n <=N and (n<N->(j>0 && ->A[n][j-1]!=0))): n nad
  13. //     j = max m : 0 <= m <= i and (m>0 -> i<N && A[i][m-1]!=0))): m
  14. // Quote1(N-i-j)>=0
  15. // Inner loop
  16. // I2: Q2[N/j] and i<N and 0 <= j <= i
  17. // Q2: i<N and j = max m : 0 <= m <=i and (m>0 -> A[i][m-1]!=0): m
  18. // Quote2(N-j)>=0
  19.  
En esta version, tenemos la fortuna de parar en la primera linea en la que hayamos encontrado el elemento no valido, que resultara estar en A(i)[j-1] si j>0 (Es un invariante)...
O en N, si no lo encontramos...Pero el cambio no es gratuiro.. el avance de i es condicional, i.e. i+=!j

Saludos...Cuidaos del COVID...!



20  Programación / Programación C/C++ / Re: [ALGEBRA DE MATRICES] Matriz triangular superior desdendiente en C. en: 2 Mayo 2020, 21:56 pm
Cuando tienes proyectos sin terminar pero @dijsktra te pica a darle más vueltas a un algoritmo aparentemente sencillo.  :laugh: :laugh:
Grandeeee....

...
Código
  1. int upperTriangleDesc(const int **A, const int N){
  2.    size_t i = 1; j = 0; // Declaramos e inicializamos j para poder usarlo en la condicion del bucle externo
  3.    while(i < N && !A[i][j]){
  4.        // El bucle interno no tiene ninguna complicacion
  5.        while(j < i && !A[i][j]){
  6.            ++j;
  7.        }
  8.        // Ahora al salir tenemos dos situaciones:
  9.        // - (j = i) y en tal caso la matriz todavia es triangular superior -> Incrementamos i y restablecemos j a 0 para recorrer otra fila
  10.        // - (A[i][j] != 0) y en tal caso la matriz ya no es triangular superior -> No podemos modificar i ni j para que el bucle de fuera tambien termine
  11.        if(j == i){
  12.            ++i;
  13.            j = 0;
  14.        }
  15.    }
  16.    // Los bucles acaban cuando:
  17.    // Un elemento no es nulo (A[i][j] != 0) -> !triangular
  18.    // Llegamos al final (i == N) -> SI A[N-1][N-2] == 0 ENTONCES triangular SINO !triangular
  19.    return (i == N && !A[N-1][N-2]);
  20. }
Chavalote! Este no te lo puedo bendecir... Tiene un sutil fallo. Te digo cual?
Prueba a evaluar la matriz de 1 fila y 1 columna...
El resultado es indeterminado... porque entonces accedes a una posicion tal como A[0][-1]  . Si acierta, dependera del compilador, o de la conjunci'on de los astros...
Que pasa? que las matrices de 1 fila y 1 columna no son matrices???  Prueba [[1]]!  :laugh: :laugh: :laugh:


Podemos ver que esto se complica mucho y solo para quitar una variable local. Así que tenía que haber otra solución.
Ese es el punto... Que tenemos que hacerlo sencillo. Pero claro, con lo bien que lo hiciste al principio, cacda vez queda menos margen...

...
Código
  1. int upperTriangleDesc(const int **A, const int N){
  2.    size_t i = 1, j = 0;
  3.    while(i < N && !j){
  4.        while(j < i && !A[i][j]){
  5.            ++j;
  6.        }
  7.        // Al salir: SI j < i ENTONCES A[i][j] != 0 SINO SI A[i][j-1] == 0 ENTONCES triangular (de momento) SINO !triangular
  8.        j = (j < i) || A[i][j-1];
  9.        ++i;
  10.    }
  11.    // Triangular <-> j = 0
  12.    return !j;
  13. }

A ver qué tal esta vez.  :silbar: :silbar:

 ;-) ;-) ;-)  Bravo... Correcta... pero aun redundante... :rolleyes: ya que en
Código
  1. j=(j<i)||A[i][j-1]
  2.  
es equivalente a
Código
  1. j=(j<i)
  2.  
En ese punto. N>i>0 siempre. ya que 1<=i<=N (desde el principio 1==1, y siempre aumenta... y por meterse en el primer bucle i<N.
(Si has llegado a j==i, es porque todos los anteriores son 0, en particular, A[j-1]. luego es "por el momento triangular", lo que tu registras poniendo j=0.Si no llegas, a j==i es porque A[j] es distinto de 0, y tu la marcas a 1, "diciendo que no es triangular". Por evaluacion en cortocircuito, no se evalua A[j-1]...

Y como tu dices, se ha hecho mas "compleja de leer" ya que...j
  • Unas veces marca el indice de la columna 0<=j<N A[j] (while)
  • Otras veces marca un predicado booleano {0,1} para saber si es triangular "pr el momento" j=(j<i)||A[j-1]

Pongo ya mi solucion en el mensaje abajo, para no repetir, en respuesta a fary

Páginas: 1 [2] 3 4 5 6 7 8 9 10 11
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines