Rumus pengujian primality

30

Tujuan Anda adalah untuk menentukan apakah angka yang diberikan nprima dalam byte paling sedikit. Tapi, kode Anda harus berupa ekspresi Python 2 tunggal pada angka yang hanya terdiri dari

  • operator
  • variabel input n
  • konstanta bilangan bulat
  • tanda kurung

Tidak ada loop, tidak ada tugas, tidak ada fungsi bawaan, hanya apa yang tercantum di atas. Iya itu mungkin.

Operator

Berikut daftar semua operator di Python 2 , yang termasuk operator aritmatika, bitwise, dan logis:

+    adddition
-    minus or unary negation
*    multiplication
**   exponentiation, only with non-negative exponent
/    floor division
%    modulo
<<   bit shift left
>>   bit shift right
&    bitwise and
|    bitwise or
^    bitwise xor
~    bitwise not
<    less than
>    greater than
<=   less than or equals
>=   greater than or equals
==   equals
!=   does not equal

Semua nilai menengah adalah bilangan bulat (atau Salah / Benar, yang secara implisit sama dengan 0 dan 1). Eksponen tidak boleh digunakan dengan eksponen negatif, karena ini dapat menghasilkan pelampung. Catatan yang /melakukan pembagian lantai, tidak seperti Python 3, jadi //tidak diperlukan.

Bahkan jika Anda tidak terbiasa dengan Python, operator harus cukup intuitif. Lihat tabel ini untuk diutamakan operator dan bagian ini dan di bawah untuk spesifikasi rinci tata bahasa. Anda dapat menjalankan Python 2 di TIO .

I / O

Input: Bilangan bulat positif nminimal 2.

Output: 1 jika nprima, dan 0 sebaliknya. Truedan Falsebisa juga digunakan. Bytes paling sedikit menang.

Karena kode Anda adalah ekspresi, itu akan menjadi potongan, mengharapkan nilai input disimpan n, dan mengevaluasi untuk output yang diinginkan.

Kode Anda harus bekerja untuk nbatas sewenang - wenang yang besar dan sistem. Karena tipe bilangan bulat Python tidak terikat, tidak ada batasan pada operator. Kode Anda mungkin membutuhkan waktu lama untuk dijalankan.

Tidak
sumber
Mungkin ini harus memiliki tag python?
fəˈnɛtɪk

Jawaban:

35

43 byte

(4**n+1)**n%4**n**2/n&2**(2*n*n+n)/-~2**n<1

Cobalah online!

Metode ini mirip dengan jawaban kedua Dennis (dihapus), tetapi jawaban ini lebih mudah dibuktikan benar.

Bukti

Bentuk pendek

Digit paling signifikan (4**n+1)**n%4**n**2dalam basis yang tidak dapat dibagi oleh n akan membuat digit (kurang signifikan) berikutnya dalam bukan nol (jika "digit berikutnya" tidak berada di bagian fraksional), maka a dengan bitmask dieksekusi untuk memeriksa jika ada digit pada posisi ganjil bukan nol.2nn(4**n+1)**n%4**n**2/n&2**(2*n*n+n)/-~2**n

Bentuk panjang

Misalkan menjadi bilangan yang memiliki representasi basis b , yaitu a n b n + + a 1 b 1 + a 0 b 0 , dan a i be the digit at " posisi " i dalam basis b representasi.[an,,a1,a0]bbanbn++a1b1+a0b0aiib

  • .2**(2*n*n+n)/-~2**n=2(2n+1)n1+2n=4n2×2n1+2n=(4n21)×2n1+2n+2n1+2n

Karena (dengann2n-1s) adalah bilangan bulat, dan2n2n×4n211+2n=2n(2n1)×(4n)n14n1=[2n1,0,2n1,0,2n1,0]2nn 2n1, =[2n-1,0,2n-1,0,2n-1,0]2n.2n1+2n=02**(2*n*n+n)/-~2**n[2n1,0,2n1,0,2n1,0]2n

Selanjutnya, pertimbangkan

(4**n+1)**n=(4n+1)n=(n0)40n+(n1)41n++(nn)4n2=[(nn),0,,0,(n1),0,(n0)]2n

