Numeri congruenti


21

definizioni:

  • Un triangolo è considerato un triangolo rettangolo se uno degli angoli interni è esattamente di 90 gradi.
  • Un numero è considerato razionale se può essere rappresentato da un rapporto di numeri interi, ovverop/q , dove entrambi pe qsono numeri interi.
  • Un numero nè un numero congruente se esiste un triangolo rettangolo di area in ncui tutte e tre le parti sono razionali.
  • Questo è OEIS A003273 .

Sfida

Questa è una sfida al . Dato un numero di input x, genera un valore distinto e coerente se xè un numero congruente e un valore distinto e coerente se xnon è un numero congruente. I valori di output non devono necessariamente essere verità / falsità nella tua lingua.

Regola speciale

Ai fini di questa sfida, puoi presumere che la congettura di Birch e Swinnerton-Dyer sia vera. In alternativa, se riesci a provare la congettura di Birch e Swinnerton-Dyer, vai a richiedere il tuo premio da $ 1,000,000 Millennium. ;-)

Esempi

(Usando Trueper numeri congruenti e Falsealtro).

5 True
6 True
108 False

Regole e chiarimenti

  • Input e output possono essere forniti con qualsiasi metodo conveniente .
  • È possibile stampare il risultato su STDOUT o restituirlo come risultato di una funzione. Indicare nella richiesta quali valori può assumere l'output.
  • È accettabile un programma completo o una funzione.
  • Sono vietate le scappatoie standard .
  • Si tratta di quindi si applicano tutte le normali regole del golf e vince il codice più breve (in byte).

3
L'input è un numero intero positivo?
Lynn,

Il mio approccio iniziale era quello di moltiplicare l'input per un numero quadrato arbitrario fino a quando non è la metà del prodotto delle gambe in una tripla pitagorica, ma poi ho capito che potrebbe essere un po 'difficile terminare effettivamente per un input non congruente.
Corda non correlata dal

@ Xi'an Va bene, ma le sfide dovrebbero essere autosufficienti.
Lynn,

@Lynn Sì, l'input sarà un numero intero positivo.
AdmBorkBork,

Risposte:


8

R, 179 173 142 141 137 135 134 byte

Usando gli stessi argomenti basati sul Teorema di Tunnell , restituisce un 0if nnon congruente e 1altrimenti. (Mi ci è voluto molto tempo per individuare il vincolo sulla condizione che si applica solo agli interi senza quadrati .)

function(n){b=(-n:n)^2
for(i in b^!!b)n=n/i^(!n%%i)
P=1+n%%2
o=outer
!sum(!o(y<-o(8/P*b,2*b,"+")/P-n,z<-16/P*b,"+"),-2*!o(y,4*z,"+"))}

Provalo online

Miglioramenti apportati da Arnaud e Giuseppe (il codice finale è principalmente di Guiseppe!), Con -3 grazie a Robin

Analisi della sintassi:

for(i in b[b>0])n=n/i^(!n%%i) #eliminates all square divisors of n
P=2^(n%%2)                    #n odd (2) or even (1)
o=outer                       #saves 3 bytes 
o(8/P*b,2*b,"+")/P-n          #all sums of (8/P)x^2+(2/P)*y^2-n
o(...,16/P*b,"+")             #all sums of above and (16/P)*z^2
o(...,4*z,"+"))               #all sums of above and (64/P)*z^2
!o(...,4*z,"+"))              #all sums of above equal to zero
!sum(!...,2*!...)             #are zeroes twice one another (Tunnell)

con il teorema di Tunnell che afferma che n è congruente se e solo se il numero di soluzioni intere a 2x² + y² + 8z² = n è il doppio del numero di soluzioni intere a 2x² + y² + 32z² = n se n è dispari e il numero delle soluzioni intere a 8x² + y² + 16z² = n è il doppio del numero di soluzioni intere fino a 8x² + y² + 64z² = n se n è pari.


1
Benvenuti in PPCG! L'obiettivo è rendere il codice il più breve possibile. Forse si potrebbe guardare a questi suggerimenti per giocare a golf o di questi suggerimenti R-specifici .
Giuseppe,

1
C'è un sacco di spazio bianco, e anche io consiglierei di includere un link per provarlo online! per aiutarti a verificare il tuo codice :-)
Giuseppe,

1
Sentiti libero di contattarci anche nella chat R golfista, se lo desideri; puoi avvisare usando @[username]... Immagino che sei stato attratto dal golf di codice da Robin Ryder ??
Giuseppe,

1
142 byte - le funzioni anonime vanno benissimo, e ho fatto qualche altro golf che sono felice di spiegare
Giuseppe

