Urutannya terlalu meta

25

Kami mulai dengan urutan kosong 1-diindeks:

_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,...

Pada langkah ke- n , kita mengisi setiap a (n) kosong dengan bilangan bulat lebih besar dari 1 mulai dari sisa kosong pertama, di mana a (n) adalah entri ke- n dalam urutan.

Setelah langkah pertama:

2,_,3,_,4,_,5,_,6,_,7,_,8,_,9,_,10,_,11,_,12,_,13,_,...

Perhatikan bahwa (1) harus 2 karena bilangan bulat pertama lebih besar dari 1 adalah 2.

Pada langkah kedua, kami mengisi setiap (2) kosong. Jelas bahwa a (2) harus 2.

2,2,3,_,4,3,5,_,6,4,7,_,8,5,9,_,10,6,11,_,12,7,13,_,...

Pada langkah ketiga, kami mengisi setiap a (3) kosong. Dari urutan, a (3) = 3.

2,2,3,2,4,3,5,_,6,4,7,_,8,5,9,3,10,6,11,_,12,7,13,_,...

Pada langkah keempat, kami mengisi setiap a (4) kosong. Dari urutan, a (4) = 2.

2,2,3,2,4,3,5,2,6,4,7,_,8,5,9,3,10,6,11,3,12,7,13,_,...

Akhirnya:

2,2,3,2,4,3,5,2,6,4,7,2,8,5,9,3,10,6,11,3,12,7,13,2,...

Tugas

Diberikan n, kembalikan elemen ke- n dari urutan.

10.000.000 syarat pertama dari urutan dapat ditemukan di sini .

Ini adalah . Jawaban terpendek dalam byte menang. Celah standar berlaku.

Biarawati Bocor
sumber
@LuisMendo Terima kasih, saya telah menambahkannya.
Leaky Nun
Hanya ingin tahu, apa salahnya mr. Yang harus dikeluarkan dari urutan?
Dead Possum
@DeadPossum dengan baik, jika Anda mengisi setiap kosong, maka Anda selesai dalam satu langkah.
Leaky Nun
2
@DeadPossum Jika a (n) adalah 1, maka langkah ke-n akan mengisi setiap kosong yang tersisa, mengakhiri generasi.
Leaky Nun
1
@QBrute Saya memberikan daftar 10.000.000 pertama yang ditautkan dalam pertanyaan; plot saja mereka.
Leaky Nun

Jawaban:

20

Haskell , 80 67 byte

g~(a:b)|let k!l=k:take(a-1)l++(k+1)!drop(a-1)l=2!g b
m=g m
(!!)$0:m

Cobalah online!

Haskell adalah bahasa yang sempurna untuk mendefinisikan daftar yang tak terbatas dalam hal dirinya sendiri.

Anders Kaseorg
sumber
1
Mengingat bahwa tautan TIO berfungsi seperti yang diharapkan, saya kira pertanyaan saya seharusnya: Bisakah Anda menambahkan penjelasan tentang cara kerjanya?
Julian Wolf
2
@JulianWolf Sepertinya Anda tidak terbiasa dengan letpenjaga pola. pattern1 | let pattern2 = expr2 = expr1berarti hal yang sama dengan pattern1 = let pattern2 = expr2 in expr1(untuk alasan yang sama yang [expr1 | let pattern2 = expr2]berarti hal yang sama dengan [let pattern2 = expr2 in expr1]).
Anders Kaseorg
1
Saya harus ingat letpenjaga pola (terutama mereka dapat melakukan fungsi)! Juga, m=2:2:2`drop`g msatu byte lebih pendek.
Ørjan Johansen
1
(!!)$0:mlebih pendek dua byte.
Ørjan Johansen
1
Sebenarnya, Anda bisa menjatuhkan 2:2:barang sepenuhnya dengan sedikit lebih malas: g ~(a:b)|...dan m=g m.
Ørjan Johansen
10

C, 123 byte

