Nomor kongruen

21

Definisi:

  • Segitiga dianggap sebagai segitiga siku-siku jika salah satu sudut dalam persis 90 derajat.
  • Suatu bilangan dianggap rasional jika dapat diwakili oleh rasio bilangan bulat, yaitu p/q, di mana keduanya pdan qbilangan bulat.
  • Angka nadalah angka kongruen jika ada segitiga siku-siku dari area di nmana ketiga sisinya rasional.
  • Ini adalah OEIS A003273 .

Tantangan

Ini adalah tantangan . Diberikan nomor input x,, mengeluarkan nilai yang berbeda dan konsisten jika xmerupakan angka kongruen, dan nilai berbeda dan konsisten terpisah jika xbukan angka kongruen. Nilai-nilai output tidak harus benar-benar benar / salah dalam bahasa Anda.

Aturan khusus

Untuk keperluan tantangan ini, Anda dapat berasumsi bahwa dugaan Birch dan Swinnerton-Dyer adalah benar. Atau, jika Anda dapat membuktikan dugaan Birch dan Swinnerton-Dyer, klaim hadiah Millenium $ 1.000.000 Anda. ;-)

Contohnya

(Menggunakan Truenomor kongruen dan Falselainnya).

5 True
6 True
108 False

Aturan dan Klarifikasi

  • Input dan output dapat diberikan dengan metode apa pun yang mudah .
  • Anda dapat mencetak hasilnya ke STDOUT atau mengembalikannya sebagai hasil fungsi. Silakan sebutkan dalam kiriman Anda nilai apa yang bisa diambil oleh output.
  • Program lengkap atau fungsi dapat diterima.
  • Celah standar dilarang.
  • Ini adalah sehingga semua aturan golf biasa berlaku, dan kode terpendek (dalam byte) menang.
AdmBorkBork
sumber
3
Apakah input bilangan bulat positif?
Lynn
Pendekatan awal saya adalah mengalikan input dengan angka kuadrat sewenang-wenang sampai setengah dari produk kaki dalam triple Pythagoras, tetapi kemudian saya menyadari mungkin agak sulit untuk benar-benar menghentikan input yang tidak kongruen.
String Tidak Terkait
@ Xi'an Oke, tapi tantangan harusnya mandiri.
Lynn
@ Lynn Ya, input akan berupa bilangan bulat positif.
AdmBorkBork

Jawaban:

8

R, 179 173 142 141 137 135 134 byte

Menggunakan argumen yang sama berdasarkan Teorema Tunnell , mengembalikan a 0jika ntidak kongruen dan 1sebaliknya. (Butuh waktu lama untuk menemukan batasan pada kondisi hanya berlaku untuk bilangan bulat kuadrat .)

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

Cobalah online

Perbaikan yang dibawa oleh Arnaud dan Giuseppe (kode terakhir kebanyakan milik Guiseppe!), Dengan -3 berkat Robin

Analisis sintaksis:

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)

dengan Teorema Tunnell yang menyatakan bahwa n adalah kongruen jika dan hanya jika jumlah solusi integer ke 2x² + y² + 8z² = n dua kali lipat jumlah solusi integer ke 2x² + y² + 32z² = n jika n ganjil dan jumlahnya solusi integer hingga 8x² + y² + 16z² = n adalah dua kali lipat jumlah solusi integer hingga 8x² + y² + 64z² = n jika n adalah genap.

Xi'an
sumber
1
Selamat datang di PPCG! Tujuannya adalah membuat kode sesingkat mungkin. Mungkin Anda bisa melihat tip - tip ini untuk bermain golf atau tip - tip R-spesifik ini .
Giuseppe
1
Ada banyak ruang kosong, dan saya juga merekomendasikan untuk menyertakan tautan ke Try It Online! untuk membantu memverifikasi kode Anda :-)
Giuseppe
1
Jangan ragu untuk menghubungi chat pegolf R juga jika Anda mau; Anda bisa memberi tahu dengan menggunakan @[username]... Saya kira Anda ditarik ke dalam kode golf oleh Robin Ryder ??
Giuseppe
1
142 byte - fungsi anonim baik-baik saja, dan saya membuat beberapa golf lain yang dengan senang hati saya jelaskan
Giuseppe
1
Bagus! Apakah ada alasan yang Anda gunakan -n:n? Saya tidak membaca teorema Tunnel, tetapi bagi saya sepertinya itu n:0akan bekerja dengan baik untuk -1 byte ... Juga, pro tip, jika Anda menekan tombol "tautan" di bagian atas TIO, Anda akan mendapatkan hasil yang bagus. format untuk menyalin dan menempel ke PPCG :-) EDIT: Saya melihat, ada beberapa kasus di mana n:0tidak berfungsi.
Giuseppe
3

