Advertisement
EmanueleBonin

Emanuele Bonin - Ricerca Mattoni diofantei

Aug 7th, 2019
577
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.73 KB | None | 0 0
  1. /*
  2.     linea di comando per la compilazione con cc65
  3.     cl65 -t c64 -O --codesize 800 -Cl diofanto.c diofantoExtern.s -o DioFanto.prg
  4.  
  5.     il programma per c64 è scritto in maniera da sfruttare la pagina 0 tramite l'inclusione
  6.     del file diofantoExtern.s che riporto:
  7.     Diofanto.s
  8.     ## Inizio File ##
  9. .export _m1;
  10. _m1 = $40
  11.  
  12. .export _m2;
  13. _m2 = $42
  14.  
  15. .export _m3;
  16. _m3 = $44
  17.  
  18. .export _T1;
  19. _T1 = $46
  20.  
  21. .export _T2;
  22. _T2 = $48
  23.  
  24. .export _T3;
  25. _T3 = $50
  26.  
  27. .export _SPIGA;
  28. _SPIGA = $52
  29.  
  30. .export _SPIGB;
  31. _SPIGB = $56
  32.  
  33. .export _SPIGC;
  34. _SPIGC = $60
  35.  
  36. .export _MoltiplicatoreMax;
  37. _MoltiplicatoreMax = $64
  38.     ## Fine File ##
  39.  
  40.  
  41. */
  42.  
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <time.h>
  46.  
  47. #define MMAX        15
  48. #define MAXLEVEL    5
  49.  
  50. #define POKE(addr,val)     (*(unsigned char*) (addr) = (val))
  51.  
  52.  
  53. unsigned int TPP[1100][3];
  54. unsigned int TPP_Index = 0;
  55. unsigned int HH;
  56. unsigned int MM;
  57. unsigned int Sec;
  58. unsigned int Milli;
  59. unsigned int totale = 0;
  60. unsigned long int start_t, end_t, total_t;
  61.  
  62. #ifdef __C64__
  63. extern unsigned int m1;
  64. #pragma zpsym("m1")
  65. extern unsigned int m2;
  66. #pragma zpsym("m2")
  67. extern unsigned int m3;
  68. #pragma zpsym("m3")
  69. extern unsigned int T1;
  70. #pragma zpsym("T1")
  71. extern unsigned int T2;
  72. #pragma zpsym("T2")
  73. extern unsigned int T3;
  74. #pragma zpsym("T3")
  75. extern unsigned int MoltiplicatoreMax;
  76. #pragma zpsym("MoltiplicatoreMax")
  77. extern unsigned long int SPIGA;
  78. #pragma zpsym("SPIGA")
  79. extern unsigned long int SPIGB;
  80. #pragma zpsym("SPIGB")
  81. extern unsigned long int SPIGC;
  82. #pragma zpsym("SPIGC")
  83. #else
  84.  
  85. unsigned int m3;
  86. unsigned int m2;
  87. unsigned int m1;
  88.  
  89. unsigned long int SPIGA, SPIGB, SPIGC;
  90. unsigned int T1, T2, T3;
  91.  
  92. unsigned int MoltiplicatoreMax;
  93.  
  94. #endif // C64
  95.  
  96.  
  97. // Matrice generatrice delle triplette
  98. typedef struct M {
  99.     unsigned int Mx[3][3]; // = {{1,2,2},{2,1,2},{2,2,3}};
  100. } tM;
  101. tM MT;
  102.  
  103. void AssignNext(int TPP_Index_Padre, int nMode, int Livello);
  104. void AddNextLevel(int Padre, int Livello) {
  105.  
  106.     AssignNext(Padre, 1, Livello);
  107.     AssignNext(Padre, 2, Livello);
  108.     AssignNext(Padre, 3, Livello);
  109.  
  110. }
  111.  
  112. // Funzione che calcola i tre figli generati dal nodo From
  113. // e assegna i valori al nodo To
  114. // Viene utilizzato il teorema di Barnings
  115. // node indica quali modifiche vanno apportate alla matrice
  116. // iniziale per generare uno dei tre "figli" della tripletta "genitore"
  117. void AssignNext(int TPP_Index_Padre, int nMode, int Livello) {
  118.     unsigned int a, b, c, sw;
  119.     unsigned int M1=1, M2=1;
  120.     if (nMode != 2) {
  121.         if (nMode == 1)
  122.             M2 = -1;
  123.         else
  124.             M1 = -1;
  125.     }
  126.  
  127.     a = MT.Mx[0][0] * TPP[TPP_Index_Padre][0] * M1 +
  128.         MT.Mx[0][1] * TPP[TPP_Index_Padre][1] * M2 +
  129.         MT.Mx[0][2] * TPP[TPP_Index_Padre][2];
  130.  
  131.     b = MT.Mx[1][0] * TPP[TPP_Index_Padre][0] * M1 +
  132.         MT.Mx[1][1] * TPP[TPP_Index_Padre][1] * M2 +
  133.         MT.Mx[1][2] * TPP[TPP_Index_Padre][2];
  134.  
  135.     c = MT.Mx[2][0] * TPP[TPP_Index_Padre][0] * M1 +
  136.         MT.Mx[2][1] * TPP[TPP_Index_Padre][1] * M2 +
  137.         MT.Mx[2][2] * TPP[TPP_Index_Padre][2];
  138.  
  139.     // La generazione mantiene sempre la stessa parità
  140.     // a; /* dispari */
  141.     // b; /* pari */
  142.     // c; /* dispari*/
  143.  
  144.     /* Ordino la terna in modo da avere sempre a < b
  145.        a discapito dell'ordinamento per parità (a dispari e b pari)
  146.        in modo da poter eseguire le ricerche successive
  147.     */
  148.     if (b < a) {
  149.         sw = b;
  150.         b=a;
  151.         a=sw;
  152.     }
  153.  
  154.     ++TPP_Index;
  155.  
  156.     TPP[TPP_Index][0] = a;
  157.     TPP[TPP_Index][1] = b;
  158.     TPP[TPP_Index][2] = c;
  159.  
  160.     if (Livello < MAXLEVEL) {
  161.         AddNextLevel(TPP_Index, Livello+1);
  162.     }
  163. }
  164.  
  165.  
  166.  
  167. // Inizializzazione delle variabili comuni
  168. void Initialize() {
  169.     TPP_Index = 0;
  170.     TPP[TPP_Index][0] = 3;
  171.     TPP[TPP_Index][1] = 4;
  172.     TPP[TPP_Index][2] = 5;
  173.  
  174.     AddNextLevel(TPP_Index, 1);
  175. }
  176.  
  177. int MCD(unsigned int n1, unsigned int n2) {
  178.     /* algoritmo di Euclide */
  179.     unsigned int a, b, mcd = 1;
  180.     if (n1 > n2) {
  181.         a = n1;
  182.         b = n2;
  183.     } else {
  184.         a = n2;
  185.         b = n1;
  186.     }
  187.     if ((a % b) == 0)
  188.         mcd = b;
  189.     else
  190.         mcd = MCD(b, a % b);
  191.     return mcd;
  192. }
  193.  
  194.  
  195.  
  196.  
  197. void WalkOnList() {
  198.  
  199.  
  200.  
  201.     unsigned short ContaTerne= 0;
  202.     MoltiplicatoreMax=MMAX;
  203.  
  204.  
  205.  
  206.     // MoltiplicatoreMax contiene il numero massimo che potrà assumere il valore di
  207.     // "scalatura" della terna pitagorica B C D2 (quella più piccola)
  208.     // che sarà la prima ad essere scelta.
  209.     // Questo comporterà un ciclo ulteriore fino a tale valore
  210.  
  211.     // +T3---+---------------------------+
  212.     // |   / |              F          T1|
  213.     // | D/  A                           |
  214.     // | /   |                           |
  215.     // +--B--+----C----------------------+
  216.     //       |                         T2|
  217.     //       B             E             |
  218.     //       +---------------------------+
  219.     // Ip:F>E>D
  220.     // F>E
  221.     // A^2+C^2 > B^2+C^2 => A^2>B^2 => A>B
  222.     // E>D
  223.     // B^2+C^2 > B^2+A^2 => C^2>A^2 => C>A
  224.     // F>D
  225.     // A^2+C^2 > B^2+A^2 => C^2>B^2 => C>B
  226.     //
  227.     // Quindi: C>A>B
  228.     //
  229.     // Per ogni faccia, con le lettere minuscole indico i due cateti (a,b) e l'ipotenusa c
  230.     // tenendo presente che a<b<c. l'indice dopo ma lettera minuscola
  231.     // indica la tera di appartenenza.
  232.     // Inoltre identifico ogni faccia con una terna e generalizzo pensando alla terna come
  233.     // una terna che possa non essere primitiva, quindi ogniuno degli elementi della terna
  234.     // è moltiplicato per una stessa costante.
  235.     // chiamiamo m1, m2, m3 le tre costanti che moltiplicano le terne primitive di
  236.     // ogn'una delle tre facce, in questo modo possiamo scrivere:
  237.  
  238.     // T1 = A,C,F = a1*m1,b1*m1,c1*m1
  239.     // T2 = B,C,E = a2*m2,b2*m2,c2*m2
  240.     // T3 = B,A,D = a3*m3,b3*m3,c3*m3
  241.     //
  242.     // Gli spigoli sono ordinati secondo la loro grandezza
  243.     // (1) A = a1*m1 = b3*m3
  244.     // (2) B = a2*m2 = a3*m3
  245.     // (3) C = b1*m1 = b2*m2
  246.     //
  247.     // lavorando sulle prime due delle ultime tre equivalenze sopra esposte:
  248.     // dalla (1) m1 = ((b3*m3)/a1) = A/a1 => che a1|A
  249.     // dalla (2) m2 = ((a3*m3)/a2) = B/a2 => che a2|B
  250.     // dalla (3) m2 = ((b1*m1)/b2) = C/b2 => che b2|C
  251.     //
  252.  
  253.     // girando nella maniera opportuna le equivalenze (1) (2) (3)otteniamo:
  254.     // m3 = a1*m1/b3, m2 = a3*m3/a2, m1=b2*m2/b1
  255.     // m3 = a1*(b2*m2/b1)/b3 => m3 = a1*(b2*(a3*m3/a2)/b1)/b3
  256.     // => m3 = (a1*b2*a3*m3)/(a2*b1*b3) => m3/m3 = (a1*b2*a3)/(b1*a2*b3)
  257.     // quindi abbiamo che un mattone diofanteo rispetta l'equivalenza:
  258.     // 1 = (a1*b2*a3)/(b1*a2*b3)
  259.     // il che ci permette di escludere le triplette primitive che non rispettino tale regola
  260.     // prima ancora di andare a cercare i moltiplicatori opportuni.
  261.  
  262.     // Se analizziamo la parità dei tre spigoli, partendo da:
  263.     // A^2+B^2=D^2
  264.     // A^2+C^2=F^2
  265.     // B^2+C^2=E^2
  266.     // Troviamo che:
  267.     // D^2+E^2+F^2 = 2(A^2+B^2+C^2)
  268.     // il che indica che la somma dei quadrati delle diagonali deve essere pari
  269.     // il che vuol dire che o sono tutte e tre diagonali pari oppure
  270.     // ve ne sono due dispari e una sola pari.
  271.     // d'altronde non può essere nemmeno che siano tutte e tre pari altrimenti
  272.     // vorrebbe dire che gli elementi di tutte le terne pitagoriche dovrebbero
  273.     // essere pari, ma questo non è possibile.
  274.     // quindi due diagonali devono essere pari e una dispari.
  275.     // questo ci evita di cercare il moltiplicatore m3 pari che renderebbe due diagonali pari
  276.  
  277. #ifndef __C64__
  278. #define FOUT 1
  279. #endif // __C64__
  280. #ifdef FOUT
  281.     FILE *fp;
  282.     fp=fopen("c:\\temp\\Mattoni.txt", "w");
  283. #endif // FOUT
  284.  
  285.     // Ciclo sulla faccia più piccola
  286.     // Primitiva è il puntatore alla tripletta che indica la faccia più piccola
  287.     T3=0;
  288.     while(T3<TPP_Index) {
  289.         T2=0;
  290.         while(T2<TPP_Index-1) {
  291.             T1=0;
  292.             while(T1<TPP_Index-2) {
  293.                 if ((unsigned long int)TPP[T1][1]*(unsigned long int)TPP[T2][0]*(unsigned long int)TPP[T3][1] == (unsigned long int)TPP[T1][0]*(unsigned long int)TPP[T2][1]*(unsigned long int)TPP[T3][0]) {
  294.                     m3=1;
  295.                     SPIGA = 0;
  296.                     SPIGB = 0;
  297.                     while(m3<=MoltiplicatoreMax) {
  298.                         SPIGA += TPP[T3][1]; // TPP[T3][1] * m3
  299.                         SPIGB += TPP[T3][0]; // TPP[T3][0] * m3
  300.                         if (SPIGA % TPP[T1][0] ==0 && SPIGB % TPP[T2][0]==0) {
  301.                             m2 = SPIGB / TPP[T2][0]; // m2 = B/a2
  302.                             m1 = SPIGA / TPP[T1][0]; // m1 = A/a1
  303.                             // Controllo che il parallelepipedo perfetto appena trovato non sia una mera scalatura
  304.                             // se mcd(m0, m1, m2) == 1 allora è un parallelepipedo primo
  305.                             if(MCD(m1, MCD(m2, m3))==1) {
  306.                                 ++ContaTerne;
  307.  
  308.                                 SPIGC = TPP[T2][1]*m2;
  309.  
  310.                                 end_t = clock()-start_t;
  311.                                 Sec = (unsigned short) (end_t / CLOCKS_PER_SEC);
  312.                                 HH = Sec/3600;
  313.                                 MM = (Sec%3600)/60;
  314.                                 Sec= (Sec%3600)%60;
  315.                                 Milli = ((end_t % CLOCKS_PER_SEC) * 1000) / CLOCKS_PER_SEC;
  316.                                 printf("M%2d - %03u:%02u:%u.%03u (%lu ticks)\n", ContaTerne, HH, MM, Sec, Milli, end_t);
  317.  
  318.                                 printf("%8u %8u %8u %4u\n", TPP[T1][0], TPP[T1][1], TPP[T1][2], m1);
  319.                                 printf("%8u %8u %8u %4u\n", TPP[T2][0], TPP[T2][1], TPP[T2][2], m2);
  320.                                 printf("%8u %8u %8u %4u\n", TPP[T3][0], TPP[T3][1], TPP[T3][2], m3);
  321.                                 printf("%8lu %8lu %8lu\n", SPIGA, SPIGB, SPIGC);
  322.  
  323. #ifdef FOUT
  324.                                 fprintf(fp,"M%2d - %03u:%02u:%u.%03u (%lu ticks)\nPremere Invio per iniziare la ricerca\n", ContaTerne, HH, MM, Sec, Milli, end_t);
  325.                                 fprintf(fp,"%8u %8u %8u %4u\n", TPP[T1][0], TPP[T1][1], TPP[T1][2], m1);
  326.                                 fprintf(fp,"%8u %8u %8u %4u\n", TPP[T2][0], TPP[T2][1], TPP[T2][2], m2);
  327.                                 fprintf(fp,"%8u %8u %8u %4u\n", TPP[T3][0], TPP[T3][1], TPP[T3][2], m3);
  328.                                 fprintf(fp,"%8lu %8lu %8lu\n", SPIGA, SPIGB, SPIGC);
  329. #endif // FOUT
  330.                                 printf("-------------------------------------\n");
  331.                                 m3 =MMAX; // forzo uscita ... forse col Break fa prima
  332.                             }
  333.                         }
  334.                         ++m3;
  335.                     }
  336.                 }
  337.                 ++T1;
  338.             }
  339.             ++T2;
  340.         }
  341.         ++T3;
  342.     }
  343. #ifdef FOUT
  344.  
  345.     fclose(fp);
  346. #endif // FOUT
  347. }
  348.  
  349.  
  350.  
  351. int main() {
  352.  
  353.  
  354.     MT.Mx[0][0] = 1;
  355.     MT.Mx[0][1] = 2;
  356.     MT.Mx[0][2] = 2;
  357.     MT.Mx[1][0] = 2;
  358.     MT.Mx[1][1] = 1;
  359.     MT.Mx[1][2] = 2;
  360.     MT.Mx[2][0] = 2;
  361.     MT.Mx[2][1] = 2;
  362.     MT.Mx[2][2] = 3;
  363.  
  364.     start_t = clock();
  365.     Initialize();
  366.  
  367.     end_t = clock()-start_t;
  368.     Sec = (unsigned int) (end_t / CLOCKS_PER_SEC);
  369.     HH = Sec/3600;
  370.     MM = (Sec%3600)/60;
  371.     Sec= (Sec%3600)%60;
  372.     Milli = ((end_t % CLOCKS_PER_SEC) * 1000) / CLOCKS_PER_SEC;
  373.     printf("\nCalcolo TPP\nTPP Totali:%d\n", TPP_Index + 1);
  374.     printf("HHH:MM:ss.mm - %03u:%02u:%u.%03u (%lu ticks)\n", HH, MM, Sec, Milli, end_t);
  375.  
  376.  
  377.  
  378.     start_t = clock();
  379.     WalkOnList();
  380.     end_t = clock()-start_t;
  381.     Sec = (unsigned int) (end_t / CLOCKS_PER_SEC);
  382.     HH = Sec/3600;
  383.     MM = (Sec%3600)/60;
  384.     Sec= (Sec%3600)%60;
  385.     Milli = ((end_t % CLOCKS_PER_SEC) * 1000) / CLOCKS_PER_SEC;
  386.     printf("Fine HHH:MM:ss.mm - %03u:%02u:%u.%03u (%lu ticks)\n", HH, MM, Sec, Milli, end_t);
  387.  
  388.     return 0;
  389. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement