Números congruentes

21

Definições:

  • Um triângulo é considerado um triângulo retângulo se um dos ângulos internos for exatamente 90 graus.
  • Um número é considerado racional se puder ser representado por uma razão de números inteiros, ou seja p/q, onde ambos pe qsão números inteiros.
  • Um número né um número congruente se existir um triângulo retângulo de área em nque todos os três lados sejam racionais.
  • Este é o OEIS A003273 .

Desafio

Este é um desafio para o . Dado um número de entrada x, produza um valor distinto e consistente se xfor um número congruente e um valor distinto e consistente separado se xnão for um número congruente. Os valores de saída não precisam necessariamente ser verdade / falsey no seu idioma.

Regra Especial

Para os propósitos deste desafio, você pode assumir que as conjecturas de Birch e Swinnerton-Dyer são verdadeiras. Como alternativa, se você puder provar a conjectura de Birch e Swinnerton-Dyer, reivindique seu prêmio do Millennium de US $ 1.000.000. ;-)

Exemplos

(Usando Truepara números congruentes e Falseoutros).

5 True
6 True
108 False

Regras e esclarecimentos

  • A entrada e a saída podem ser fornecidas por qualquer método conveniente .
  • Você pode imprimir o resultado em STDOUT ou retorná-lo como resultado da função. Indique na sua submissão quais valores a saída pode assumir.
  • Um programa completo ou uma função são aceitáveis.
  • As brechas padrão são proibidas.
  • Isso é portanto todas as regras usuais de golfe se aplicam e o código mais curto (em bytes) vence.
AdmBorkBork
fonte
3
A entrada é um número inteiro positivo?
Lynn
Minha abordagem inicial foi multiplicar a entrada por um número quadrado arbitrário até que seja metade do produto das pernas em um triplo pitagórico, mas então percebi que poderia ser um pouco difícil finalizar uma entrada não congruente.
String não relacionada
@ Xi'an Ok, mas os desafios devem ser independentes.
Lynn
@ Lynn Sim, a entrada será um número inteiro positivo.
AdmBorkBork 29/04

Respostas:

8

R, 179 173 142 141 137 135 134 bytes

Usando os mesmos argumentos baseados no Teorema de Tunnell , retorna a 0se nnão for congruente e 1não. (Demorei muito tempo para identificar a restrição na condição aplicável apenas a números inteiros livres de quadrado .)

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

Experimente online

Melhorias trazidas por Arnaud e Giuseppe (o código final é principalmente de Guiseppe!), Com -3 graças a Robin

Análise de sintaxe:

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)

com o Teorema de Tunnell afirmando que n é congruente se e somente se o número de soluções inteiras para 2x² + y² + 8z² = n for duas vezes maior que o número de soluções inteiras para 2x² + y² + 32z² = n se n for ímpar e o número de soluções inteiras para 8x² + y² + 16z² = n é o dobro do número de soluções inteiras para 8x² + y² + 64z² = n se n for par.

Xi'an
fonte
1
Bem-vindo ao PPCG! O objetivo é tornar o código o mais curto possível. Talvez você pode olhar para estas dicas para golfe ou essas dicas específicas-R .
Giuseppe
1
Há muito espaço em branco, e também recomendo incluir um link para o Try It Online! para ajudar a verificar o seu código :-)
Giuseppe
1
Sinta-se à vontade para entrar em contato também no bate - papo do jogador R, se quiser; você pode notificar usando @[username]... Acho que você foi puxado para o código de golfe por Robin Ryder?
Giuseppe
1
142 bytes - funções anônimas estão perfeitamente bem, e eu fiz alguns outros golfe que fico feliz em explicar
Giuseppe
1
Agradável! Existe algum motivo para você usar -n:n? Não li o teorema de Tunnel, mas parece-me que n:0funcionaria da mesma forma para -1 byte ... Além disso, dica profissional, se você pressionar o botão "link" na parte superior do TIO, ficará legal formatos para copiar e colar no PPCG :-) EDIT: Entendo, existem alguns casos em n:0que não funciona.
Giuseppe
3

Ferrugem - 282 bytes

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]}
  • Use o teorema de Jerrold B. Tunnell , que eu realmente não entendo, mas parece funcionar de qualquer maneira.
  • divida n por todos os seus fatores quadrados, para torná-lo "livre de quadrados", uma vez que nos artigos abaixo o teorema de Tunnell é descrito apenas para liberações quadradas.
    • Acredito que isso possa funcionar porque todo número congruente, quando multiplicado por um quadrado, cria um número congruente maior e vice-versa. testando o número menor, podemos validar o maior, que no nosso caso é n. (todos os quadrados removidos podem ser multiplicados para formar um quadrado grande).
  • faça um loop em todas as combinações possíveis de inteiros x, y, z, teste as equações de Tunnell:
    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
    • no próprio código, as quatro equações foram agrupadas em uma, dentro de um loop, usando o módulo para pares / ímpares
  • mantenha uma contagem das equações correspondentes a n
  • após o loop, teste as proporções dos pontos (por Tunnell)

Veja também:

corrigido par / ímpar, obrigado @Level River St

não brilhante
fonte
1
oh bem, no momento em que consegui esse trabalho, só vi a resposta c ++ que estava errada ...
don bright
obrigado Level River St
don bright
3

C ++ (gcc) , 251 234 bytes

Obrigado a @arnauld por apontar um erro de digitação bobo da minha parte.

-17 bytes graças a @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;}

Experimente online!

Retorna 1 se nfor congruente, 0 caso contrário.

qs2q também é congruente (o algoritmo parece quebrar em alguns números que contêm quadrados).

Neil A.
fonte
1
@ Arnauld: ah, isso foi um erro de digitação da minha parte. fixo.
Neil A.
1

JavaScript (ES7), 165 bytes

Muito parecido com a resposta de @ NeilA. , Isso é baseado no teorema de Tunnell e, portanto, assume que a conjectura de Birch e Swinnerton-Dyer é verdadeira.

Retorna um valor booleano.

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

Experimente online!

Quão?

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

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

Experimente online!

encontrou um local para inicializar t=1e expandiu a lista de quadrados em um trio, em vez de usar qpara fazer cópias adicionais.

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}

Experimente online!

Usa o teorema de Tunnell como as outras respostas. Eu uso uma única equação da seguinte maneira.

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

Nós verificar os casos k=8e k=32e verificar se há o dobro de soluções para k=8que k=32. Isso é feito adicionando k-16a tcada vez que encontramos uma solução. Isso é +16 no caso k=32ou -8 no caso k=8. No geral, o número é congruente se tfor o mesmo que seu valor inicial no final da função.

É necessário encontrar todas as soluções para a equação de teste. Vejo muitas respostas testando entre +/- sqrt n. Não há problema em testar também fora desses limites se o código for mais curto, mas nenhuma solução será encontrada porque o lado esquerdo da equação excederá n. O que eu perdi no começo é que negativo e positivo x,y,zsão considerados separadamente. Assim, -3,0,3produz três quadrados 9,0,9e todas as soluções devem ser contadas separadamente (0 deve ser contado uma vez e 9deve ser contado duas vezes).

Código ungolfed

->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
fonte
sobre soluções positivas e negativas, mesmo aqui, perdi um bom tempo perdendo esse ponto!
Xian