Numéros congruents

21

Définitions:

  • Un triangle est considéré comme un triangle rectangle si l'un des angles intérieurs est exactement à 90 degrés.
  • Un nombre est considéré comme rationnel s'il peut être représenté par un rapport d'entiers, c'est-à-dire p/qoù les deux pet qsont des entiers.
  • Un nombre nest un nombre congru s'il existe un triangle rectangle de surface noù les trois côtés sont rationnels.
  • Il s'agit d'OEIS A003273 .

Défi

Il s'agit d'un . Étant donné un numéro d'entrée,, xaffichez une valeur distincte et cohérente si xest un nombre congru, et une valeur distincte distincte et cohérente si xn'est pas un nombre congru. Les valeurs de sortie ne doivent pas nécessairement être véridiques / falsey dans votre langue.

Règle spéciale

Aux fins de ce défi, vous pouvez supposer que la conjecture de Birch et Swinnerton-Dyer est vraie. Alternativement, si vous pouvez prouver la conjecture de Birch et Swinnerton-Dyer, allez réclamer votre prix Millenium de 1000000 $. ;-)

Exemples

(Utilisation Truepour des nombres congrus et Falseautrement).

5 True
6 True
108 False

Règles et clarifications

  • L'entrée et la sortie peuvent être fournies par n'importe quelle méthode pratique .
  • Vous pouvez imprimer le résultat dans STDOUT ou le renvoyer en tant que résultat de fonction. Veuillez indiquer dans votre soumission les valeurs que la sortie peut prendre.
  • Un programme complet ou une fonction sont acceptables.
  • Les failles standard sont interdites.
  • Il s'agit de donc toutes les règles de golf habituelles s'appliquent et le code le plus court (en octets) gagne.
AdmBorkBork
la source
3
L'entrée est-elle un entier positif?
Lynn
Mon approche initiale a été de multiplier l'entrée par un nombre carré arbitraire jusqu'à ce que ce soit la moitié du produit des jambes dans un triple de Pythagore, mais j'ai réalisé qu'il pourrait être un peu difficile de terminer pour une entrée non congruente.
Unrelated String
@ Xi'an D'accord, mais les défis doivent être autonomes.
Lynn
@Lynn Oui, l'entrée sera un entier positif.
AdmBorkBork

Réponses:

8

R, 179 173 142 141 137 137 135 134 octets

En utilisant les mêmes arguments basés sur le théorème de Tunnell , renvoie un 0si nn'est pas congru et 1sinon. (Il m'a fallu un certain temps pour repérer la contrainte sur la condition s'appliquant uniquement aux entiers sans carré .)

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,"+"))}

Essayez-le en ligne

Améliorations apportées par Arnaud et Giuseppe (le code final est principalement celui de Guiseppe!), Avec -3 grâce à Robin

Analyse syntaxique:

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)

avec le théorème de Tunnell indiquant que n est congru si et seulement si le nombre de solutions entières à 2x² + y² + 8z² = n est deux fois plus que le nombre de solutions entières à 2x² + y² + 32z² = n si n est impair et le nombre de solutions entières à 8x² + y² + 16z² = n est deux fois plus que le nombre de solutions entières à 8x² + y² + 64z² = n si n est pair.

Xi'an
la source
1
Bienvenue chez PPCG! Le but est de rendre le code le plus court possible. Peut-être que vous pourriez regarder ces conseils pour jouer au golf ou ces conseils R-spécifiques .
Giuseppe
1
Il y a beaucoup d'espace, et je recommanderais également d'inclure un lien vers Try It Online! pour aider à vérifier votre code :-)
Giuseppe
1
N'hésitez pas à tendre la main dans le chat du golfeur R si vous le souhaitez; vous pouvez avertir en utilisant @[username]... Je suppose que vous avez été entraîné dans le golf de code par Robin Ryder ??
Giuseppe
1
142 octets - les fonctions anonymes sont parfaitement bien, et j'ai fait quelques autres golfs que je suis heureux d'expliquer
Giuseppe
1
Agréable! Y a-t-il une raison que vous utilisez -n:n? Je n'ai pas lu le théorème de Tunnel, mais il me semble que n:0cela fonctionnerait aussi bien pour -1 octet ... Aussi, astuce de pro, si vous appuyez sur le bouton "lien" en haut de TIO, vous serez bien formats pour copier et coller dans PPCG :-) EDIT: Je vois, il y a des cas où n:0ça ne marche pas.
Giuseppe
3

