Tính số hạng thứ n của chuỗi tự mô tả của Golomb


11

Lấy cảm hứng từ câu hỏi trước .

Trình tự tự mô tả của Golomb g (n) là một chuỗi trong đó bất kỳ số tự nhiên nào nđược lặp lại trong chuỗi g (n) lần.

Một vài số đầu tiên trong chuỗi là:

n    1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20
g(n) 1  2  2  3  3  4  4  4  5  5  5  6  6  6  6  7  7  7  7  8

Bạn có thể thấy g (4) = 3 và "4" được lặp lại 3 lần trong chuỗi.

Cho một đầu vào n, đầu ra g(n).

Hạn chế: n <100000.

Mã nhỏ nhất thắng.


Đối với cách tiếp cận ngây thơ, điều này giống như câu hỏi trước ngoại trừ việc nó sử dụng nchứ không phải 2 - n % 1. Bạn có bất kỳ lý do để mong đợi câu trả lời sẽ khác nhau đáng kể?
Peter Taylor

2
Trong Haskell, bạn có thể sử dụng điều này:golomb=1:2:2:concat(zipWith replicate(drop 2 golomb)[3..])
FUZxxl

@PeterTaylor: Tôi không biết điều đó.
beary605

Câu trả lời:


5

GolfScript (31 ký tự)

~([1 2.]2{.2$=[1$)]*@\+\)}3$*;=

Bản giới thiệu


Đẹp, nhưng bạn đã thực sự thử điều này với n = 99999, và nếu vậy, mất bao lâu? (Khi tôi dùng thử, nó đã chạy trong một giờ trước khi đạt giới hạn bộ nhớ 100 MiB mà tôi đã đặt cho nó và gặp sự cố.)
Ilmari Karonen

@IlmariKaronen, không. Câu hỏi không đặt ra bất kỳ giới hạn nào về hiệu quả bộ nhớ hoặc thời gian, vì vậy tôi cho rằng ràng buộc về kích thước đầu vào là dành cho những ngôn ngữ có ints chiều rộng cố định.
Peter Taylor

6

Thạch , không cạnh tranh

10 byte Câu trả lời này không cạnh tranh, vì thử thách trước khi tạo ra Jelly.

’ßßạ¹ß‘µṖ¡

Điều này sử dụng công thức đệ quy a (1) = 1, a (n + 1) = 1 + a (n + 1 - a (a (n))) từ trang OEIS.

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

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

’ßßạ¹ß‘µṖ¡ Main link. Input: n

’          Decrement; yield n - 1.
 ßß        Recursively call the main link twice, with argument n - 1.
   ạ¹      Take the absolute difference of a(a(n - 1)) and n.
     ß     Recursively call the main link, with argument n - a(a(n - 1)).
      ‘    Increment the result, yielding 1 + a(n - a(a(n - 1))).
       µ   Combine the chain to the left into a single link.
        Ṗ  Pop [1, ..., n]. This yields [] iff n == 1.
         ¡ Execute the chain iff Ṗ returned a non-empty array.

4

PHP - 63 ký tự

function g($n){for(;++$i<=$n;){for(;++$j<=$i;){echo $i;}$j=0;}}

Nhanh và ngắn.

Tôi dường như đã có trình tự sai trong tâm trí. Derp.

Đây là ĐÚNG, nhanh và ngắn.

function g($n){for(;++$i<$n;){echo round(1.201*pow($i,.618));}}

Độ chính xác có thể bị vượt quá mốc 100.000 yêu cầu, nhưng thực tế tôi đã đạt được nhãn hiệu này.


3

PHP

Phiên bản đệ quy này ngắn hơn (60) nhưng tính toán không hiệu quả:

function g($n){return$n==1?1:1+g($n-g(g($n-1)));}echo g($n);

Cái này nhanh hơn nhiều nhưng lâu hơn (78):

$a=[1,2,2];for($i=3;$i<$n;$i++)for($j=0;$j<$a[$i-1];$j++)$a[]=$i;echo$a[$n-1];

Nhanh hơn nhiều, nhưng ở 89 ký tự sẽ là:

$a=[1,2,2];for($i=3;!isset($a[$n-1]);$i++)for($j=0;$j<$a[$i-1];$j++)$a[]=$i;echo$a[$n-1];