f(n){int*p=calloc(n,4),i=0,j,k;for(*p=p[1]=2;i<n;++i)for(j=0,k=i/2?0:2-i;j<n;++j)p[j]||k++%p[i]||(p[j]=k/p[i]+2);n=p[n-1];}

Cobalah online!

Panduan

f(n){int*p=calloc(n,4),

Mengalokasikan array n bilangan bulat untuk menyimpan pertama n unsur urutan. Ini sizeof(int)sebagai 4kode hard , yang merupakan asumsi yang aman dalam banyak kasus dan tentu saja saya bersedia membuat dalam konteks kode golf. :)

i=0,j,k;

Ini semua adalah penghitung: iuntuk indeks langkah kita, juntuk mengulangi urutan mencari ruang kosong, dan kuntuk menghitung berapa banyak ruang kosong telah terlihat.

for(*p=p[1]=2;i<n;++i)

Sebelum kita memulai loop utama, kita menyelinap dalam inisialisasi dua elemen pertama dari urutan 2. ( p[0]= *(p + 0)= *p.) Meskipun demikian, ini tidak masuk hitungan k, tapi ...

for(j=0,k=i/2?0:2-i;j<n;++j)

... kami juga melakukan inisialisasi licik dari k, yang menguji untuk melihat apakah ikurang dari 2dan mengoreksi nilai awal kjika demikian. Loop dalam juga dimulai di sini, yang mengulangi seluruh urutan sejauh ini pada setiap langkah.

p[j]||k++%p[i]||(p[j]=k/p[i]+2);

Baris ini benar-benar bisa menggunakan beberapa penjelasan. Kami dapat memperluas ini ke:

if (!(p[j] || ((k++) % p[i]))) {
    p[j] = k / p[i] + 2;
}

oleh hubungan arus pendek, dan kemudian oleh hukum De Morgan dan fakta yang 0salah dalam C:

if (p[j] == 0 && ((k++) % p[i]) == 0) {
    p[j] = k / p[i] + 2;
}

Ini pada dasarnya menyatakan: "jika ruang ini kosong, kenaikan k. Dan jika ksebelumnya merupakan kelipatan dari ukuran langkah, jalankan pernyataan berikut." Oleh karena itu, kami menjalankan pernyataan pada setiap elemen ukuran langkah , yang persis bagaimana urutannya dijelaskan. Pernyataan itu sendiri sederhana; semua itu adalah menghasilkan 2, 3, 4, ....

n=p[n-1];}

Menggunakan tricky-return-without-a-return yang bekerja dengan gcc, kita "mengembalikan" elemen terakhir dari n istilah pertama dalam urutan, yang kebetulan merupakan istilah ke- n .

Gagang pintu
sumber
3

Pyth, 29 byte

M?tH?eJ.DtHg1GghG-tHhJ+2hJ2g1

Cobalah online

Bagaimana itu bekerja

Alih-alih bermain-main dengan daftar, ini menggunakan formula rekursif polos.

M                                def g(G, H):
 ?tH                                 if H - 1:
      J.DtHg1G                           J = divmod(H - 1, g(1, G))
    ?e                                   if J[-1]:
              ghG-tHhJ                       return g(G + 1, H - 1 - J[0])
                                         else:
                      +2hJ                   return 2 + J[0]
                                     else:
                          2              return 2
                           g1Q   print(g(1, eval(input())))
Anders Kaseorg
sumber
3

Haskell , 67 byte

0%j=2
i%j|d<-div i$f j=last$d+2:[(i-d-1)%(j+1)|d*f j<i]
f=(%1).pred

Cobalah online!

Solusi aritmatika rekursif yang ternyata pada dasarnya metode yang sama dengan jawaban Pyth Anders Kaseorg .

Kode ini tercakup dalam kutil - bagian jelek yang kelihatannya bisa di-golf, tapi saya tidak mengerti caranya.

