Trình tự quá meta


25

Chúng tôi bắt đầu với một chuỗi 1 chỉ mục trống:

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

Ở bước thứ n , chúng ta điền vào mỗi khoảng trống a (n) với các số nguyên lớn hơn 1 bắt đầu từ khoảng trống đầu tiên còn lại, trong đó a (n) là mục thứ n trong chuỗi.

Sau bước đầu tiên:

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

Lưu ý rằng a (1) phải là 2 vì số nguyên đầu tiên lớn hơn 1 là 2.

Trong bước thứ hai, chúng tôi điền vào mỗi khoảng trống (2). Rõ ràng là một (2) phải là 2.

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

Trong bước thứ ba, chúng tôi điền vào mỗi khoảng trống (3). Từ dãy, a (3) = 3.

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

Trong bước thứ tư, chúng tôi điền vào mỗi khoảng trống (4). Từ dãy, 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,_,...

Cuối cùng:

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

Bài tập

Cho n, trả về phần tử thứ n của chuỗi.

10.000.000 điều khoản đầu tiên của chuỗi có thể được tìm thấy ở đây .

Đây là . Câu trả lời ngắn nhất trong byte thắng. Tiêu chuẩn áp dụng.


@LuisMendo Cảm ơn, tôi đã thêm nó.
Leaky Nun

Chỉ tò mò, mr.One đã bị loại ra khỏi chuỗi?
Dead Possum

@DeadPossum tốt, nếu bạn điền vào mỗi chỗ trống, thì bạn đã hoàn thành một bước.
Rò rỉ Nun

2
@DeadPossum Nếu a (n) là 1, thì bước thứ n sẽ điền vào mỗi chỗ trống còn lại, chấm dứt thế hệ.
Nữ tu rò rỉ

1
@QBrute Tôi đã cung cấp một danh sách 10.000.000 đầu tiên được liên kết trong câu hỏi; Chỉ cần âm mưu chúng.
Rò rỉ Nun

Câu trả lời:


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

Hãy thử trực tuyến!

Haskell là ngôn ngữ hoàn hảo để xác định một danh sách vô hạn theo chính nó.


1
Cho rằng liên kết TIO hoạt động như mong đợi, tôi đoán câu hỏi của tôi nên thay thế: Bạn có thể thêm một lời giải thích về cách thức hoạt động của nó không?
Julian Wolf

2
@JulianWolf Nghe có vẻ như bạn không quen với những người letbảo vệ mẫu. pattern1 | let pattern2 = expr2 = expr1có nghĩa là điều tương tự như pattern1 = let pattern2 = expr2 in expr1(vì cùng một lý do [expr1 | let pattern2 = expr2]có nghĩa là điều tương tự như [let pattern2 = expr2 in expr1]).
Anders Kaseorg

1
Tôi phải nhớ những người letbảo vệ mẫu (đặc biệt là họ có thể thực hiện các chức năng)! Ngoài ra, m=2:2:2`drop`g mlà một byte ngắn hơn.
Ørjan Johansen

1
(!!)$0:mngắn hơn hai byte.
Ørjan Johansen

1
Trên thực tế, bạn có thể bỏ những 2:2:thứ hoàn toàn với một chút lười biếng hơn: g ~(a:b)|...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];}

Hãy thử trực tuyến!

Hướng dẫn

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

Phân bổ một mảng gồm n số nguyên để lưu trữ n phần tử đầu tiên của chuỗi. Mã hóa cứng nàysizeof(int) như 4, đó là một giả định an toàn trong đa số trường hợp và chắc chắn một trong tôi sẵn sàng thực hiện trong bối cảnh của sân mã. :)

i=0,j,k;

Đây là tất cả các bộ đếm: icho chỉ mục của bước chúng tôi đang thực hiện, jđể lặp qua chuỗi tìm kiếm khoảng trống vàk để đếm xem có bao nhiêu khoảng trống đã được nhìn thấy.

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

Trước khi bắt đầu vòng lặp chính của chúng tôi, chúng tôi lén lút khởi tạo hai yếu tố đầu tiên của chuỗi thành 2. ( p[0]= *(p + 0)= *p.) Điều này làm mất tínhk , nhưng ...

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

... Chúng tôi cũng thực hiện một khởi tạo lén lút k, kiểm tra xem icó nhỏ hơn không 2và sửa giá trị bắt đầu knếu có. Vòng lặp bên trong cũng bắt đầu ở đây, lặp đi lặp lại trên toàn bộ chuỗi cho đến nay trong mỗi bước.

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

Dòng này thực sự có thể sử dụng một số giải thích. Chúng tôi có thể mở rộng này để:

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

bằng cách đoản mạch, và sau đó theo luật của De Morgan và thực tế 0là sai lệch trong C:

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