1
Bello! C'è un motivo che usi -n:n? Non ho letto il teorema di Tunnel, ma mi sembra che n:0funzionerebbe altrettanto bene per -1 byte ... Inoltre, suggerimento professionale, se premi il pulsante "link" nella parte superiore di TIO, otterrai una bella formati per copiare e incollare in PPCG :-) EDIT: vedo, ci sono alcuni casi in cui n:0non funziona.
Giuseppe,

3

Ruggine - 282 byte

fn is(mut n:i64)->bool{let(mut v,p)=(vec![0;4],n as usize%2);while let Some(l)=(2..n).filter(|i|n%(i*i)==0).nth(0){n/=l*l;}for x in -n..=n{for y in -n..=n{for z in -n..=n{for i in 0..2{if n-6*x*x*(n+1)%2==2*x*x+(2-n%2)*(y*y+(24*i as i64+8)*z*z){v[2*p+i]+=1};}}}}v[2*p]==2*v[2*p+1]}
  • Usa Jerrold B. Tunnell il teorema di , che in realtà non capisco, ma sembra funzionare comunque.
  • dividi n per tutti i suoi fattori quadrati, per renderlo "quadrato libero", poiché nelle carte sottostanti il ​​teorema di Tunnell è descritto solo per i quadrati liberi.
    • Credo che questo potrebbe funzionare perché ogni numero congruente, moltiplicato per un quadrato, crea un numero congruente più grande e viceversa. quindi testando il numero più piccolo, possiamo validare il più grande, che nel nostro caso è n. (tutti i quadrati rimossi, possono essere moltiplicati insieme per formare un quadrato grande).
  • loop through all possible combinations of x,y,z integers, test Tunnell's equations:
    if n is odd, test if n = 2x2+y2+32z2 and/or 2x2+y2+8z2
    if n is even, test if n = 8x2+2y2+64z2 and/or 8x2+2y2+16z2
    • in the code itself, the four equations have been smooshed into one, inside a loop, using modulo for even/odd
  • keep a tally count of which equations match n
  • after looping, test the ratios of the tallies (per Tunnell)

See Also:

corrected even/odd, thanks@Level River St


1
oh well, at the time i got this working i only saw the c++ answer which was wrong...
don bright

thanks Level River St
don bright

3

C++ (gcc), 251 234 bytes

Thanks to @arnauld for pointing out a silly typo on my part.

-17 bytes thanks to @ceilingcat.

#import<cmath>
int a(int n){int s=sqrt(n),c,x=-s,y,z,i=1,X;for(;++i<n;)for(;n%(i*i)<1;n/=i*i);for(;x++<s;)for(y=-s;y++<s;)for(z=-s;z++<s;c+=n&1?2*(n==X+24*z*z)-(n==X):2*(n==4*x*x+2*X+48*z*z)-(n/2==2*x*x+X))X=2*x*x+y*y+8*z*z;return!c;}

Try it online!

Returns 1 if n is congruent, 0 otherwise.

Given that we can assume that the Birch and Swinnerton-Dyer conjecture is true, I used Tunnel's Theorem as a test. Note that technically only nonzero x, y, and z need to be tested, as a set of positive (x, y, z) implies more sets for when each of those is negative, since the four numbers defined use the square of x, y, and z in their calculation. Additionally, since only the ratio of the two numbers A and B, or C and D, is desired, we need not even worry about these other sets. Thus, we only need to add 2 for every solution for A or C, and subtract 1 for every solution of B or D, and check if we end with 0. Also, the input is reduced to a squarefree integer, because if q is a congruent number then s2q is also congruent (the algorithm seems to break on some square-containing numbers.


1
@Arnauld: ah, that was a typo on my part. fixed.
Neil A.

1

JavaScript (ES7), 165 bytes

Much like @NeilA.'s answer, this is based on Tunnell's theorem and therefore assumes that the Birch and Swinnerton-Dyer conjecture is true.

Returns a Boolean value.

n=>(r=(g=i=>i<n?g(i+!(n%i**2?0:n/=i*i)):n**.5|0)(s=2),g=(C,k=r)=>k+r&&g(C,k-1,C(k*k)))(x=>g(y=>g(z=>s+=2*(n==(X=(n&1?2:8)*x+(o=2-n%2)*y)+o*32*z)-(n==X+o*8*z))))|s==2

Try it online!

How?

We first transform the input n into its square-free counterpart n, compute r=n and initialize s to 2.

