Mengikuti tradisi pertanyaan yang bagus seperti Temukan prime terbesar yang panjang, jumlah dan produknya prima , ini merupakan varian dari tantangan prime terbesar.
Memasukkan
Kode Anda tidak boleh mengambil input apa pun.
Definisi
Kami mengatakan prima p
adalah good
jika p-1
memiliki 2
faktor prima yang persis berbeda.
Keluaran
Kode Anda harus menampilkan perbedaan absolut antara bilangan prima baik berturut-turut q
dan p
sehingga |q-p|
sebesar mungkin dan q
merupakan bilangan prima terkecil terkecil lebih besar dari p
. Anda dapat menampilkan sejumlah pasangan yang baik dan hasil terakhir Anda akan dianggap sebagai skor.
Contoh
Urutan dari 55 bilangan prima yang baik pertama adalah https://oeis.org/A067466 .
Skor
Skor Anda hanya |q-p|
untuk pasangan bilangan prima bagus yang Anda hasilkan.
Bahasa dan perpustakaan
Anda dapat menggunakan bahasa atau pustaka yang Anda suka (yang tidak dirancang untuk tantangan ini) kecuali untuk fungsi pustaka apa pun untuk pengujian primality atau bilangan bulat anjak piutang. Namun, untuk keperluan penilaian saya akan menjalankan kode Anda di mesin saya jadi tolong berikan instruksi yang jelas untuk bagaimana menjalankannya di Ubuntu.
Mesin Saya Pengaturan waktu akan dijalankan pada mesin saya. Ini adalah instalasi standar Ubuntu pada Prosesor Delapan-Core AMD 8GB 8GB AMD. Ini juga berarti saya harus dapat menjalankan kode Anda.
Detail
- Saya akan membunuh kode Anda setelah 2 menit kecuali mulai kehabisan memori sebelum itu. Karena itu harus memastikan untuk mengeluarkan sesuatu sebelum dipotong.
- Anda tidak boleh menggunakan sumber bilangan prima eksternal.
- Anda dapat menggunakan metode pengujian prima probabilistik meskipun saya diberitahu oleh Mego bahwa dengan tabel yang baik, Miller-Rabin dapat menguji hingga 341.550.071.728.321 (atau bahkan lebih tinggi) secara deterministik. Lihat juga http://miller-rabin.appspot.com/ .
Entri terbaik yang memeriksa semua bilangan bulat dari 1
- 756 oleh kucing di Go
- 756 oleh El'endia Starman dengan Python
- 1932 oleh Adnan di C # (menggunakan mono 3.2.8)
- 2640 oleh yeti di Python (menggunakan pypy 4.01)
- 2754 oleh Reto Koradi di C ++
- 3486 oleh Peter Taylor di Jawa
- 3900 oleh primo dalam RPython (menggunakan pypy 4.01)
- 4176 oleh The Coder in Java
Entri terbaik yang dapat melompati sejumlah besar bilangan bulat untuk menemukan celah besar
- 14226 oleh Reto Koradi di C ++
- 22596 oleh primo dalam RPython (menggunakan pypy 4.01). Rekor tercapai setelah 5 detik!
sumber
Jawaban:
RPython (PyPy 4.0.1), 4032
RPython adalah subset terbatas dari Python, yang dapat diterjemahkan ke C dan kemudian dikompilasi menggunakan RPython Toolchain. Tujuannya adalah untuk membantu dalam menciptakan penerjemah bahasa, tetapi juga dapat digunakan untuk menyusun program-program sederhana.
Untuk mengkompilasi, unduh sumber PyPy saat ini (PyPy 4.0.1), dan jalankan yang berikut:
Eksekusi yang dihasilkan akan diberi nama
good-primes-c
atau serupa di direktori kerja saat ini.Catatan Implementasi
Generator bilangan prima
primes
adalah Saringan Eratosthenes tanpa batas, yang menggunakan roda untuk menghindari kelipatan 2 , 3 , 5 , atau 7 . Itu juga menyebut dirinya secara rekursif untuk menghasilkan nilai berikutnya yang digunakan untuk menandai. Saya cukup puas dengan generator ini. Profil garis mengungkapkan bahwa dua baris paling lambat adalah:jadi saya tidak berpikir ada banyak ruang untuk perbaikan, selain mungkin menggunakan roda yang lebih besar.
Untuk pemeriksaan "kebaikan", pertama semua faktor dua dihapus dari n-1 , menggunakan peretasan-twiddling untuk menemukan kekuatan terbesar dari dua yang merupakan pembagi
(n-1 & 1-n)
. Karena p-1 harus bahkan untuk setiap prima p> 2 , maka 2 harus menjadi salah satu faktor prima yang berbeda. Apa yang tersisa dikirim keis_prime_power
fungsi, yang sesuai dengan namanya. Memeriksa apakah nilai adalah kekuatan utama adalah "hampir bebas", karena hal itu dilakukan bersamaan dengan pemeriksaan primality, dengan paling O (log p n) operasi, di mana p adalah faktor prima terkecil dari n. Divisi percobaan mungkin tampak naif sedikit, tapi dengan pengujian saya itu adalah metode tercepat untuk nilai-nilai kurang dari 2 32 . Saya menghemat sedikit dengan menggunakan kembali roda dari ayakan. Khususnya:dengan mengulangi roda panjang 48,
p*p < n
cek akan dilewati ribuan kali, pada harga rendah, rendah tidak lebih dari 48 operasi modulo tambahan. Itu juga melompati lebih dari 77% dari semua kandidat, daripada 50% dengan hanya mengambil peluang.Beberapa keluaran terakhir adalah:
Kode juga Python yang valid, dan harus mencapai 3588 ~ 3900 ketika dijalankan dengan juru bahasa PyPy baru-baru ini.
RPython (PyPy 4.0.1), 22596
Kiriman ini sedikit berbeda dari yang lain yang diposting sejauh ini, dalam hal ini tidak memeriksa semua bilangan prima yang baik, tetapi malah membuat lompatan yang relatif besar. Salah satu kelemahan dari melakukan ini adalah bahwa saringan tidak dapat digunakan [saya berdiri dikoreksi?] , Jadi kita harus bergantung sepenuhnya pada pengujian primality yang dalam praktiknya sedikit lebih lambat. Ada juga media bahagia yang bisa ditemukan antara tingkat pertumbuhan, dan jumlah nilai yang diperiksa setiap kali. Nilai yang lebih kecil jauh lebih cepat untuk diperiksa, tetapi nilai yang lebih besar lebih cenderung memiliki kesenjangan yang lebih besar.
Untuk menenangkan dewa-dewa matematika, saya telah memutuskan untuk mengikuti urutan Fibonacci, memiliki titik awal berikutnya sebagai jumlah dari dua sebelumnya. Jika tidak ada catatan baru ditemukan setelah memeriksa 10 pasangan, skrip bergerak pada yang berikutnya.
Beberapa keluaran terakhir adalah:
Ketika dikompilasi, integer 64-bit digunakan, meskipun diasumsikan di beberapa tempat bahwa dua integer dapat ditambahkan tanpa overflow, jadi dalam praktiknya hanya 63 yang dapat digunakan. Setelah mencapai 62 bit signifikan, nilai saat ini dibelah dua, untuk menghindari kelebihan dalam perhitungan. Hasilnya adalah bahwa skrip mengocok nilai-nilai pada rentang 2 60 - 2 62 . Tidak melebihi presisi integer asli juga membuat skrip lebih cepat ketika ditafsirkan.
Skrip PARI / GP berikut dapat digunakan untuk mengonfirmasi hasil ini:
sumber
Mungkin 4032, campuran Atkin-Bernstein dan "deterministik" Miller-Rabin
Faktorisasi roda dan bilangan prima yang baik
Sangat jelas bahwa dengan pengecualian 2, 3, dan 5, setiap prime adalah koprime hingga 2 * 3 * 5 = 60. Ada 16 kelas ekivalen modulo 60 yang coprime hingga 60, jadi setiap tes primality hanya perlu memeriksa 16 kasus.
Namun, ketika kita mencari bilangan prima yang "baik", kita bisa semakin menipiskan kawanan. Jika
gcd(x, 60) = 1
, kami menemukan bahwa dalam kebanyakan kasusgcd(x-1, 60)
adalah 6 atau 10. Ada 6 nilaix
yang 2:Oleh karena itu kita dapat melakukan precompute bilangan prima "baik" dari formulir
2^a 3^b + 1
dan2^a 5^b + 1
menggabungkannya menjadi hasil dari generator prima yang hanya menganggap 10% dari bilangan sebagai bilangan prima potensial .Catatan implementasi
Karena saya sudah memiliki implementasi Java dari saringan Atkin-Bernstein yang tergeletak di sekitar, dan yang sudah menggunakan roda sebagai komponen utama, rasanya wajar untuk mengeluarkan jari-jari yang tidak perlu dan mengadaptasi kode. Saya awalnya mencoba menggunakan arsitektur produsen-konsumen untuk mengeksploitasi 8 core, tetapi manajemen memori terlalu berantakan.
Untuk menguji apakah suatu prima adalah prima "baik", saya menggunakan uji Miller-Rabin "deterministik" (yang benar-benar berarti uji Miller-Rabin yang telah diperiksa orang lain terhadap daftar yang dihasilkan secara deterministik). Ini tentu saja dapat ditulis ulang untuk juga menggunakan Atkin-Bernstein, dengan beberapa caching untuk mencakup rentang yang sesuai dengan sqrt, cbrt, dll., Tetapi saya tidak yakin apakah itu akan menjadi peningkatan (karena akan menguji banyak angka yang Saya tidak perlu menguji), jadi itu percobaan untuk hari lain.
Di komputer saya yang cukup lama ini berjalan ke
dalam waktu 2 menit, dan kemudian
masing-masing pada 3:10, 3:20, dan 3:30.
Simpan sebagai
PPCG65876.java
, kompilasi sebagaijavac PPCG65876.java
, dan jalankan sebagaijava -Xmx1G PPCG65876
.sumber
isGood
pemeriksaan.C ++, 2754 (semua nilai, uji primality brute force)
Ini adalah kekuatan kasar, tetapi ini adalah permulaan sebelum matematikawan lokal kami dapat bekerja dengan sesuatu yang lebih efisien.
Saya dapat menambahkan beberapa penjelasan jika perlu, tetapi mungkin sangat jelas dari kode. Karena jika
p
adalah bilangan prima selain 2, kita tahu itup - 1
genap, dan salah satu dari dua faktor itu selalu 2. Jadi kita menghitung bilangan prima, mengurangip - 1
dengan semua faktor 2, dan memeriksa bahwa nilai yang tersisa adalah bilangan prima, atau bahwa semua faktornya adalah prima yang sama.Kode:
Program ini mencetak perbedaan serta dua bilangan prima yang sesuai setiap kali perbedaan maksimum yang baru ditemukan. Sampel keluaran dari uji coba di mesin saya, di mana nilai yang dilaporkan 2754 ditemukan setelah sekitar 1:20 menit:
sumber
C ++, 14226 (hanya nilai tinggi, uji Miller-Rabin)
Memposting ini secara terpisah karena sama sekali berbeda dari solusi awal saya, dan saya tidak ingin sepenuhnya mengganti posting yang telah mendapatkan sejumlah upvotes.
Terima kasih kepada @primo karena menunjukkan masalah dengan versi aslinya. Ada kelebihan untuk jumlah besar dalam tes bilangan prima.
Ini mengambil keuntungan dari beberapa wawasan yang telah diperoleh selama evolusi solusi lain. Pengamatan utama adalah:
Berdasarkan ini, metode yang digunakan di sini cukup sederhana:
Hasil:
Kode:
sumber
PyPy-2.4.0
Python-2
The
x
Files...Episode: "Lihat bu! Bukan satu divisi!"
;-)
Saya mengujinya di Debian8 dengan PyPy-2.4.0 dan Python2 dimulai seperti:
Jika benar-benar ada banyak RAM,
del L[n]
saluran dapat dihapus.Generator bilangan prima dasar adalah ini:
Ini pada dasarnya melakukan apa yang dilakukan saringan Eratosthenes tetapi dalam urutan yang berbeda.
L
adalah kamus tetapi dapat dilihat sebagai daftar (pita) dari daftar angka. Sel yang tidakL[n]
ada ditafsirkan sebagain
tidak memiliki divisi utama yang diketahui sampai sekarang.The
while
Loop melakukan Keputusan yang prima prima atau tidak pada setiap giliran untukL[n]
.Jika
L[n]
ada (sama dengann in L
),P = L[n]
adalah daftar pembagi utama yang berbeda darin
. Jadin
bukan prima.Jika
L[n]
tidak ada, tidak ada pembagi utama yang ditemukan. Jadin
harus prima denganP = [n]
menjadi pembagi yang dikenal.Sekarang
P
adalah daftar pembagi utama yang diketahui untuk kedua kasus.The
for p in P
Loop bergerak setiap masuknyaP
ke depan dengan jarak nilai itu pada tape angka.Ini adalah bagaimana pembagi melompat pada pita dan inilah alasan mengapa nomor melompat ini harus prima. Angka-angka baru hanya terekam dalam kaset berdasarkan
else
keputusan di atas dan angka-angka itu tidak memiliki pembagi yang diketahui selain mereka sendiri. Nonprima tidak pernah masuk ke daftar iniL[n]
.Bilangan prima yang melompat pada daftar semuanya berbeda karena setiap angka
n
hanya dilihat sekali dan hanya ditambahkan sebagai pembagi (jika bukan prime :)0
atau (jika prime :)1
kali. Pembagi utama yang diketahui hanya akan bergerak maju tetapi tidak pernah diduplikasi. JadiL[n]
akan selalu memegang pembagi utama yang berbeda atau akan kosong.Kembali ke program atas untuk mencari celah utama:
... membuat pembagi prima dari
n
dalamB
ketikan
diketahui tidak menjadi perdana.Jika
n
diakui sebagai prima,B
pegang daftar pembagi utama loop pass sebelumnya dengan melihatn-1
:... jadi
len(B) == 2
artinyan - 1
memiliki dua pembagi utama yang berbeda.g
hanya mengingat prime prime terakhir yang terlihat sebelum yang baru,M
adalah panjang dari gap prime maksimum sebelumnya danm
panjang dari gap yang baru ditemukan.Selamat berakhir.
sumber
C #, mungkin 1932
Saya menemukan itu, semakin cepat algoritma Anda untuk menemukan bilangan prima, semakin baik skor Anda. Saya juga cukup yakin bahwa algoritma saya bukan metode yang paling optimal untuk pencarian prima.
sumber
Python 3, 546
... dalam dua menit di komputer saya, yang saya pikir jauh lebih kuat daripada milik Anda.
Saya mungkin bisa membuat ini lebih efisien dengan mengoptimalkan untuk
x=2
kasus ini, tapi eh. Cukup baik. : Psumber
p: 2, q: 3, |q-p|: 1
untuk saya.Pergilah, mungkin 756
Karena malu! Saya seorang pemula sehingga saya dengan naif menggunakan kembali beberapa kode lama dan mengharapkannya bekerja dan cepat! Jika saya menerapkan kembali ini dan benar-benar membangunnya di sekitar bilangan prima yang baik, itu akan jauh lebih cepat, tetapi sayangnya, saya sedang belajar. (Saya mungkin akan menjawab lagi besok dengan solusi yang sepenuhnya dibangun kembali yang dibangun untuk tujuan.)
Jelas, menggunakan konkurensi.
sumber
Java, 4224 (99,29 dtk)
Saringan Eratosthenes yang Sangat Disesuaikan dengan keunggulan BitSet
Waktu yang diperlukan tergantung pada Batas Maks. Dari angka-angka Prime yang akan dihitung
Untuk
sumber
Python 3, 1464
Dengan bantuan dari Lembik , yang idenya adalah hanya memeriksa dua bilangan prima pertama setelah kekuatan dua dan ketika ditemukan segera beralih ke kekuatan dua berikutnya. Jika seseorang dapat menggunakan ini sebagai titik lompatan, jangan ragu. Sebagian dari hasil saya di bawah ini setelah menjalankan ini di IDLE. Kode berikut.
Penghargaan untuk primo ketika saya meraih daftar bilangan prima kecil untuk kode ini.
Edit: Saya telah mengedit kode agar sesuai dengan spesifikasi yang sebenarnya dari masalah (dua pembagi prima yang berbeda tidak persis dua pembagi prima yang berbeda), dan saya dilaksanakan tidak pindah ke kekuatan berikutnya dua sampai baik bilangan prima program ini telah ditemukan memiliki celah lebih besar dari dua bilangan prima baik terakhir yang ditemukannya. Saya juga harus memberikan penghargaan kepada Peter Taylor , karena saya menggunakan idenya bahwa bilangan prima yang baik hanya bisa beberapa nilai mod 60.
Sekali lagi, saya telah menjalankan ini pada komputer yang lambat di IDLE, jadi hasilnya mungkin lebih cepat pada sesuatu seperti PyPy, tapi saya belum bisa memeriksanya.
Contoh hasil saya (p, q, qp, waktu):
Kode saya:
sumber
j
dengan4
bukan2
? Dan Anda tampaknya menolak tanpa syarat jikaj-1
bukan prime times kekuatan dua, di mana Anda harus menguji apakah itu prime power dikalikan kekuatan dua.Go: All Integers: 5112
good.go
:Keluaran:
Sebagai perbandingan: peterSO maks 5112 di 41,04s versus The Coder max 4176 di 51,97s.
Coder: maks | qp | 4176 q 1964330609 p 1964326433
Keluaran:
sumber