, sehinggaakan memotong angka menjadi 2 n digit terakhir - yang tidak termasuk ( n4n2=(2n)2n%4**n**22n (yaitu 1) tetapi termasuk semua koefisien binomial lainnya.(nn)

Tentang /n:

  • Jika adalah bilangan prima, hasilnya adalah [ ( nn. Semua digit pada posisi ganjil adalah nol.[(nn1)/n,0,,0,(n1)/n,0,0]2n

  • Jika bukan bilangan prima:n

    Biarkan menjadi bilangan bulat terbesar sehingga n ( na (n>a>0). Tulis ulang dividen sebagain(na)n>a>0

    [(nn1),0,(nn2),0,,(na+1),0,0,0,,0,0,0]2n+[(na),0,(na1),0,,(n0)]2n

    Puncak pertama memiliki semua digit yang dapat dibagi dengan , dan digit pada posisi 2 a - 1 nol.n2a1

    Sumand kedua memiliki digit paling signifikan (pada posisi ) tidak dapat dibagi dengan n dan (dasar) 2 n > n , sehingga hasil bagi ketika membagi bahwa dengan n akan memiliki digit pada posisi 2 a - 1 bukan nol.2an2n>nn2a1

    Oleh karena itu, hasil akhir ( (4**n+1)**n%4**n**2/n) harus memiliki digit (basis , tentu saja) di posisi 2 a + 1 bukan nol.2n2a+1

Akhirnya, bitwise AND ( &) melakukan bitwise vectorized AND pada digit dalam basis (karena base adalah kekuatan 2), dan karena a & 0 = 0 , a & ( 2 n - 1 ) = a untuk semua 0 a < 2 n , adalah nol iff memiliki semua digit di posisi n pertama ganjil nol - yang setara dengan n menjadi prima.2na&0=0,a&(2n1)=a0a<2n(4**n+1)**n%4**n**2/n&2**(2*n*n+n)/-~2**n(4**n+1)**n%4**n**2/nnn

pengguna202729
sumber
2
Akan (4**n+1)**n%2**n**2/n&2**n**2/-~2**n<1bekerja
Dennis
11
Jika mudah dibuktikan benar, dapatkah Anda memasukkan buktinya dalam jawaban? Kami memiliki MathJax sekarang, sehingga relatif mudah untuk membuat bukti terbaca, dan saya tidak bisa melihat alasan yang jelas untuk pembagian dengan ntidak menyebabkan interaksi yang tidak diinginkan antara basis digit 4**n.
Peter Taylor
3
"Saya telah menemukan bukti yang benar-benar luar biasa dari jawaban ini yang mana komentar ini terlalu kecil untuk dikandung ..."
Digital Trauma
1
Saran untuk memperpendek bukti diterima.
user202729
1
Bagus sekali! Ini adalah solusi yang sama yang saya temukan. Saya menemukan beberapa byte dapat dipotong (4**n+1)**n%4**n**2/n<<n&4**n**2/-~2**n<1. Saya ingin tahu apakah tantangan ini dimungkinkan tanpa operator bitwise.
xnor
6

Python 2 , 56 byte

n**(n*n-n)/(((2**n**n+1)**n**n>>n**n*~-n)%2**n**n)%n>n-2

Cobalah online!

Ini adalah bukti-of-konsep yang tantangan ini bisa dilakukan dengan hanya operator aritmatika, khususnya tanpa bitwise |, &atau ^. Kode ini menggunakan bitwise dan operator perbandingan hanya untuk bermain golf, dan mereka dapat dengan mudah diganti dengan persamaan aritmatika.

Namun, solusinya sangat lambat, dan saya belum dapat menjalankan `, terima kasih kepada eksponen dua tingkat seperti 2 n n .n=62nn

Gagasan utamanya adalah membuat ekspresi untuk faktorial , yang memungkinkan kita melakukan tes primoral Teorema Wilson ( n - 1 ) ! % n > n - 2 di mana % adalah operator modulo.n!(n1)!%n>n2%

Kita dapat membuat ekspresi untuk koefisien binomial , yang terbuat dari faktorial

(mn) =m!n!(mn)!

Tetapi tidak jelas bagaimana cara mengekstrak hanya satu dari faktor-faktor ini. Caranya adalah dengan memalu dengan membuat m benar-benar besar.n!m

(mn) =m(m1)(mn+1)n!=mnn!(11m)(12m)(1n1m)

So, if we let c be the product (11m)(12m)(1n1m), we have

n!=mn(mn)c

If we could just ignore c, we'd be done. The rest of this post is looking how large we need to make m to be able to do this.

c1 from below as m. We just need to make m huge enough that omitting c gives us a value with integer part n! so that we may compute

n!=mn(mn)

For this, it suffices to have 1c<1/n! to avoid the ratio passing the next integer n!+1.

Observe that c is a product of n terms of which the smallest is (1n1m). So, we have

c>(1n1m)n>1n1mn>1n2m,

which means 1c<n2m. Since we're looking to have 1c<1/n!, it suffices to take mn!n2.

In the code, we use m=nn. Since Wilson's Theorem uses (n1)!, we actually only need m(n1)!(n1)2. It's easy to see that m=nn satisfies the bound for the small values and quickly outgrows the right hand side asymptotically, say with Stirling's approximation.

xnor
sumber
3

This answer doesn't use any number-theoretic cleverness. It spams Python's bitwise operators to create a manual "for loop", checking all pairs 1i,j<n to see whether i×j=n.

Python 2, way too many bytes (278 thanks to Jo King in the comments!)

((((((2**(n*n)/(2**n-1)**2)*(2**((n**2)*n)/(2**(n**2)-1)**2))^((n*((2**(n*n-n)/(2**n-1))*(2**((n**2)*(n-1))/(2**n**2-1))))))-((2**(n*n-n)/(2**n-1))*(2**((n**2)*(n-1))/(2**(n**2)-1))))&(((2**(n*(n-1))/(2**n-1))*(2**((n**2)*(n-1))/(2**(n**2)-1)))*(2**(n-1)))==0))|((1<n<6)&(n!=4))

Try it online!

This is a lot more bytes than the other answers, so I'm leaving it ungolfed for now. The code snippet below contains functions and variable assignment for clarity, but substitution turns isPrime(n) into a single Python expression.

def count(k, spacing):
    return 2**(spacing*(k+1))/(2**spacing - 1)**2
def ones(k, spacing):
    return 2**(spacing*k)/(2**spacing - 1)

def isPrime(n):
    x = count(n-1, n)
    y = count(n-1, n**2)
    onebits = ones(n-1, n) * ones(n-1, n**2)
    comparison = n*onebits
    difference = (x*y) ^ (comparison)
    differenceMinusOne = difference - onebits
    checkbits = onebits*(2**(n-1))
    return (differenceMinusOne & checkbits == 0 and n>1)or 1<n<6 and n!=4

Why does it work?

I'll do the same algorithm here in base 10 instead of binary. Look at this neat fraction:

1.09992=1.002003004005

If we put a large power of 10 in the numerator and use Python's floor division, this gives an enumeration of numbers. For example, 1015/(9992)=1002003004 with floor division, enumerating the numbers 1,2,3,4.

Let's say we multiply two numbers like this, with different spacings of zeroes. I'll place commas suggestively in the product.

1002003004×1000000000002000000000003000000000004=
1002003004,002004006008,003006009012,004008012016

The product enumerates, in three-digit sequences, the multiplication table up to 4 times 4. If we want to check whether the number 5 is prime, we just have to check whether 005 appears anywhere in that product.

To do that, we XOR the above product by the number 005005005005, and then subtract the number 001001001001. Call the result d. If 005 appeared in the multiplication table enumeration, it will cause the subtraction to carry over and put 999 in the corresponding place in d.

To test for this overflow, we compute an AND of d and the number 900900900900. The result is zero if and only if 5 is prime.

Lopsy
sumber
1
A quick print of the expression puts this at 278 bytes (though I'm sure a lot of the parenthesises aren't necessary)
Jo King