Menemukan bilangan prima tanpa menggunakan "karakter utama"

21

Tugas Anda, jika Anda memilih untuk menerimanya, adalah menulis program / fungsi yang menerima bilangan bulat N sebagai input. Program / fungsi harus menampilkan / mengembalikan daftar bilangan prima N pertama . Tapi inilah intinya: Anda tidak diperbolehkan menggunakan karakter utama dalam kode Anda. Karakter utama adalah karakter yang titik kode Unicode-nya adalah bilangan prima. Dalam rentang ASCII yang dapat dicetak, ini adalah:

%)+/5;=CGIOSYaegkmq

Tetapi aturan ini juga berlaku untuk karakter non-ASCII jika kode Anda menggunakannya.

  • Input yang valid adalah bilangan bulat N di mana 0 <N <= T , di mana Anda dapat memilih T , tetapi harus lebih besar dari atau sama dengan 10000. T tidak harus terbatas.
  • Untuk input yang tidak valid (bukan bilangan bulat, bilangan bulat di luar kisaran), lempar pengecualian atau hasilkan / tidak menghasilkan apa-apa / null.
  • Integer dengan spasi spasi awal / akhir sebagai input dianggap tidak valid.
  • Integer dengan +karakter tanda sebagai input dianggap tidak valid.
  • Integer dengan nol di depan karena input dianggap valid.
  • Jika bahasa Anda memungkinkan Anda untuk meneruskan bilangan bulat yang sudah diuraikan sebagai input, aturan penguraian di atas (kecuali rentang yang) tidak berlaku, karena int sudah diuraikan.
  • Masukan selalu basis-10.
  • Penggunaan generator prima dan penguji primitif bawaan (ini mencakup fungsi faktorisasi prima) tidak diizinkan.
  • Pembatasan sumber dikenakan pada karakter Unicode, tetapi penghitungan byte untuk skor dapat dalam pengkodean lain jika diinginkan.
  • Outputnya bisa berisi satu baris baru, tetapi ini tidak diperlukan.
  • Jika Anda menampilkan / mengembalikan daftar bilangan prima sebagai string, maka setiap bilangan prima harus dibatasi oleh satu atau beberapa karakter non-digit. Anda dapat memilih pembatas yang Anda gunakan.
  • Ini adalah tantangan , kode terpendek dalam byte menang.

Stack Snippet untuk memverifikasi kode Anda

Anda dapat menggunakan Cuplikan Stack di bawah ini untuk memverifikasi bahwa kode Anda tidak mengandung karakter utama:

var primes=[],max=10000;for(var i=2;i<=max;i++){primes.push(i);}for(var N=2;N<Math.sqrt(max);N++){if(primes.indexOf(N)===-1){continue;}primes=primes.filter(function (x){return x===N||x%N!==0;});}function setText(elem,text){var z=('innerText' in elem)? 'innerText' : 'textContent';elem[z]=text;}function verify(inputCode,resultSpan){var invalidChars=[];var success=true;for(var i=0;i<inputCode.length;i++){var cc = inputCode.charCodeAt(i);if (cc>max){setText(resultSpan,"Uh oh! The char code was bigger than the max. prime number calculated by the snippet.");success = false;break;}if (primes.indexOf(cc)!==-1){invalidChars.push(inputCode[i]);}}if (invalidChars.length===0&&success){setText(resultSpan, "Valid code!");}else if(success) {  var uniqueInvalidChars = invalidChars.filter(function (x, i, self){return self.indexOf(x)===i;});setText(resultSpan, "Invalid code! Invalid chars: " + uniqueInvalidChars.join(""));    }}document.getElementById("verifyBtn").onclick=function(e){e=e||window.event;e.preventDefault();var code=document.getElementById("codeTxt").value;verify(code,document.getElementById("result"));};
Enter your code snippet here:<br /><textarea id="codeTxt" rows="5" cols="70"></textarea><br /><button id="verifyBtn">Verify</button><br /><span id="result"></span>

