Tripla sequenza pitagorica


33

Una tripla pitagorica è composta da tre numeri interi positivi a, b e c, in modo tale che a 2 + b 2 = c 2 . Tale tripla è comunemente scritta (a, b, c) e un esempio ben noto è (3, 4, 5). Se (a, b, c) è una tripla pitagorica, allora lo è anche (ka, kb, kc) per qualsiasi numero intero positivo k. Una tripla pitagorica primitiva è una in cui a, bec sono coprimi .

Usando questa conoscenza, possiamo creare una sequenza concatenando insieme le minime lunghezze delle triple, in cui l'elemento successivo nella sequenza è l'ipotenusa (il numero più grande) della più piccola tripla pitagorica primitiva contenente l'elemento precedente come la più piccola delle sue lunghezze.

Inizia con la più piccola tripla pitagorica primitiva (3, 4, 5). La sequenza inizia con 3e l'ipotenusa (elemento successivo nella sequenza) è 5. Quindi trova la più piccola tripla pitagorica primitiva con 5come una gamba e ottieni (5, 12, 13). Quindi la sequenza continua con 13.

Emette la sequenza per sempre, oppure accetta un input intero ne genera i primi nelementi della sequenza, zero o uno indicizzato.

È necessario supportare l'output almeno attraverso e compreso 28455997, ma se il limite del tipo di dati che si sta utilizzando è stato improvvisamente aumentato, dovrebbe funzionare per quel nuovo limite. Quindi non è possibile codificare un elenco di numeri.

3
5
13
85
157
12325
90733
2449525
28455997
295742792965
171480834409967437
656310093705697045
1616599508725767821225590944157
4461691012090851100342993272805
115366949386695884000892071602798585632943213
12002377162350258332845595301471273220420939451301220405

OEIS A239381

Sequenze simili (non emetterle!):


C'è un limite di tempo?
Loovjo,

@Loovjo No, ma dovresti sapere / dimostrare che l'output è corretto. Ci sono alcune sequenze simili in cui l'output differisce dopo 12325.
mbomb007,

La sequenza simile a cui sto pensando differisce dopo 85... il suo prossimo termine è 3613(riesci a indovinare di cosa si tratta ancora?)
Neil,

@Neil Una rapida ricerca produce A053630 , la spirale di Pitagora. Tuttavia, ho fatto riferimento ai due nella sfida, perché mentre lavoravo alla mia implementazione ho accidentalmente raggiunto quelle due sequenze o simili.
mbomb007,

1
Anzi, se fossi stato più sveglio avrei potuto cercarlo da solo ...
Neil,

Risposte:


11

Gelatina , 19 byte

o3ṄÆF*/€ŒPP€²+Ṛ$HṂß

Ho salvato un byte grazie a @ Dennis eseguendo il refactoring in una sequenza infinita.

Non accetta input e argomenti, quindi restituisce la sequenza all'infinito stampando ogni termine mentre li calcola. Questo metodo rallenta man mano che i numeri diventano più grandi poiché dipende dalla fattorizzazione primaria.

Provalo online!

Questo calcola il termine successivo calcolando la fattorizzazione in termini di potenza primaria del termine corrente. Per 12325, questo è {5 2 , 17, 29}. Esiste una variante della formula di Euclide per il calcolo delle triple di Pitagora { a , b , c },

formula

dove m > n e la tripla sono primitivi se m e n sono coprimi.

Per calcolare la radice primitiva successiva da 12325, trova m e n tale che mn = 12325 e scegli m , n in modo che gcd ( m , n ) = 1. Quindi genera tutte le coppie di m , n creando tutti i sottoinsiemi di {5 2 , 17, 29} e trovare il prodotto di ciascuno di quei sottoinsiemi che sono {1, 25, 17, 29, 425, 725, 493, 12325}. Quindi dividere 12325 per ciascun valore e coppia in modo che ogni coppia sia m , n . Calcola la formula per c usando ciascuna coppia e prendi il minimo che è 90733.

  • Il metodo precedente non è riuscito a determinare il termine successivo dopo 228034970321525477033478437478475683098735674620405573717049066152557390539189785244849203205. Il metodo precedente ha scelto l'ultimo valore come fattore quando la scelta corretta era il 3 ° e l'ultimo numero primo. Il nuovo metodo è più lento ma funzionerà sempre poiché verifica tutte le coppie di coprimi per trovare l'ipotenusa minima.

