Golf pseudoprimes!


9

Pendahuluan / Latar Belakang

Dalam sebuah diskusi baru - baru ini di chat crypto saya ditantang untuk berdiskusi / membantu dengan tes primality Fermat dan angka-angka Carmichael. Tes ini didasarkan pada premis yang a^(p-1) mod p==1akan selalu berlaku untuk bilangan prima p, tetapi tidak selalu untuk komposit. Sekarang nomor carmichael pada dasarnya adalah tes musuh terburuk Fermat: Nomor yang harus Anda pilih auntuk tidak ikut-ikutan pmendapatkannya a^(p-1) mod p!=1. Sekarang jika abukan co-prime, Anda pada dasarnya menemukan faktor non-sepelepdan seperti kita ketahui anjak piutang bisa sangat sulit. Apalagi jika semua faktor cukup besar. Anda sekarang mungkin menyadari mengapa tes Fermat tidak sering digunakan dalam praktik (well, ada algoritma yang lebih baik), itu karena ada angka yang Anda sebagai pembela (dalam hal keamanan) harus melakukan jumlah pekerjaan yang sama seperti seorang penyerang (yaitu faktor nomor).

Jadi sekarang kita tahu mengapa angka-angka ini agak menarik, kita akan menghasilkan mereka dengan cara sesingkat mungkin, jadi kita bisa mengingat kode pembuatan jika kita membutuhkannya!

Nomor Carmichael juga dikenal sebagai A002997 di OEIS .
Sudah ada tantangan terkait , tetapi entri dari sana tidak kompetitif di sini karena mereka dioptimalkan untuk kecepatan dibandingkan dengan ukuran. Argumen yang sama berlaku untuk arah terbalik, entri di sini cenderung membuat trade-off terhadap kecepatan demi ukuran.

Spesifikasi

Memasukkan

Ini adalah tantangan standar , sehingga Anda mengambil bilangan bulat positif atau non-negatif nsebagai input. nmungkin 0 atau 1 diindeks sesuai keinginan Anda (sebutkan).

Keluaran

Output Anda akan menjadi nnomor carmichael -th atau nnomor carmichael pertama , seperti yang Anda inginkan (sebutkan).

Spesifikasi

Integer xadalah nomor Carmichael jika dan hanya jika xkomposit dan untuk semua bilangan bulat ydengan gcd(x,y)=1, itu menyatakan bahwa y^(x-1) mod x==1.

Yang menang?

Ini adalah , jadi kode terpendek dalam byte menang!
IO standar dan aturan celah berlaku.

Uji Kasus

Beberapa angka carmichael pertama adalah:

 561,1105,1729,2465,2821,6601,8911,10585,15841,
 29341,41041,46657,52633,62745,63973,75361,101101,
 115921,126217,162401,172081,188461,252601,278545,
 294409,314821,334153,340561,399001,410041,449065,
 488881,512461

Jawaban:



6

Python 2 , 92 byte

f=lambda j,n=1:j and f(j-([(k/n)**~-n%n for k in range(n*n)if k/n*k%n==1]<[1]*~-n),n+1)or~-n

Cobalah online!

1-diindeks dan lambat sebagai molase.

Dalam pemahaman daftar, saya menggunakan metode Dennis untuk menghasilkan semua bilangan bulat coprime ken ( total n ), dan kemudian saya menghitung x**~-n%nuntuk semuanya. Mari kita sebut daftar ini L.

Untuk mendeteksi nomor Carmichael, saya membandingkan daftar ini secara leksikografis dengan daftar yang terdiri dari n-1satu. Mengapa ini bekerja?

Setiap elemen Ladalah bilangan bulat positif: (k/n)adalah coprime to n, begitu (k/n)**~-njuga adalah, begitu (k/n)**~-n%n > 0. Dengan demikian, satu-satunya nilai yang mungkin dari Lyang secara leksikografis kurang dari [1]*(n-1) yang seluruhnya terdiri dari kurang dari n-1 yang. ( Ltidak dapat berisi lebih dari n-1nilai, karena ntidak dapat memiliki lebih dari n-1total! Jadi, perbandingan seperti tidak [1,1,1,1,3] < [1,1,1,1]ada.)