ProgramFOX
sumber
10
Ini cukup kejam yang ;kebetulan dilarang ...
15ıʇǝɥʇu
Jika penguji primalitas tidak diizinkan, bagaimana dengan fungsi faktorisasi utama.
Maltysen
@Maltysen Dari fungsi faktorisasi utama, Anda dapat dengan cepat melihat apakah angka itu prima atau tidak, jadi saya khawatir itu tidak diizinkan. Saya akan mengklarifikasi itu.
ProgramFOX
Apakah kita diberi mandat untuk membuang beberapa input yang tidak valid ini? Sebagai contoh, jika fungsi string-> int bahasa kita memungkinkan untuk memimpin +, sepertinya mengecewakan diharuskan untuk membuangnya secara manual.
Runer112
11
Saya sangat bersemangat tentang hal ini dan mulai mencari solusi, kemudian menyadari bahwa orangtua yang tertutup tidak diizinkan. Yah, aku keluar.
Alex A.

Jawaban:

10

CJam, 19 18 30 34 33 19 17 21 20 byte

Cobalah online.

{_3\#,2>__ff*:~-<N*}

Ini mungkin salah satu algoritma yang paling tidak efisien yang pernah saya terapkan. Tapi saya melakukannya untuk ukuran!

Jawaban saya terdiri dari blok kode, yang bertindak seperti fungsi anonim di CJam. Jalankan dengan integer segera sebelum itu di stack, dan daftar yang dihasilkan dibuang ke stack. Saya memperlakukan batas atas pada input sebagai tidak terbatas sehingga saya tidak perlu memeriksa batas itu.

Algoritme saya mulai dengan menaikkan 3 inputpangkat ke - th, yang dijamin memberikan angka lebih besar dari input-th prima jika inputnya valid. Kemudian daftar bilangan bulat dari 2 ke angka ini dikurangi satu yang dihasilkan, yang merupakan petak yang cukup besar untuk memuat semua bilangan prima yang kita inginkan. Untuk menghilangkan angka komposit ... huh ... kami membuat daftar setiap produk berpasangan, yang akan menghasilkan semua angka komposit dari 4 hingga nilai yang sangat besar, cukup besar untuk keperluan kita. Maka itu hanya masalah menghapus setiap elemen dari daftar asli yang ada di daftar komposit ini, memangkasnya ke inputelemen pertama , dan bergabung dengan elemen dengan karakter baris baru.

Algoritme harus bekerja untuk input apa pun. Namun, apakah penerjemah / komputer memiliki cukup memori atau waktu adalah pertanyaan lain, karena persyaratan waktu dan ruang bersifat eksponensial sehubungan dengan input. Jadi jika input lebih besar dari sekitar 5 untuk penerjemah online atau sekitar 8 untuk yang offline, maka jawaban untuk pertanyaan itu mungkin tidak.

Runer112
sumber
3
heh, pada 17 Anda memiliki jumlah byte utama dalam jawaban Anda.
Corey Ogburn
Mengapa Anda membutuhkannya S*?
jimmy23013
@ user23013 Masukan tidak valid kurang dari 1 masih diumpankan melalui algoritma, mereka hanya menghasilkan daftar kosong. Tapi itu bukan keluaran yang legal untuk mereka, jadi saya bergabung dengan elemen daftar dengan spasi untuk menghasilkan output kosong untuk input yang tidak valid ini.
Runer112
1
Saya perhatikan ini, bukankah Skarakter utama?
Zacharý
Itu adalah karakter utama. Saya tahu saya terlambat 2 tahun untuk mengatakan ini, tetapi jawaban ini seharusnya tidak valid
Zacharý
8

Jawa. 474 byte

i\u006dport j\u0061v\u0061.util.*\u003bvoid b(int b\u0029{Lon\u0067 c\u003d2L,d,f[]\u003d{}\u003bfor(f\u003dArr\u0061ys.copy\u004ff(f,b\u0029,Arr\u0061ys.fill(f,0L\u0029\u003bb-->0\u003b\u0029for(d\u003d0L\u003bf[b]<1\u003bf[b]\u003dd<1?c:f[b],d\u003d0L,c\u002b\u002b\u0029for(lon\u0067 h:f\u0029d\u003dh>0&&c\u002fh*h\u003d\u003dc?1:d\u003bj\u0061v\u0061x.x\u006dl.bind.JAXB.un\u006d\u0061rsh\u0061l(""\u002bArr\u0061ys.\u0061sList(f\u0029,Lon\u0067.cl\u0061ss\u0029\u003b}

Mengambil input melalui argumen fungsi, output melalui pengecualian yang dibuang.

Bertakuk:

i\u006dport j\u0061v\u0061.util.*\u003b
void b(int b\u0029{
    Lon\u0067 c\u003d2L,d,f[]\u003d{}\u003b
    for(f\u003dArr\u0061ys.copy\u004ff(f,b\u0029,Arr\u0061ys.fill(f,0L\u0029\u003bb-->0\u003b\u0029
        for(d\u003d0L\u003bf[b]<1\u003bf[b]\u003dd<1?c:f[b],d\u003d0L,c\u002b\u002b\u0029
            for(lon\u0067 h:f\u0029
                d\u003dh>0&&c\u002fh*h\u003d\u003dc?1:d\u003b
    j\u0061v\u0061x.x\u006dl.bind.JAXB.un\u006d\u0061rsh\u0061l(""\u002bArr\u0061ys.\u0061sList(f\u0029,Lon\u0067.cl\u0061ss\u0029\u003b
}

Karakter yang dihapus dihapus:

import java.util.*;
void b(int b){
    Long c=2L,d,f[]={};
    for(f=Arrays.copyOf(f,b),Arrays.fill(f,0L);b-->0;)
        for(d=0L;f[b]<1;f[b]=d<1?c:0,d=0L,c++)
            for(long h:f)
                d=h>0&&c/h*h==c?1:d;
    javax.xml.bind.JAXB.unmarshal(""+Arrays.asList(f),Long.class);
}

Penjelasan:

Long c,d,f[]={};                                                //Initialize variables.

for(f=java.util.Arrays.copyOf(f,b),Arrays.fill(f,0L);b-->0;)
    f=java.util.Arrays.copyOf(f,b),Arrays.fill(f,0L)            //Initialize f to an array of 0's.
                                                     b-->0      //Iterate over the first b primes.

for(d=0L;f[b]<1;f[b]=d<1?c:0,d=0L,c++)
    d=0L                        d=0L                            //Initialize d to 0.
         f[b]<1                      c++                        //Increment c while the b'th prime is 0.
                f[b]=d<1?c:0                                    //If d = 0, the b'th prime = c, else continue.

for(long h:f)                                                   //Iterate over all found primes.

d=h>0&&c/h*h==c?1:d;
  h>0                                                           //Ignore non-found primes.
       c/h*h==c                                                 //Equivalent to c%h==0
               ?1:d                                             //If h is prime and c is divisible by h, d = 1. Otherwise d stays unchanged.

javax.xml.bind.JAXB.unmarshal(""+Arrays.asList(f),Long.class)   //Print solution to stderr
javax.xml.bind.JAXB.unmarshal(                   ,Long.class)   //Prints what's contained to stderr.
                                 Arrays.asList(f)               //Convert f to list.
                              ""+                               //Convert to string.

Solusi asli saya menggunakan returnpernyataan. Setelah mengajukan pertanyaan ini pada StackOverflow, regettman cukup berbaik hati untuk menyediakan cara untuk output / kembali tanpa menggunakan huruf utama.

Seperti biasa, saran dipersilahkan :)

TheNumberOne
sumber
3
+1. Itu pasti sangat sulit bagimu dan rgettman untuk mencari tahu. Sangat mengesankan. :)
TNT
5

Ruby, 74

->n,*o{o<<[2..n*n][0].find{|x|!o.find{|y|1.>x.^y.*x.div y}}until o[n-1]
o}

Penjelasan:

*omenginisialisasi array output kosong. sampai memiliki nitem, kami menemukan angka terkecil> = 2 yang tidak membagi item apa pun saat ini o, kemudian menambahkannya ke o. Untuk menguji pembagian, ya. Semua operator yang baik tidak diizinkan, dan saya bahkan tidak bisa menggunakannya divmod. Yang terbaik yang bisa saya lihat adalah menggunakan x.div y, yang mengambil x dibagi dengan y dan dibulatkan, lalu kalikan dengan y lagi. Jika sama dengan x, tidak ada pembulatan, jadi y membagi x. 1.>x.^adalah tes kesetaraan, memeriksa apakah hasil xor adalah 0. .Sebelum setiap operator adalah karena Anda tidak dapat mencampur .panggilan operator-bebas dan metode bebas kurung.

Sunting: Spesifikasi pengecekan jangkauan ditambahkan setelah saya memposting ini, saya kira. Untuk mematuhi diperlukan 79 karakter:

->n,*o{o<<[*2..-~n*n].find{|x|!o.find{|y|1.>x.^y.*x.div y}}until o[n-1]||n<1
o}
histokrat
sumber
4

CJam, 38 37 30 byte

{_~2#,2>\{(\{1$37c~},\p}*'<(~}

Coba di sini

Saya pikir ini harus mematuhi semua aturan dan bekerja untuk N non-negatif (yaitu T tidak terbatas). Ini sangat tidak efisien, jadi jangan mencobanya untuk jumlah yang besar.

Ini adalah blok - hal yang paling dekat dengan fungsi (tanpa nama) - yang mengharapkan integer pada stack, mencetak semua bilangan prima dan meninggalkan stack tanpa inputnya. Untuk semua input yang tidak valid, ia akan melakukan kesalahan atau tidak mencetak apa pun.

Sebagian besar kode adalah validasi input, diikuti oleh saringan Eratosthenes. Saya hanya perlu mengatasi batasan input di 3 tempat:

  • )adalah kenaikan di CJam. Aku membutuhkannya sekali, tetapi bisa menggantinya dengan~ (bitwise komplemen) karena saya mengkuadratkan angka setelahnya.
  • %adalah modulo. saya menggunakan37c~ sebagai gantinya, yang pertama menciptakan karakter %dan kemudian mengevaluasi itu. Ini membuat kode jauh lebih lambat.
  • ;muncul dan membuang elemen dari stack. Saya perlu melakukan ini di akhir. Alih-alih saya menggunakan '<(~yang mendorong karakter <, mengurangi dan mengevaluasi itu.
Martin Ender
sumber
Saya pikir, mengingat semua aturan parsing input, kami tidak diizinkan untuk hanya mengambil integer yang sudah diuraikan.
Runer112
@ Runer112 Kami diizinkan menulis "fungsi yang menerima bilangan bulat". Bukan "fungsi yang menerima representasi string dari integer".
Martin Ender
3

Bash + coreutils, 227 byte

printf -vb br`dc<<<Di14B8209P`
printf -vc -- $[$1-0]
[ "${1#$c}" -o $c -lt 1 ]||{
for i in {2..104729}
{
for f in `jot $[i-1] $[i-1] 1`
{
[ 0 -lt `dc<<<"$i $f~p"` ]||$b
}
[ $f -lt 2 ]&&printf $i\ &&: $[c--]
[ $c -lt 1 ]&&$b
}
}

Ini cukup sulit. Beberapa hal yang saya temui:

  • Sebagian besar loop ( whiledan until) tidak dapat digunakan karena mereka paling dekat dengan doneyang merupakan kata kunci shell dan tidak dapat menjadi hasil dari ekspansi variabel (kecuali evaldigunakan, tetapi itu juga keluar). Satu-satunya loop yang dapat digunakan adalah for/ inyang memungkinkan {/ }bukan do/ done. for (( ; ; ))juga tidak bisa digunakan.
  • = keluar, jadi kita perlu cara lain untuk menetapkan variabel. printf -vbagus untuk ini.
  • Kita tahu bahwa p (10000) adalah 104729 jadi untuk loop luar untuk bilangan prima potensial kita cukup mengulang dari 2 menjadi 104729 dan memecah begitu kita memiliki bilangan prima yang cukup
  • jotmenghasilkan daftar faktor potensial di loop dalam. Jika faktor potensial membagi prime potensial, maka itu tidak prima dan kami keluar lebih awal
  • Untungnya breakadalah shell builtin dan bukan kata kunci, jadi dapat dihasilkan sebagai hasil dari ekspansi. dcmengkonversi nomor base 13 menjadi bytestream eak.
  • Untuk memeriksa apakah faktor potensial membagi potensial prima, kita tidak dapat menggunakan operator aritmatika biasa /atau %shell. Jadi ini diserahkan kepada dcs ~operator, yang mendorong bagi dan sisa ke stack.
  • -lt - kurang dari - adalah satu-satunya operator perbandingan shell yang dapat digunakan.
  • echotidak ada gunanya untuk output. printfbekerja meskipun selama kita hindari%

Mendapatkan validasi input dengan benar sedikit menyebalkan. Ini tidak mengembalikan apa pun jika input tidak valid.

Keluaran:

$ ./primenoprime.sh 10
2 3 5 7 11 13 17 19 23 29 $ 
Trauma Digital
sumber
3

Haskell, 90 byte

\n->[fst c|c<-zip[p|p<-[2..],not$or[b>p-1&&b-1<p|b<-[u*v|u<-[2..p-1],v<-[2..p-1]]]][1..n]]

Ini adalah fungsi anonim yang mengambil integer n sebagai input.

Cara kerjanya: [p|p<-[2..],not$or[b>p-1&&b-1<p|b<-[u*v|u<-[2..p-1],v<-[2..p-1]]]](contoh pertama dari prime-liner nomor satu di wiki Haskell tetapi dengan elemfungsi diganti) membuat daftar bilangan prima yang tak terbatas. zipdengan angka dari 1hingga nuntuk membuat daftar (prime, seq. number)pasangan. Hapus seq. nomor lagi. Hasilnya adalah daftar bilangan prima panjang n.

nimi
sumber
1

Rust, 64897 byte

|n|println!{"{:?}",&[2,3,6-1,7,11,13,17,19,23,29,31,37,41,43,47,60-7,0x3b,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,0x97,0x9d,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,0xfb,0x101 ...}

(kode terpotong karena batas karakter, solusi lengkap di sini )

Fitur karat berikut menjadi tidak tersedia karena batasan utama:

  • panggilan fungsi, karena memerlukan ')'
  • binding reguler, karena mereka membutuhkan let (e)
  • definisi makro, mereka membutuhkan aturan makro! (a, e, m)
  • pernyataan pertandingan, mereka membutuhkan pertandingan (a, m) dan => (=)
  • mutability, karena selalu diperkenalkan dengan kata kunci mut (m).
  • return (e), break (a, e), lanjutkan (e)
  • lain (e)

Apa yang secara teknis dapat Anda gunakan:

  • jika. Tetapi tanpa yang lain, mereka tidak berguna dalam konteks ekspresi, jadi hanya baik untuk efek samping.
  • makro. Makro standar seperti cetak! biasanya diikuti oleh (), tetapi sebenarnya sah untuk menggunakan {} atau [] sebagai gantinya. Tanpa ini, tugas tidak akan mungkin.
  • penutupan, dalam arti paling sempit. Anda tidak dapat memanggil mereka (membutuhkan ()) atau mengikatnya (mengharuskan biarkan), tetapi Anda dapat menentukan satu yang non-rekursif. Tanpa ini, tugas jelas akan menjadi mustahil.
  • struct.
  • untuk loop. Ini menjanjikan, karena mereka benar-benar memungkinkan pengikatan variabel, dan mereka mengambil iterator, yang masih dapat didefinisikan dengan sintaks rentang. Iterator bahkan bisa menjadi ekspresi.
  • Operator bawaan, kecuali +,% dan /. Operator logis hubungan pendek tampak menjanjikan.

Saya tidak bisa membuat apa pun Turing-lengkap dengan alat-alat ini. Maafkan saya. Yang tersisa hanyalah memasukkan 10.000 primes pertama penuh, dibersihkan dari 5's. Setidaknya Anda dapat mengirisnya dan memiliki solusi yang valid, dalam arti sesempit mungkin.

Saya sangat ingin para pakar Turing tarpit diving (atau di Rust!) Memberi tahu saya jika saya bisa melakukan sesuatu yang lebih baik!

Harald Korneliussen
sumber
1

GNU APL, 75 68 67 65 59 56 55 karakter

⎕IOharus 1.

∇z←p n
z←2,j←3
j←j--2
→2×⍳∨⌿1>z|j
z←z,j
→2×⍳n>⍴z
z←n↑z∇

Saya kembali pada bulan ini kemudian menyadari bahwa saya memiliki ruang ekstra!

Zacharý
sumber
Apakah ini dalam pengkodean APL atau UTF-8? Jika Anda mengonversikannya ke pengkodean APL (dan itu valid) itu akan jauh lebih pendek dalam byte.
NoOneIsHere
UTF-8. Ya, tapi pada poin karakter rendah itu, akan ada lebih banyak bilangan prima.
Zacharý
Tepatnya, sekarang byte dihitung dalam APL, tetapi pembatasan sumbernya adalah Unicode. (Saya menyadari tantangannya memungkinkan jumlah byte non-Unicode)
Zacharý
0

Pyth - 12 byte

Gunakan fungsi faktorisasi utama pyth untuk melihat apakah # adalah prima. !tPTTrik penggunaan menyarankan saya pada jawaban saya untuk primes di bawah jutaan masalah.

<f!tPTr2^T6Q

Karena filter hanya berfungsi untuk bilangan prima di bawah n dan bukan yang pertama, saya hanya mencari kebalikan dari pi (x) untuk 10.000 dan mendapatkan 104.000 jadi saya menggunakan bilangan prima di bawah 10⁶ dan mendapatkan n pertama. Ini tidak benar-benar menjalankan, sehingga Anda harus menguji dengan mengganti ^T6dengan ^T3dan membatasi n ke bawah 1000. Masukan dari stdin dan output ke stdout.

<          Q     Slice first n
f     r2^T6      filter on range 2->10⁶
 !               Logical not (gives true if tail is empty)
  t              Tail (all but first, so gives empty if prime fact is len 1)
   PT            Prime factorization of filter var (len 1 if num is prime)
Maltysen
sumber
5
Dari aturan: "Penggunaan generator prima dan penguji primitif bawaan tidak diizinkan."
Runer112
@ Runer112 Ya tapi ini bukan tester primality, adalah faktorisasi utama, ada di perbatasan aturan. Saya mungkin harus bertanya apakah ini diizinkan.
Maltysen
@Maltysen "Penggunaan generator prima bawaan dan penguji primality (ini termasuk fungsi faktorisasi utama) tidak diperbolehkan" - tampaknya cukup jelas bagi saya.
Trauma Digital
4
@DigitalTrauma klarifikasi "(ini termasuk fungsi faktorisasi utama)" ditambahkan setelah jawaban ini diposting
Martin Ender
MartinBüttner Benar. Saya kira kebijakannya hingga @ ProgramFOX'es.
Digital Trauma