Karat - 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]}
  • Gunakan teorema Jerrold B. Tunnell , yang sebenarnya tidak saya mengerti, tetapi sepertinya berhasil.
  • bagilah dengan semua faktor kuadratnya, untuk membuatnya 'bebas persegi', karena dalam makalah-makalah di bawah ini teorema Tunnell dijelaskan hanya untuk bebas-kuadrat.
    • Saya percaya ini mungkin berhasil karena setiap angka kongruen, ketika dikalikan dengan kuadrat, menciptakan angka kongruen yang lebih besar, dan sebaliknya. jadi dengan menguji angka yang lebih kecil, kita dapat memvalidasi yang lebih besar, yang dalam kasus kami adalah n. (semua kotak yang dihapus, dapat dikalikan bersama untuk membuat satu kotak besar).
  • 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
    • dalam kode itu sendiri, empat persamaan telah smooshed menjadi satu, di dalam satu loop, menggunakan modulo untuk genap / ganjil
  • simpan penghitungan hitungan persamaan mana yang cocok n
  • setelah pengulangan, uji rasio penghitungan (per Tunnell)

Lihat juga:

dikoreksi genap / ganjil, terima kasih @Level River St

jangan cerah
sumber
1
oh well, pada saat saya berhasil ini saya hanya melihat jawaban c ++ yang salah ...
don bright
terima kasih Level River St
don bright
3

C ++ (gcc) , 251 234 byte

Terima kasih kepada @arnauld karena menunjukkan kesalahan ketik saya.

-17 byte terima kasih kepada @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;}

Cobalah online!

Mengembalikan 1 jika nkongruen, 0 sebaliknya.

qs2q juga kongruen (algoritme tampaknya terputus pada beberapa angka yang mengandung persegi.

Neil A.
sumber
1
@Arnauld: ah, itu salah ketik di pihak saya. tetap.
Neil A.
1

JavaScript (ES7), 165 byte

Sama seperti jawaban @ NeilA. , ini didasarkan pada teorema Tunnell dan oleh karena itu mengasumsikan bahwa dugaan Birch dan Swinnerton-Dyer adalah benar.

Mengembalikan nilai Boolean.

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

Cobalah online!

Bagaimana?

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

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

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
sumber
1

Ruby , 126 byte

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

Cobalah online!

menemukan tempat untuk menginisialisasi t=1dan memperluas daftar kotak menjadi triplet alih-alih menggunakan quntuk membuat salinan tambahan.

Ruby , 129 byte

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

Cobalah online!

Menggunakan teorema Tunnell seperti jawaban lainnya. Saya menggunakan persamaan tunggal sebagai berikut.

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

Kami memeriksa kasing k=8dan k=32dan memeriksa apakah ada dua kali lebih banyak solusi k=8daripada k=32. Hal ini dilakukan dengan menambahkan k-16ke tsetiap kali kita menemukan solusi. Ini bisa +16 dalam case k=32atau -8 dalam case k=8. Secara keseluruhan angka tersebut kongruen jika tsama dengan nilai awal di akhir fungsi.

Penting untuk menemukan semua solusi untuk persamaan uji. Saya melihat banyak jawaban menguji antara +/- sqrt n. Sangat OK untuk menguji juga di luar batas ini jika membuat kode lebih pendek, tetapi tidak ada solusi yang ditemukan karena sisi kiri persamaan akan melebihi n. Hal yang saya lewatkan pada awalnya adalah bahwa negatif dan positif x,y,zdianggap terpisah. Dengan demikian -3,0,3menghasilkan tiga kotak 9,0,9dan semua solusi harus dihitung secara terpisah (0 harus dihitung sekali dan 9harus dihitung dua kali.)

Kode tidak dikunci

->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
sumber
tentang solusi positif dan negatif, sama di sini, saya membuang-buang waktu untuk melewatkan poin ini!
Xi'an