Memeriksa bahwa ada kurang dari n-1entri dalam Lmemastikan yang nkomposit. (Memiliki n-1jumlah adalah kondisi yang setara dengan primality.) Dan kemudian, kondisi untuk menjadi nomor Carmichael adalah persis bahwa setiap elemen Lsama 1. Jadi perbandingan leksikografis ini mendeteksi dengan tepat apa yang Lkami minati.

Tn. Xcoder menyimpan byte dengan beralih ke formulir lambda rekursif: jmenghitung mundur setiap kali kami menekan nomor Carmichael, dan nmenghitung setiap kali kami melakukan rekursi. Jadi sekali jmencapai nol, n-1sama dengan original_value_of_jangka Carmichael ke-10.


5

Jelly ,  12  11 byte

-1 byte terima kasih kepada miles & Mr. Xcoder (penggunaan atom fungsi Carmichael & golfnya)

%Æc’=ÆP
⁹Ç#

Tautan monadik yang mengambil ndan mengembalikan daftar nnomor Carmichael pertama .

Cobalah online!

Bagaimana?

Sama seperti sebelumnya (di bawah) kecuali bahwa ada built-in untuk fungsi Carmichael - yang menghasilkan daya terkecil sehingga input dinaikkan ke kekuatan itu kongruen dengan satu modulo bahwa daya untuk semua bilangan bulat co-prime ke bilangan bulat itu. Dengan demikian kita dapat mengecualikan false-positif (bilangan prima) dalam lebih sedikit byte dan memiliki kode lebih cepat!

%Æc’⁼ÆP - isCarmichael: number, n (any integer)
 Æc     - Carmicael function of n
%       - n modulo that
   ’    - decremented (0 for Carmichael numbers and primes)
     ÆP - is n prime? (1 for primes 0 otherwise)
    ⁼   - equal?

⁹Ç# - Main link: number, n
  # - count up finding the first n values satisfying:
 Ç  - ...condition: call the last link as a monad
⁹   - ...starting with a value of: literal 256

Sebelumnya 12 bytes :

Ṗ*%⁼Ṗ_ÆP
⁹Ç#

Cobalah online! (Ya, waktunya habis n=3).

Bagaimana?

Angka,, cadalah angka Carmichael jika itu komposit dan memang benar bahwa bilangan bulat mana pun x, dinaikkan ke ckongruen dengan xmodulo c.

Kita hanya perlu memeriksa ini positif xuntuk x=cdirinya sendiri.

Perhatikan juga bahwa pada x=ccek adalah apakah xdinaikkan ke kekuatan xkongruen untuk xmodulo x, yang benar - jadi kita tidak perlu memeriksa ini (ini membuat kode lebih pendek).

Ṗ*%⁼Ṗ_ÆP - Link 1, isCarmichaelNumber: integer c (greater than 1)
Ṗ        - pop c (uses the implicit range(c)) = [1, 2, 3, ..., c-1]
 *       - raise to the power of c (vectorises) = [1^c, 2^c, 3^c, ..., (c-1)^c]
  %      - modulo by c (vectorises) = [1^c%c, 2^c%c, 3^c%c, ..., (c-1)^c%c]
    Ṗ    - pop c = [1, 2, 3, ..., c-1]
   ⁼     - equal? (non-vectorising) = 1 if so, 0 if not
      ÆP - isPrime?(c) = 1 if so, 0 if not
     _   - subtract = 1 if Carmichael 0 if not
         -     (Note the caveat that c must be an integer greater than 1, this is because
         -      popping 1 yields [] thus the equality check will hold; same for 0,-1,...)

⁹Ç# - Main link: number, n
  # - count up finding the first n values satisfying:
 Ç  - ...condition: call the last link as a monad
⁹   - ...starting with a value of: literal 256

Juga 12 byte tetapi menghitung 33 pertama dalam waktu kurang dari satu menit dengan menggunakan atom Carmichael.
mil

11 byte dengan menggunakan fungsi Carmichael bawaan.
Tn. Xcoder

@ Mr.Xcoder saya akan menyarankan mil diposting secara terpisah, kemudian lihat milik Anda kemudian lihat komentar Anda dan hapus. Dv mungkin karena seseorang berpikir itu terlalu mirip dengan mil 'berkomentar satu daripada yang ini, tapi saya pikir bahkan itu adalah alasan aneh karena tidak ada alasan untuk berpikir bahwa Anda tidak menemukan hal yang sama secara mandiri (saya tahu saya' telah melakukan hal semacam itu berkali-kali). Saya akan memposting 11 Anda jika Anda mau, tetapi saya berpendapat Anda atau mil harus mengambil kredit.
Jonathan Allan