Đó là O (n)



3

Oasis , 7 byte (không cạnh tranh)

Mã số:

n<aae>T

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

Oasis là một ngôn ngữ được thiết kế bởi Adnan chuyên về trình tự.

Hiện tại, ngôn ngữ này có thể làm đệ quy và dạng đóng.

Các Tở cuối là viết tắt cho 10, mà chỉ ra rằng a(0) = 0a(1) = 1. Để thêm nhiều testcase, chỉ cần thêm vào danh sách ở cuối.

n<aae>T
n<aae>10  expanded

       0  a(0) = 0
      1   a(1) = 1

n         push n (input)
 <        -1
  a       a(above)  [a is the sequence]
   a      a(above)
    e     a(n-above)
     >    +1

Bây giờ chúng tôi chủ yếu tính toán a(n-a(a(n-1))+1.


2

Perl, 48 ký tự

(@a=(@a,($,)x($a[$,++]||$,)))<$_?redo:say$,for<>

Đầu vào trên stdin, đầu ra cho thiết bị xuất chuẩn. Cần Perl 5.10+ và -M5.010để bật saytính năng này. Mất khoảng thời gian O ( n 2 ) do thao tác mảng không hiệu quả, nhưng vẫn đủ nhanh để dễ dàng tính toán đến kỳ hạn thứ 100.000.


2

Julia - 28

Bằng cách đệ quy :

a(n)=n==1?1:1+a(n-a(a(n-1)))

Đầu ra:

[a(i) for i=1:20]'
1x20 Array{Int64,2}:
 1  2  2  3  3  4  4  4  5  5  5  6  6  6  6  7  7  7  7  8

2

Python - 64 ký tự

n=input()
g=[1,2,2]
for i in range(3,n):g+=[i]*g[i-1]
print g[n]

1
Điều đó thật tuyệt. Tôi không nghĩ làm [i]*g[i-1]sẽ làm điều đó vì vậy tôi cúi xuống để làm theo cách khác; Tôi nghĩ rằng nó sẽ hoạt động giống như nhân một ma trận với vô hướng vì một số lý do ...
chucksmash

1

Javascript, 93 ký tự

c=[,1],i=c.length;function g(n){for(i;i<n;i++) c[i]=g(i);return c[n]||(c[n]=1+g(n-g(g(n-1))))}

1

J, 43 ký tự

f=:3 :'<.@:+&0.5(p^2-p)*y^p-1[p=:(+%)/20$1'

Xác định hàm sử dụng biểu thức tiệm cận được đưa ra trên trang wikipedia.

   f 5
3
   f 20
8
   f 100000
1479

9 ký tự khó chịu được sử dụng chỉ làm tròn đến số nguyên gần nhất.


1

Mở đầu , 69 55 54 byte

?1-(v  #1)-
1   0v ^(#    0 (1+0)#)!
    (#)  ^#1-(0)#

Nếu một trình thông dịch tuân thủ tiêu chuẩn được sử dụng, điều này sẽ lấy đầu vào và đầu ra làm giá trị byte . Để thực sự sử dụng số thập phân trên STDIN / STDOUT, bạn cần thông dịch Python với NUMERIC_OUTPUT = Truevà một tùy chọn bổ sung NUMERIC_INPUT = True.

Giải trình

Bộ xương của chương trình là

?1-(    1 -
1                     )!

Chúng tôi đọc đầu vào Nlên giọng nói đầu tiên và giảm âm lượng để có được N-1. Chúng tôi cũng khởi tạo tiếng nói thứ hai để 1. Sau đó, chúng tôi lặp N-1một lần, mỗi lần lặp lại sẽ nhận giá trị tiếp theo của chuỗi trên ngăn xếp thứ hai. Cuối cùng, chúng tôi in Nsố thứ.

Ý tưởng của chương trình là đặt từng phần tử của chuỗi vào hàng đợi trên giọng nói thứ ba và giảm phần đầu của hàng đợi đó trong mỗi lần lặp. Khi đạt đến đầu 0, chúng ta tăng giá trị của chuỗi và loại bỏ nó 0.

Bây giờ vấn đề là Prelude sử dụng ngăn xếp và không phải hàng đợi. Vì vậy, chúng ta cần thay đổi xung quanh ngăn xếp đó một chút để sử dụng nó như một hàng đợi.

v  #
0v ^
(#)

Điều này sao chép giá trị hiện tại của chuỗi thành giọng nói đầu tiên (dưới dạng bản sao tạm thời), đẩy một 0giọng nói lên giọng nói thứ hai (để đánh dấu sự kết thúc của hàng đợi). Và sau đó thực hiện một vòng lặp để dịch chuyển (và do đó đảo ngược) ngăn xếp thứ ba lên ngăn thứ hai. Sau vòng lặp, chúng tôi đặt bản sao của giá trị chuỗi hiện tại lên trên cùng của ngăn xếp thứ hai (là đuôi của hàng đợi của chúng tôi).

 )
(#
 ^#1-

Điều này có vẻ hơi xấu, nhưng về cơ bản, đó là một vòng lặp để chuyển chồng trở lại giọng nói thứ ba. Vì âm thanh )nằm trong cùng cột với hướng dẫn dịch chuyển, nên 0chúng tôi đã nói giọng nói thứ hai trước đó cũng sẽ kết thúc bằng giọng nói thứ ba, vì vậy chúng tôi cần phải loại bỏ nó bằng giọng nói khác #. Sau đó giảm đỉnh của giọng nói thứ 3, tức là đầu của hàng đợi.

Bây giờ nó có một chút khó chịu - chúng tôi muốn chạy một số mã khi giá trị đó là 0, nhưng cấu trúc điều khiển duy nhất của Prelude (vòng lặp) chỉ đáp ứng với các giá trị khác không.

 0 (1+0)#
(0)#

Lưu ý rằng đỉnh của giọng nói thứ hai là trung thực (vì chuỗi Golomb không chứa bất kỳ 0s nào ). Vì vậy, khối lượng công việc đi vào giọng nói đó (cặp dấu ngoặc đơn sau). Chúng ta chỉ cần ngăn điều đó xảy ra nếu người đứng đầu hàng đợi 0chưa có. Vì vậy, đầu tiên chúng ta có một "vòng lặp" trên giọng nói thứ ba sẽ đẩy một 0giọng nói thứ hai nếu đầu của hàng đợi vẫn khác không. Chúng tôi cũng đặt một 0giọng nói thứ ba để thoát khỏi vòng lặp ngay lập tức. Các #trên giọng nói thứ ba sau đó hoặc là loại bỏ rằng 0, hoặc loại bỏ người đứng đầu của hàng đợi nếu đã là zero. Bây giờ vòng lặp thứ hai chỉ được nhập nếu phần đầu của hàng đợi bằng 0 (và0trên giọng nói thứ hai không bao giờ được đẩy). Trong trường hợp đó, chúng tôi tăng giá trị hiện tại của chuỗi và đẩy a 0để thoát khỏi vòng lặp. Cuối cùng, sẽ luôn có một 0đầu trên ngăn xếp, mà chúng ta cần loại bỏ.

Tôi đã nói với bạn rằng phủ định logic là khó chịu trong Prelude ...


1

Toán học, 27 byte

f@1=1;f@n_:=1+f[n-f@f[n-1]]

Một giải pháp đệ quy khác.


1

CJam, 14 byte

CJam trẻ hơn nhiều so với thử thách này, vì vậy câu trả lời này không đủ điều kiện cho dấu kiểm màu xanh lá cây. Tuy nhiên, khá hiếm khi bạn có thể sử dụng jnó một cách độc đáo, vì vậy tôi vẫn muốn đăng nó.

l~2,{_(jj-j)}j

Kiểm tra nó ở đây.

Giải trình

jvề cơ bản là "toán tử đệ quy ghi nhớ". Nó cần một số nguyên N, một mảng và một khối F. Mảng được sử dụng để khởi tạo sự phân biệt: phần tử tại chỉ mục isẽ được trả về F(i). jsau đó tính toán F(N), bằng cách tìm kiếm nó hoặc bằng cách chạy khối (với ntrên ngăn xếp) nếu giá trị chưa được ghi nhớ. Tính năng thực sự tiện lợi là trong khối, jchỉ lấy một số nguyên ivà gọi F(i)đệ quy. Vì vậy, đây là mã:

l~             "Read and eval input.";
  2,           "Push a 2-range onto the stack, i.e. [0 1]. The first value is irrelevant
                but the second value is the base case of the recursion.";
    {       }j "Compute F(N).";
     _(        "Duplicate i and decrement to i-1.";
       jj      "Compute F(F(i-1)).";
         -     "Subtract from i.";
          j    "Compute F(n-F(F(i-1))).";
           )   "Increment the result.";

1

J, 16 byte

    <:{1($1+I.)^:[~]

    (<:{1($1+I.)^:[~]) every 1+i.20  NB. results for inputs 1..20
1 2 2 3 3 4 4 4 5 5 5 6 6 6 6 7 7 7 7 8

Giải pháp này chủ yếu dựa trên giải pháp của thuật toán cho một vấn đề tương tự. Bạn có thể tìm thấy một số lời giải thích về phương pháp này ở đó.

J, 33 byte

Trong cách tiếp cận này, tôi xây dựng một chuỗi h(k)với các giá trị của các chỉ mục đầu tiên itrong g(i)=kđó như vậy h = 1 2 4 6 9 12 16.... Chúng ta có thể nhận được h(k)khá đơn giản từ h(1..k-1)biểu thức ({:+1+[:+/#<:])có đầu vào h(1..k-1).

Tính toán đầu ra từ hlà đơn giản.h ([:+/]>:[) input

[:+/]>:1 2(,{:+1+[:+/#<:])@]^:[~]

1

Brachylog , 13 byte (không cạnh tranh)

1|-₁↰↰:?-ṅ↰+₁

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

Giải trình

1                Input = 1 = Output
 |               Or
  -₁↰            a(Input - 1)
     ↰           a(a(Input - 1))
      :?-ṅ       Input - a(a(Input - 1))
          ↰      a(Input - a(a(Input - 1))
           +₁    1 + a(Input - a(a(Input -1))

0

Python - 76 ký tự

n=20;g=[1,2,2];[[g.append(i)for j in range(g[i-1])]for i in range(3,n)];g[n]

Điều này thực sự lấp đầy danh sách với một loạt các Nones. Có vẻ là số tiền "chính xác" của Nonetho :)
daniero

1
@Daniero vâng đó là loại mã kỳ lạ. Tôi đã phải chạy nó một vài lần để thuyết phục bản thân nó thực sự hiệu quả. Nó lấp đầy sự hiểu biết danh sách với một loạt các Nones kể từ khi list.append () trả về Nonekiểu. Tôi chỉ sử dụng các hiểu biết danh sách lồng nhau để đạt được một vòng lặp lồng nhau. Mục đích duy nhất của việc hiểu danh sách ở đây là làm cho mã lặp đúng số lần - chúng bị loại bỏ các giá trị
chucksmash

Nó lưu hai ký tự nếu tôi đã thực hiện các vòng lặp lồng truyền thống :)
chucksmash

Thật không may, có vẻ như bạn đang mã hóa dữ liệu đầu vào mà chúng tôi không cho phép và giả sử môi trường REPL sẽ biến điều này thành một đoạn trích. Theo mặc định , tất cả các lần gửi phải là các chương trình hoặc chức năng đầy đủ sử dụng một trong các phương thức I / O mặc định của chúng tôi thay vì đoạn trích. Hãy cho tôi biết nếu bạn có bất kỳ câu hỏi.
Alex A.

@AlexA. Làm một chút khảo cổ học?
chucksmash

0

JavaScript - 48 ký tự

for(g=[,i=j=k=1,2];i<1e5;k=--k?k:g[++j])g[i++]=j

Tạo mảng 1 chỉ mục gchứa các giá trị chuỗi.

Chỉnh sửa - JavaScript - 46 ký tự

v=[,1];for(x=2;x<1e5;)v[x]=1+v[x-v[v[x++-1]]]

Tạo mảng 1 chỉ mục vchứa các giá trị chuỗi.

Chỉnh sửa 2 - ECMAScript 6 - 27 Ký tự

g=x=>x-1?1+g(x-g(g(x-1))):1

Hai cái đầu tiên khá nhanh - thứ ba thì rất chậm


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.