Rouille - 282 octets

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]}
  • Utilisez le théorème de Jerrold B. Tunnell , que je ne comprends pas vraiment, mais qui semble fonctionner de toute façon.
  • divisez n par tous ses facteurs carrés, pour le rendre «sans carré», car dans les articles ci-dessous le théorème de Tunnell est décrit pour les carrés libres uniquement.
    • Je crois que cela pourrait fonctionner parce que chaque nombre congruent, lorsqu'il est multiplié par un carré, crée un plus grand nombre congruent, et vice versa. donc en testant le plus petit nombre, nous pouvons valider le plus grand, qui dans notre cas est n. (tous les carrés supprimés peuvent être multipliés pour former un grand carré).
  • 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
    • dans le code lui-même, les quatre équations ont été fusionnées en une seule, à l'intérieur d'une boucle, en utilisant modulo pour pair / impair
  • garder un décompte des équations qui correspondent à n
  • après le bouclage, testez les ratios des décomptes (par Tunnell)

Voir également:

corrigé pair / impair, merci @Level River St

Don Bright
la source
1
eh bien, au moment où j'ai obtenu ce travail, je n'ai vu que la réponse c ++ qui était fausse ...
don bright
merci Level River St
don bright
3

C ++ (gcc) , 251 234 bytes

Merci à @arnauld d'avoir signalé une faute de frappe stupide de ma part.

-17 octets grâce à @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;}

Essayez-le en ligne!

Renvoie 1 si n est congru, 0 sinon.

qs2q est également congruente (l'algorithme semble casser sur certains nombres contenant des carrés.

Neil A.
la source
1
@Arnauld: ah, c'était une faute de frappe de ma part. fixé.
Neil A.
1

JavaScript (ES7), 165 octets

Tout comme la réponse de @ NeilA. , Cela est basé sur le théorème de Tunnell et suppose donc que la conjecture de Birch et Swinnerton-Dyer est vraie.

Renvoie une valeur booléenne.

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

Essayez-le en ligne!

Comment?

nnr=ns2

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

gCk2r<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

g(x,y,z)[r+1,r]3s2An=Bnn2Cn=Dnn

UNEn=#{(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}n=#{(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
Arnauld
la source
1

Rubis , 126 octets

->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}

Essayez-le en ligne!

trouvé un endroit pour initialiser t=1et élargir la liste des carrés en un triplet au lieu d'utiliser qpour faire des copies supplémentaires.

Rubis , 129 octets

->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}

Essayez-le en ligne!

Utilise le théorème de Tunnell comme les autres réponses. J'utilise une seule équation comme suit.

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

Nous vérifions les cas k=8et k=32vérifions s'il y a deux fois plus de solutions k=8que k=32. Cela se fait en ajoutant k-16à tchaque fois que nous trouvons une solution. C'est soit +16 dans le cas k=32ou -8 dans le cas k=8. Globalement, le nombre est congru sit est identique à sa valeur initiale à la fin de la fonction.

Il est nécessaire de trouver toutes les solutions à l'équation de test. Je vois de nombreuses réponses tester entre +/- sqrt n. Il est parfaitement correct de tester également en dehors de ces limites s'il raccourcit le code, mais aucune solution ne sera trouvée car le côté gauche de l'équation dépassera n. Ce que j'ai manqué au début, c'est que le négatif et le positif x,y,zsont considérés séparément. On -3,0,3obtient ainsi trois carrés 9,0,9et toutes les solutions doivent être comptées séparément (0 doit être compté une fois et 9doit être compté deux fois.)

Code non golfé

->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.
Level River St
la source
sur les solutions positives et négatives, même ici, j'ai perdu un bon moment à manquer ce point!
Xi'an