@miles too ... ^
Jonathan Allan

@JonathanAllan Cukup poskan sendiri. Sebutkan miles dan kontribusi saya, dan saya juga tidak memikirkan mil :-) (BTW Saya bahkan tidak melihat komentar miles: - / sebelum memposting jawaban saya)
Mr. Xcoder

2

ECMAScript Regex, 86 89 byte

Peringatan: Jangan baca ini jika Anda tidak ingin beberapa sihir regex unary dimanjakan untuk Anda. Jika Anda ingin mencoba mencari tahu sendiri keajaiban ini, saya sangat menyarankan memulai dengan menyelesaikan beberapa masalah di ECMAScript regex: lihat posting ini sebelumnya untuk daftar masalah yang direkomendasikan secara spoiler-taged yang direkomendasikan untuk diselesaikan satu per satu.

^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$))((?=(xx+?)\5*$)(?=(x+)(\6+$))\7(?!\5*$)){2,}x$

Cobalah online!

# Match Carmichael numbers in the domain ^x*$ using Korselt's criterion
# N = input number (initial value of tail)
^
(?!
    # Iterate through factors \1, with \2 = \1-1, for which \2 does not divide into N-1
    (x(x+))
    (?!\2*$)           # Assert N-1 is not divisible by \2
    \1*(?=\1$)         # Assert N is divisible by \1; tail = \1
    # If the factor \1, which already passed the aboved tests, is prime, then fail the
    # outside negative lookahead, because N is not a Carmichael number.
    (?!(xx+)\3+$)
)
# Assert that N has at least 2 unique prime factors, and that all of its prime factors
# are of exactly single multiplicity (i.e. that N is square-free).
(
    (?=(xx+?)\5*$)     # \5 = smallest prime factor of tail
    (?=(x+)(\6+$))     # \6 = tail / \5 (implicitly); \7 = tool to make tail = \6
    \7                 # tail = \6
    (?!\5*$)           # Assert that tail is no longer divisible by \5, i.e. that that
                       # prime factor was of exactly single multiplicity.
){2,}
x$

Keajaiban utama regex ini adalah pada bagian yang menyatakan bahwa semua faktor utama N adalah multiplisitas tunggal. Ini adalah trik yang sama seperti yang digunakan oleh string Match saya yang panjangnya adalah kekuatan keempat dan Find the Smoothest Number regexes: pembagian implisit berulang dengan faktor prima terkecil.

Mungkin juga untuk secara langsung menguji bahwa N tidak memiliki faktor kuadrat sempurna (yaitu, bahwa N bebas kuadrat). Ini menggunakan varian dari algoritma multiplikasi yang dijelaskan secara singkat dalam paragraf dari angka saya yang banyak, posting regex untuk menguji apakah suatu angka adalah kuadrat sempurna. Ini adalah spoiler . Jadi jangan membaca lebih jauh jika Anda tidak ingin beberapa sihir regex unary canggih dimanjakan untuk Anda . Jika Anda ingin mencoba mencari tahu sendiri keajaiban ini, saya sangat menyarankan memulai dengan memecahkan beberapa masalah dalam daftar masalah yang direkomendasikan secara spoiler-tag pada posting sebelumnya , dan mencoba untuk menemukan wawasan matematika secara mandiri.

Namun, menggunakan algoritme itu untuk masalah ini tidak memberikan manfaat apa pun. Ini menghasilkan regex lebih lambat, dengan ukuran lebih besar dari 97 byte. Tanpa uji multiplisitas prima (yang dalam satu loop menegaskan baik bahwa setidaknya ada 2 faktor prima dan bahwa mereka masing-masing multiplisitas tunggal), kita harus secara terpisah menyatakan bahwa N adalah komposit.

^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$)|((xx+)\5*(?=\5$))?(x(x*))(?=(\6*)\7+$)\6*$\8)(xx+)\9+$