r = (                // we will eventually save isqrt(n) into r
  g = i =>           // g = recursive function taking an integer i
    i < n ?          //   if i is less than n:
      g(i + !(       //     do a recursive call with either i or i + 1
        n % i**2 ?   //     if n is not divisible by i²:
          0          //       yield 0 and therefore increment i
        :            //     else:
          n /= i * i //       divide n by i² and leave i unchanged
      ))             //     end of recursive call
    :                //   else:
      n ** .5 | 0    //     stop recursion and return isqrt(n)
  )(s = 2)           // initial call to g with i = s = 2

We then define the helper function g which invokes a callback function C with k2 for r<kr.

  g = (C, k = r) =>  // C = callback function, k = counter initialized to r
    k + r &&         //   if k is not equal to -r:
    g(               //     do a recursive call:
      C,             //       pass the callback function unchanged
      k - 1,         //       decrement k
      C(k * k)       //       invoke the callback function with k²
    )                //     end of recursive call

We finally use 3 nested calls to g to walk through all triplets (x,y,z)[r+1,r]3 and update s to test whether 2An=Bn if n is odd or 2Cn=Dn if n is even, with:

An=#{(x,y,z)[r+1,r]3n=2x2+y2+32z2}Bn=#{(x,y,z)[r+1,r]3n=2x2+y2+8z2}Cn=#{(x,y,z)[r+1,r]3n=8x2+2y2+64z2}Dn=#{(x,y,z)[r+1,r]3n=8x2+2y2+16z2}

g(x =>                            // for each x:      \    NB:
  g(y =>                          //   for each y:     >-- all these values are
    g(z =>                        //     for each z:  /    already squared by g
      s +=                        //       add to s:
        2 * (                     //         +2 if:
          n == (                  //           n is equal to either
            X =                   //           An if n is odd (o = 1)
            (n & 1 ? 2 : 8) * x + //           or Cn if n is even (o = 2)
            (o = 2 - n % 2) * y   //
          ) + o * 32 * z          //
        ) - (                     //         -1 if:
          n == X + o * 8 * z      //           n is equal to either
        )                         //           Bn if n is odd
    )                             //           or Dn if n is even
  )                               //
)                                 // if s in unchanged, then n is (assumed to be) congruent

1

Ruby, 126 bytes

->n{[8,32].product(*[(-n..-t=1).map{|i|i*=i;n%i<1&&n/=i;i}*2+[0]]*3).map{|j|d=2-n%2
k,x,y,z=j
2*d*x+y+k*z==n/d&&t+=k-16}
t==1}

Try it online!

found a place to initialize t=1 and expanded the list of squares into a triplet instead of using q to make additional copies.

Ruby, 129 bytes

->n{t=0
[8,32].product(q=(-n..-1).map{|i|i*=i;n%i<1&&n/=i;i}*2+[0],q,q).map{|j|d=2-n%2
k,x,y,z=j
2*d*x+y+k*z==n/d&&t+=k-16}
t==0}

Try it online!

Uses Tunnell's theorem like the other answers. I use a single equation as follows.

2*d*x^2 + y^2 + k*z^2 == n/d  where d=2 for even n and d=1 for odd n

We check the cases k=8 and k=32 and check if there are twice as many solutions for k=8 than k=32. This is done by adding k-16 to t every time we find a solution. This is either +16 in the case k=32 or -8 in the case k=8. Overall the number is congruent if t is the same as its initial value at the end of the function.

It is necessary to find all solutions to the test equation. I see many answers testing between +/-sqrt n. It is perfectly OK to test also outside these limits if it makes code shorter, but no solutions will be found because the left side of the equation will exceed n. The thing I missed in the beginning is that negative and positive x,y,z are considered separately. Thus -3,0,3 yields three squares 9,0,9 and all solutions must be counted separately (0 must be counted once and 9 must be counted twice.)

Ungolfed code

->n{t=0                              #counter for solutions

  q=(-n..-1).map{|i|i*=i;n%i<1&&n/=i #make n square free by dividing by -n^2 to -1^2 as necessary 
  i}*2+[0]                           #return an array of squares, duplicate for 1^2 to n^2, and add the case 0 

  [8,32].product(q,q,q).map{|j|      #make a cartesian product of all possible values for k,x,y,z and iterate
    d=2-n%2                          #d=1 for odd n, 2 for even n
    k,x,y,z=j                        #unpack j. k=8,32. x,y,z are the squared values from q.
    2*d*x+y+k*z==n/d&&t+=k-16}       #test if the current values of k,x,y,z are a valid solution. If so, adjust t by k-16 as explained above.
t==0}                                #return true if t is the same as its initial value. otherwise false.

about positive and negative solutions, same here, I wasted quite a while missing this point!
Xi'an
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.