Spiegazione

o3ṄÆF*/€ŒPP€²+Ṛ$HṂß  Main link. Input: 0 if none, else an integer P
o3                   Logical OR with 3, returns P if non-zero else 3
  Ṅ                  Println and pass the value
   ÆF                Factor into [prime, exponent] pairs
     */€             Reduce each pair using exponentation to get the prime powers
        ŒP           Powerset of those
          P€         Product of each
            ²        Square each
               $     Monadic chain
             +         Add vectorized with
              Ṛ        the reverse
                H    Halve
                 Ṃ   Minimum
                  ß  Call recursively on this value

Caspita, è davvero veloce!
mbomb007,

1
o3ṄÆfµṪ,P²SHßcon output infinito salva un byte.
Dennis,

5

Brachylog , 36 byte

3{@wB:?>:^a+~^=C:B:?:{$pd}ac#d,C:1&}

Provalo online!

Devi attendere il timeout del programma (1 minuto) prima che TIO annulli l'output. Nel REPL di SWI-Prolog questo viene stampato non appena trova il valore.

Questo stamperà la sequenza per sempre.

Dopo alcuni minuti sull'interprete offline di SWI-Prolog, ho ottenuto 90733dopo 12325. L'ho fermato dopo questo punto.

Questa non è una forza bruta completa in quanto utilizza vincoli per trovare triple di Pitagora, sebbene non sia ovviamente ottimizzata per la velocità.

Spiegazione

3{                                 }    Call this predicate with 3 as Input
  @w                                    Write the Input followed by a line break
    B:?>                                B > Input
           +                            The sum...
        :^a                             ...of Input^2 with B^2...
            ~^                          ...must equal a number which is itself a square
              =C                        Assign a fitting value to that number and call it C
               C:B:?:{$pd}a             Get the lists of prime factors of C, B and Input
                                          without duplicates
                           c#d,         Concatenate into a single list; all values must be
                                          different
                               C:1&     Call recursively with C as Input

4

Perl, 73 byte

for($_=3;$_<1e9;$_=$a**2+$b**2){$a++until($b=($_+$a**2)**.5)==($b|0);say}

Tutte le triple di Pitagora a²+b²=c²soddisfano a=r(m²-n²), b=2rmn, c=r(m²+n²)alcuni numeri interi r,m,n. Quando r=1e m,nsono coprimi con esattamente uno che è divisibile per 2, allora a,b,cè una tripla primitiva, dove a,b,csono tutti coprimi a coppie.

Con questo in mente, dato alcuni a, uso un algoritmo a forza bruta per calcolare il più piccolo ntale che a²-n²sia un quadrato, vale a dire . Quindi, cè uguale a n²+m².


Possibile errore di battitura nella tua spiegazione: cerchi ntale che a+n²sia un quadrato.
Neil,

2

Python 3, 178 byte

from math import*
p,n=[3,5],int(input())
while len(p)<n:
 for i in range(p[-1],p[-1]**2):
  v=sqrt(i**2+p[-1]**2)
  if v==int(v)and gcd(i,p[-1])==1:
   p+=[int(v)];break
print(p)

Questo è fondamentalmente solo un algoritmo a forza bruta e quindi è molto lento. Ci vuole la quantità di termini per l'output come input.

Non sono sicuro al 100% della correttezza di questo algoritmo, il programma controlla l'altra gamba fino alla prima gamba quadrata, che credo sia abbastanza, ma non ho fatto i conti.

Provalo su repl.it! (Non aggiornato) (Non provare per numeri superiori a 10, sarà molto lento)


È possibile passare a Python 3.5 e utilizzare math.gcd. Inoltre, utilizzare p+=[...]invece di p.append(...). E <2invece di ==1. E iftutti possono essere su una riga.
mbomb007,

1
Puoi ancora fare gli ultimi 2 miglioramenti che ho suggerito.
mbomb007,


Loovjo, giocherai a golf il tuo codice usando i suggerimenti o no?
mbomb007,

2

MATL , 27 byte

Ii:"`I@Yyt1\~?3MZdZdq]}6MXI

Questo produce i primi termini della sequenza. L'input è basato su 0.

Il codice è molto inefficiente. Il compilatore online scade per input maggiori di 5. L'input 6ha richiesto un minuto e mezzo offline (e ha prodotto il corretto 90733come 6 ° termine).

Provalo online!

I            % Push 3 (predefined value of clipboard I)
i            % Input n
:"           % For each (i.e. execute n times)
  `          %   Do...while
    I        %     Push clipboard I. This is the latest term of the sequence
    @        %     Push iteration index, starting at 1
    Yy       %     Hypotenuse of those two values
    t1\      %     Duplicate. Decimal part
    ~?       %     If it is zero: we may have found the next term. But we still
             %     need to test for co-primality
      3M     %       Push the two inputs of the latest call to the hypotenuse 
             %       function. The stack now contains the hypotenuse and the
             %       two legs
      ZdZd   %       Call GCD twice, to obtain the GCD of those three numbers
      q      %       Subtract 1. If the three numbers were co-prime this gives
             %       0, so the do...while loop will be exited (but the "finally" 
             %       part will be executed first). If they were not co-prime  
             %       this gives non-zero, so the do...while loop proceeds 
             %       with the next iteration
    ]        %     End if
             %     If the decimal part was non-zero: the duplicate of the 
             %     hypotenuse that is now on the top of the stack will be used
             %     as the (do...while) loop condition. Since it is non-zero, 
             %     the loop will proceed with the next iteration
  }          %   Finally (i.e. execute before exiting the do...while loop)
    6M       %     Push the second input to the hypotenuse function, which is
             %     the new term of the sequence
    XI       %     Copy this new term into clipboard I
             %   Implicitly end do...while
             % Implicitly end for each
             % Implicitly display the stack, containing the sequence terms

2

Racchetta 106 byte

(let p((h 3))(println h)(let p2((i 1))(define g(sqrt(+(* h h)(* i i))))(if(integer? g)(p g)(p2(add1 i)))))

Ungolfed:

(define (f)
  (let loop ((h 3))
    (let loop2 ((i 1))
      (define g (sqrt (+(* h h) (* i i))))
      (if (not(integer? g))
          (loop2 (add1 i))
          (begin (printf "~a ~a ~a~n" h i g)
                 (loop g))))))

test:

(f)

Uscita della versione golfata:

3
5
13
85
157
12325
12461
106285
276341
339709
10363909
17238541

Uscita della versione non modificata:

3 4 5
5 12 13
13 84 85
85 132 157
157 12324 12325
12325 1836 12461
12461 105552 106285
106285 255084 276341
276341 197580 339709
339709 10358340 10363909
10363909 13775220 17238541

(Errore dopo questo sul mio computer)


Il codice golfato stampa solo ipotenusa di sequenza. Le versioni Ungolfed mostrano tutte e tre le chiarificazioni per le terzine non menzionate nella questione.
anche il


1

PHP, 139 byte

for($k=3;$i=$k,print("$k\n");)for($j=$i+1;($k=sqrt($m=$i*$i+$j*$j))>(int)$k||gmp_intval(gmp_gcd(gmp_gcd((int)$i,(int)$j),(int)$k))>1;$j++);

Il codice sopra riportato si interrompe dopo 28455997 su sistemi a 32 bit. Se sono necessari numeri più alti, diventano 156 byte:

for($k=3;$i=$k,print("$k\n");)for($j=$i+1;!gmp_perfect_square($m=bcadd(bcpow($i,2),bcpow($j,2)))||gmp_intval(gmp_gcd(gmp_gcd($i,$j),$k=bcsqrt($m)))>1;$j++);

1

Java 8, 133 byte

-25 byte grazie alle miglia Usando n * n invece di Math.pow (n, 2)

-24 byte grazie alle miglia Utilizzo di loop anziché di while, modifica del tipo di dati, eliminazione () dovuta all'ordine delle operazioni

()->{long b=3,c,n;for(;;){for(n=1;;n++){c=b+2*n*n;double d=Math.sqrt(c*c-b*b);if(d==(int)d&b<d){System.out.println(b);break;}}b=c;}};

Usa il fatto che

Relazione

per qualsiasi coppia di numeri interi m> n> 0. Pertanto, C è uguale ad A più 2 (N) 2 . La funzione sopra trova il valore minimo di N che soddisfa questa relazione, rendendo al contempo il secondo elemento del pitagorico triplo un numero intero e maggiore del primo elemento. Quindi imposta il valore del primo elemento sul terzo elemento e si ripete con il primo elemento aggiornato.

Ungolfed:

void printPythagoreanTriples() {
    long firstElement = 3, thirdElement, n;
    while (true) {
        for (n = 1; ; n++) {
            thirdElement = firstElement + (2 * n * n);
            double secondElement = Math.sqrt(thirdElement * thirdElement - firstElement * firstElement);
            if (secondElement == (int) secondElement && firstElement < secondElement) {
                System.out.println("Found Pythagorean Triple [" +
                        firstElement + ", " +
                        secondElement + ", " +
                        thirdElement + "]");
                break;
            }
        }
        firstElement = thirdElement;
    }
}

Ideone esso!

* L'ideone non stampa l'ultimo elemento richiesto a causa dei limiti di tempo, tuttavia, come puoi vedere attraverso la logica del programma e la versione ungolf (che stampa il 28455997 come terzo elemento della precedente tripla pitagorica piuttosto che il primo elemento di il prossimo), i valori vengono stampati con un limite di tempo superiore.


Non potresti usare al n*nposto di Math.pow(n,2)?
miglia

Non so perché non ci abbia pensato ... Lo aggiungerò subito. Grazie @miles
Mario Ishac,

Mi sono rasato un po 'di più usando i forloop per farlo scendere a 133 byte()->{long b=3,c,n;for(;;){for(n=1;;n++){c=b+2*n*n;double d=Math.sqrt(c*c-b*b);if(d==(int)d&b<d){System.out.println(b);break;}}b=c;}};
miglia

1

Python 3.5, 97 byte

Output errato dopo 28455997, a causa dei limiti del tipo di dati in virgola mobile. La sqrtfunzione non è abbastanza buona, ma se la precisione fosse magicamente aumentata, funzionerebbe.

Abbastanza semplice da capire Incrementare cdi due invece di uno dimezza il tempo di esecuzione e comunque è necessario controllare solo i numeri dispari, poiché gli elementi sono sempre dispari.

import math
c=a=3
while 1:
	c+=2;b=(c*c-a*a)**.5;i=int(b)
	if math.gcd(a,i)<2<a<b==i:print(a);a=c

Provalo online

Il programma non può essere eseguito su Ideone, perché Ideone utilizza Python 3.4


Affinché l'output rimanga preciso più a lungo, dovrei usare decimal:

import math
from decimal import*
c=a=3
while 1:
	c+=2;b=Decimal(c*c-a*a).sqrt();i=int(b)
	if i==b>a>2>math.gcd(a,i):print(a);a=c

Provalo online

Per rimanere precisi a tempo indeterminato, potrei fare qualcosa di orribile come questo (aumentando la precisione richiesta ogni singola iterazione :

import math
from decimal import*
c=a=3
while 1:
	c+=2;b=Decimal(c*c-a*a).sqrt();i=int(b);getcontext().prec+=1
	if i==b>a>2>math.gcd(a,i):print(a);a=c



1

APL (NARS), 169 caratteri, 338 byte

h←{{(m n)←⍵⋄(mm nn)←⍵*2⋄(2÷⍨nn+mm),(2÷⍨nn-mm),m×n}a⊃⍨b⍳⌊/b←{⍵[2]}¨a←a/⍨{(≤/⍵)∧1=∨/⍵}¨a←(w÷a),¨a←∪×/¨{k←≢b←1,π⍵⋄∪{b[⍵]}¨↑∪/101 1‼k k}w←⍵}⋄p←{⍺=1:⍵⋄⍵,(⍺-1)∇↑h ⍵}⋄q←{⍵p 3x}

test ok fino a 14 come argomento di q:

  q 1
3 
  q 2
3 5 
  q 10
3 5 13 85 157 12325 90733 2449525 28455997 295742792965 
  q 12
3 5 13 85 157 12325 90733 2449525 28455997 295742792965 171480834409967437 656310093705697045 
  q 13
3 5 13 85 157 12325 90733 2449525 28455997 295742792965 171480834409967437 656310093705697045 
  1616599508725767821225590944157 
  q 14
NONCE ERROR
  q 14
  ∧

questo sotto troverebbe tutti i divisori del suo argomento ...

∪×/¨{k←≢b←1,π⍵⋄∪{b[⍵]}¨↑∪/101 1‼k k}

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.