Điều này về cơ bản nêu rõ: "nếu không gian này trống, hãy tăng lên k. Và nếu ktrước đây là bội số của kích thước bước, hãy chạy câu lệnh sau." Do đó, chúng tôi chạy câu lệnh trên mọi phần tử kích thước bước , đó chính xác là cách trình tự được mô tả. Bản thân tuyên bố là đơn giản; tất cả nó được tạo ra 2, 3,4 , ....

n=p[n-1];}

Sử dụng thủ thuật trả lại khó khăn mà không trả lại hoạt động gcc, chúng tôi "trả lại" phần tử cuối cùng của n thuật ngữ đầu tiên trong chuỗi, đây là thuật ngữ thứ n .


3

Bình thường, 29 byte

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

Dùng thử trực tuyến

Làm thế nào nó hoạt động

Thay vì đánh lừa các danh sách, điều này sử dụng một công thức đệ quy đơn giản.

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())))

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

Hãy thử trực tuyến!

Một giải pháp số học đệ quy hóa ra về cơ bản giống như phương pháp trả lời Pyth của Anders Kaseorg .

Mã này được bao phủ trong mụn cóc - những phần xấu xí trông giống như chúng có thể bị đánh gôn, nhưng tôi không thấy thế nào.

Hàm i%jthực sự muốn sử dụng một bộ bảo vệ để kiểm tra xem mod i(f j)>0và đánh giá một trong hai biểu thức tương ứng. Nhưng, cả hai biểu thức đều sử dụng div i(f j). Liên kết rằng trong một người bảo vệ sẽ không làm cho nó áp dụng cho cả hai bên. Theo như tôi biết, một người bảo vệ không thể được tạo ra để "phân phối" cho những người bảo vệ khác. letwhere quá dài Vì vậy, mã sử dụng lastđể chọn một trong hai biểu thức trong khi bộ bảo vệ liên kết biến. Ừ

Lý tưởng nhất là chúng ta sẽ sử dụng divModvì cả hai divmodđược sử dụng, nhưng (d,m)<-divMod ...là một biểu thức dài. Thay vào đó, chúng tôi kiểm tra chặt chẽ bản mod là khác không bằng cách xemdiv giá trị nhân với số chia có giảm giá trị ban đầu hay không.

Các 0%j=2trường hợp sẽ không cần thiết nếu Haskell ngắn mạch div 0, mà nó không. Việc .predchuyển đổi đầu vào 1 chỉ mục thành không có chỉ mục, hoặc nếu không sẽ có -1sửa chữa ở mọi nơi.


Nếu bạn biến %1 chỉ mục, thì bạn cần hiệu chỉnh năm byte - chỉ cần quan hệ. Tuy nhiên , bạn có thể sau đó inline fvào %miễn phí, và sau đó ftrở thành vô danh vì vậy bạn tiết kiệm được hai byte tổng thể.
Ørjan Johansen

@ RjanJohansen Ý của bạn ở đây là gì? Tôi không thấy cách thay đổi các tham chiếu thành fmà không mất byte.
xnor

divModdường như rẻ hơn một byte, vì nó cho phép phân nhánh với !!(0^m). Cho đến nay tôi đã có:1%j=2;i%j|(d,m)<-divMod(i-1)$j%1=[(i-d-1)%(j+1),d+2]!!(0^m);(%1)
Ørjan Johansen

Như bạn thấy, nội tuyến giả định trước 1-reindexing, loại bỏ .pred.
Ørjan Johansen

2

JavaScript (ES6), 98 93 91 byte

Một hàm đệ quy dừng ngay khi có kết quả.

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))

Phiên bản thay thế, 90 byte

Được đề xuất bởi Shaggy cho -1 byte

Điều này phải được gọi với f(n)(). Mặc dù bài đăng tương ứng trong meta hiện cho điểm số tích cực, cú pháp này rõ ràng đang bị tranh cãi.

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))

Bản giới thiệu


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))nên làm việc cho 92 byte. Gọi nó với f(n)().
Xù xì

@Shaggy Cảm ơn! Đã thêm dưới dạng phiên bản thay thế.
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];}

Biểu hiện Lambda.

Tạo một mảng số nguyên và liên tục cư trú cho đến khi giá trị thứ n được điền.

Các biến khai báo trước ở trên cùng để cắt giảm càng nhiều khai báo càng tốt vì mỗi biến có intgiá 4 byte không gian so với việc thêm vào ,nđó là 2.

Trong jlần lặp lại của phép tính, số lượng 'khoảng trống' người ta phải bỏ qua bằng a[j](hoặc 2, nếu để trống). Nó chỉ ra rằng nếu không gian trống đầu tiên chúng ta phải điền vào vị trí k, k * a[j]cung cấp cho chúng tôi 'bước' ( s).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.