Cobalah online!


 ^
 (?!
     # Iterate through factors \1, with \2 = \1-1, for which \2 does not divide into N-1
     (x(x+))
     (?!\2*$)           # Assert N-1 is not divisible by \2
     \1*(?=\1$)         # Assert N is divisible by \1; tail = \1
     # If the factor \1, which already passed the aboved tests, is prime, then fail the
     # outside negative lookahead, because N is not a Carmichael number.
     (?!(xx+)\3+$)
 |
 # Assert that N is square-free, i.e. has no divisor >1 that is a perfect square.
     ((xx+)\5*(?=\5$))?  # cycle tail through all of the divisors of N, including N itself
     # Match iff tail is a perfect square
     (x(x*))             # \6 = potential square root; \7 = \6 - 1
     (?=
         (\6*)\7+$       # iff \6 * \6 == our number, then the first match here must result in \8 == 0
     )
     \6*$\8              # test for divisibility by \6 and for \8 == 0 simultaneously
 )
 (xx+)\9+$               # Assert that N is composite
 


2
(Sebenarnya, ini adalah decision-problemjawaban, tapi tantangannya adalah sequencetantangan.) Mungkin dalam varian regex yang lebih kuat akan ada tes yang lebih langsung untuk pembagi kotak yang tersedia?
Neil

@ Neil Kau benar, aku bisa bermain golf dengan langsung menguji pembagi kuadrat. Di ECMA, tidak ada fitur tambahan yang dibutuhkan. Tapi itu akan membuatnya jauh lebih lambat (dan saya juga ingin menyembunyikannya di bawah tag spoiler). Saya ingin memasukkan kedua versi, saya pikir.
Deadcode

Ya, sangat menjengkelkan menemukan pertanyaan untuk regex yang sudah saya tulis, itu bukan jenis tantangan yang tepat. Haruskah saya menghapus jawaban saya?
Deadcode

@Neil Ini dia. Saya menerapkan algoritma menggunakan ide Anda. Ini mungkin mengapa saya tidak berpikir untuk mengejar itu sendiri; sebenarnya menghasilkan regex yang lebih lama, karena tes is-komposit diperlukan.
Deadcode

(Di bawah aturan situs Anda harus menghapus jawaban Anda, ya.) Ide saya adalah bahwa dengan menggunakan fitur tambahan, katakanlah, Retina regexes, Anda dapat memasukkan golf ke bawah ^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$)|((^x|xx\5){2,})\4*$)(xx+)\6+$, atau mungkin bahkan kurang dari 72 byte.
Neil


1

Retina , 94 byte

\d*$
x
"$+"}/^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$)|((^x|xx\5){2,})\4*$)(xx+)\6+$/^+`$
x
x

Cobalah online! 1-diindeks. Tidak cepat, begitu juga waktu untuk n>5TIO. Penjelasan:

\d*$
x

Tambahkan nilai saat ini. Pada pass pertama, ini juga menghapus ndari buffer output (tetapi $+masih dapat mengaksesnya).

/^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$)|((^x|xx\5){2,})\4*$)(xx+)\6+$/

Uji apakah nilai saat ini adalah angka Carmichael. Ini menggunakan algoritma alternatif @ Deadcode, karena pendeteksian persegi lebih pendek ketika ditulis menggunakan .NET / Perl / PCRE regex.

^+`

Ulangi sampai nilai saat ini adalah angka Carmichael.

$
x

Tambahkan nilai saat ini.

"$+"}

Ulangi kenaikan awal dan di atas nwaktu loop .

x

Ubah hasilnya menjadi desimal.


0

Haskell , 95 byte

s=filter
c n=s(\x->let l=s((1==).gcd x)f;f=[1..x-1]in l/=f&&all(\y->y^(x-1)`mod`x==1)l)[1..]!!n

Cobalah online!

Degolfed:

-- function to filter out Carmichael numbers
filterFunction x = 
    let coprimes = filter ((1 ==) . gcd x) lesserNumbers
        lesserNumbers = [1 .. x - 1]
    in
        -- the number x is Carmichael if it is not prime
        lesserNumbers /= coprimes && 
            -- and all of its coprimes satisfy the equation
            all (\y -> y ^ (x - 1) `mod` x == 1) coprimes

-- get n'th Carmichael number (zero-based)
c n = filter filterFunction [1..] !! n
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.