Fungsi ini i%jbenar-benar ingin menggunakan penjaga untuk memeriksa apakah mod i(f j)>0dan mengevaluasi salah satu dari dua ekspresi yang sesuai. Namun, kedua ekspresi tersebut digunakan div i(f j). Mengikatnya di penjaga tidak akan membuatnya berlaku untuk kedua sisi. Sejauh yang saya tahu, seorang penjaga tidak dapat dibuat untuk "mendistribusikan" penjaga lainnya. letdan whereterlalu panjang. Jadi, kode tersebut digunakan lastuntuk memilih satu dari dua ekspresi sementara penjaga mengikat variabel. Ugh.

Idealnya kami akan menggunakan divModkarena keduanya divdan moddigunakan, tetapi (d,m)<-divMod ...adalah ekspresi yang panjang. Kami bukannya memeriksa mod mod bukan nol dengan melihat apakah divnilai kali pembagi kurang dari nilai aslinya.

The 0%j=2kasus tidak akan diperlukan jika Haskell hubung pendek div 0, yang tidak. The .predbertobat 1-diindeks masukan ke nol-diindeks, atau yang lain akan ada -1koreksi di mana-mana.

Tidak
sumber
Jika Anda mengaktifkan %1-diindeks, maka Anda perlu koreksi lima byte - yang hanya mengikat. Namun , Anda kemudian dapat fmasuk %tanpa biaya, dan kemudian fmenjadi anonim sehingga Anda menyimpan dua byte secara keseluruhan.
Ørjan Johansen
@ ØrjanJohansen Apa maksud Anda dengan inline? Saya tidak melihat cara mengubah referensi ftanpa kehilangan byte.
xnor
divModtampaknya satu byte lebih murah, karena memungkinkan percabangan dengan !!(0^m). Sejauh ini saya punya:1%j=2;i%j|(d,m)<-divMod(i-1)$j%1=[(i-d-1)%(j+1),d+2]!!(0^m);(%1)
Ørjan Johansen
Seperti yang Anda lihat, inlining mengandaikan 1-reindexing, yang menghilangkan .pred.
Ørjan Johansen
2

JavaScript (ES6), 98 93 91 byte

Fungsi rekursif yang berhenti segera setelah hasilnya tersedia.

f=(n,p,a=[...Array(n)])=>a[n-1]||f(n,-~p,a.map(c=>c?c:i?i++%(a[p]||2)?c:++v:(i=1,v=2),i=0))

Versi alternatif, 90 byte

Disarankan oleh Shaggy untuk -1 byte

Yang ini harus dipanggil dengan f(n)(). Meskipun pos terkait dalam meta saat ini memberikan skor positif, sintaksis ini tampaknya disengketakan.

n=>g=(p,a=[...Array(n)])=>a[n-1]||g(-~p,a.map(c=>c?c:i?i++%(a[p]||2)?c:++v:(i=1,v=2),i=0))

Demo

Arnauld
sumber
n=>g=(p,a=[...Array(n)])=>a[n-1]||g(-~p,a.map(c=>c?c:i?i++%k?c:++v:(i=1,v=2),i=0,k=a[p]||2))harus bekerja untuk 92 byte. Sebut saja dengan f(n)().
Shaggy
@Shaggy Terima kasih! Ditambahkan sebagai versi alternatif.
Arnauld
1

Java 8, 124 byte

(i)->{int j=1,a[]=new int[i+1],k,s,n;for(;a[i]<2;){for(k=0,n=2;a[++k]>0;);for(s=a[j++]|2*k;k<=i;k+=s)a[k]=n++;}return a[i];}

Ekspresi lambda.

Membuat array integer dan terus-menerus mengisinya sampai nilai n terisi.

Pra-deklarasi variabel di atas untuk mengurangi sebanyak mungkin deklarasi karena masing-masing intbiaya 4 byte ruang dibandingkan dengan menambahkan ,nyang 2.

Pada j'iterasi perhitungan, jumlah' kosong 'yang harus dilewati adalah sama dengan a[j](atau 2, jika kosong). Ternyata jika ruang kosong pertama yang harus kita isi ada di posisi k, k * a[j]beri kami 'langkah' ( s).

Xanderhall
sumber