Tạo trình tự hình-hình của Hofstadter


16

Trong Gödel, Escher, Bach , Douglas Hofstadter giới thiệu một chuỗi số nguyên thường được gọi là chuỗi hình:

2, 4, 5, 6, 8, 9, 10, 11, 13, 14, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, ...

Bạn có thể tự mình tìm ra định nghĩa về trình tự như một phần của thử thách, nhưng nếu bạn không thể hoặc không muốn tìm ra nó, bạn có thể tìm thấy nó trên OEIS dưới dạng chuỗi A030124 và định nghĩa rõ ràng hơn một chút trên Wikipedia .

Viết chương trình hoặc hàm, được đưa ra nthông qua STDIN, ARGV hoặc đối số hàm, in danh sách các nsố đầu tiên của chuỗi sang STDOUT theo bất kỳ định dạng danh sách hợp lý nào.

Đây là mã golf, giải pháp ngắn nhất trong byte thắng.

Câu trả lời:


6

CJam, 38 30 29 21 byte

li_3*,2>\{(_pX+:X-}*;

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

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

li                     " Read an integer N from STDIN.              ";
  _3*,2>               " Push S := [ 2 3 ... (N * 3 - 1) ].         ";
        \{        }*   " Do the following N times:                  ";
          (            " Shift an integer I from S.                 ";
           _p          " Print a copy of I, followed by a linefeed. ";
             X+:X      " Execute X += I. (X is initialized to 1.)   ";
                 -     " Remove X from S.                           ";
                    ;  " Discard S from the stack.                  ";

Chạy ví dụ

$ cjam <(echo 'li_3*,2>\{(_pX+:X-}*;') <<< 20
2
4
5
6
8
9
10
11
13
14
15
16
17
19
20
21
22
23
24
25

Bạn đã bỏ lỡ phần mềm quảng cáo khi gõ url cho trình thông dịch
Beta Decay

@BetaDecay thì tại sao không chỉnh sửa để sửa nó;)
Martin Ender

@Martin Tôi không nghĩ mình đã có đủ đại diện ...
Beta Decay

2
@BetaDecay Bạn không, nhưng bạn vẫn có thể đề xuất họ (thậm chí cung cấp cho bạn 2 đại diện nếu họ được chấp nhận).
Martin Ender

Tôi cảm thấy rất thông minh khi chơi golf với 8 byte mã bổ sung. Sau đó, tôi nhận ra rằng bây giờ nó thực hiện giống hệt như câu trả lời từ lịch sử, thảm họa và Peter Taylor ...
Dennis

5

Ruby, 54 48

f=->n{x=1
b=*2..n*n
n.times{b-=[x+=p(b.shift)]}}

Bản giới thiệu

Chỉnh sửa: Đánh gôn này thêm một chút nữa khi tôi nhận ra mình không cần phải giữ toàn bộ chuỗi bổ sung trong bộ nhớ. Đây là cách nó hoạt động ngay bây giờ: Chúng tôi sử dụng xđể theo dõi số lượng tính toán lớn nhất trong chuỗi bổ sung và blà nhóm ứng cử viên cho chuỗi.nlần, chúng ta xuất phần tử nhỏ nhất còn lại vào bvà thêm nó xđể tính số tiếp theo trong chuỗi bổ sung. Sau đó, chúng tôi xóa cả hai số khỏi nhóm ứng cử viên, vì vậy chúng tôi luôn đưa ra số nhỏ nhất chưa được thêm vào một trong hai chuỗi.

Thủ thuật chơi gôn của Ruby: Cú pháp lambda của Stabby ngắn hơn định nghĩa phương thức. Yêu cầu đầu ra được đưa ra cho STDOUT thay vì giá trị trả về đã truyền cảm hứng cho tôi sử dụng thực tế là giá trị trả về p(x)x, điều mà tôi thường không nhớ vì đó không phải là trường hợp trong phiên bản Ruby được sử dụng trong Anarchy Golf.


1
Làm thế nào nó hoạt động?
tự hào

1
FWIW bạn có thể sử dụng 2..2*n. Tôi phải sử dụng n*nvì tôi đang làm việc hiệu quả b = [x]^bnên tôi cần phần tử lớn nhất blớn hơn giá trị lớn nhất x, nhưng bạn b -= [x]chỉ yêu cầu bchứa giá trị lớn nhất có thể có của chuỗi đầu ra.
Peter Taylor

5

Haskell, 67 61 60 56 55 53 ký tự

g n=take n$2:4:h
a#(x:s)=[a..x-2]++x#s
h=5#scanl(+)8h

trở lại thuật toán đầu tiên.

giải pháp này tính toán chuỗi bổ sung bằng cách tính tổng các phần tử bắt đầu của chuỗi. sau đó nó tính toán chuỗi là tất cả các số giữa các số thứ tự của phần bù.

(#)là hàm tính các số giữa dãy bổ sung.
hlà trình tự chính nó.
glà chức năng trả lời câu hỏi.

hàm g được định nghĩa để chỉ lấy số lượng phần tử cần thiết từ h.

sự tinh tế:

hthực sự là chuỗi hình hình ngoại trừ 2 yếu tố đầu tiên.
không phải chuỗi bổ sung được tính toán, mà là chuỗi bổ sung có thêm 1 cho mỗi phần tử.
hai phép tinh tế này là lý do scanl(+)8h(là mã cho chuỗi bổ sung (ngoại trừ 2 phần tử đầu tiên) có thêm 1) có 8trong đó. nó là phần tử thứ ba của chuỗi bổ sung với 1 được thêm vào nó.
Lý do tính toán không thiếu hai yếu tố đầu tiên là vì chúng được thêm gvào 2:4:h.

thí dụ:

>g 50
[2,4,5,6,8,9,10,11,13,14,15,16,17,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,36,37,38,39,40,41,42,43,44,46,47,48,49,50,51,52,53,54,55,57,58,59]

4

GolfScript ( 24 21 byte)

~.3*,1>\{(\(.p@+\|}*;

Bản demo trực tuyến

Điều này bắt đầu hoàn toàn khác, nhưng cuối cùng lại hội tụ vào một cổng GolfScript của giải pháp Ruby của lịch sử trước Dennis đưa ra một số gợi ý đưa nó theo một hướng hơi khác. Cụ thể, in các số khi chúng tôi xác định chúng tiết kiệm khá nhiều so với việc thu thập chúng trong một mảng để in ở cuối; Lý do là điều đó có nghĩa là chúng ta không phải lo lắng về hơn 3 mục trên ngăn xếp.

Mổ xẻ

~.3*,           # Eval input n, dup, multiply by 3, make list [0 1 ... 3n-1]
1>              # Discard 0, which is part of neither sequence
\{              # Execute n times: stack contains pool of numbers not yet seen
                # in either sequence and the first element of it is the next element of the
                # complement sequence
  (\(           #   Pop two numbers from the start of the pool: stack is
                #     pool[0] pool[2..max] pool[1]
  .p            #   Print pool[1]
  @+            #   Rotate pool[0] to top and add to pool[1]
  \|            #   Place pool[0]+pool[1] at the start of the pool and
                #   (this is the clever bit) remove it from later in the pool
}*
;               # Discard the unused remainder of the pool

Nếu bạn thay thế ^bằng \-, bạn có thể thay thế ).*bằng 3*. Điều này sẽ không lưu bất kỳ byte nào, nhưng nó làm giảm đáng kể thời gian chạy và sử dụng bộ nhớ. - Bạn sẽ có thể lưu một byte bằng cách giữ số nguyên trên đầu mảng. Vòng lặp sẽ có cùng số byte, nhưng khởi tạo sẽ ngắn hơn một byte.
Dennis

2
Đặt công việc hợp nhất thậm chí còn tốt hơn so với sự khác biệt:~.3*,1>\{(\(.p@+\|}*;
Dennis

3

J - 28 char

Hàm lấy nlàm đối số.

($+/\(-.~2+i.)&:>:+/)^:_&2 4

Chúng tôi chạy một hàm, với nđối số bên trái, lặp lại đối số bên phải của nó cho đến khi nó không tạo ra thay đổi. Đối số để bắt đầu là danh sách 2 4.

Trong chính hàm này, chúng ta lấy tổng một phần +/\và tổng đầy đủ +/, sau đó tăng cả hai với &:>:. Sau đó, chúng tôi tạo mọi số nguyên từ 2 đến một nhiều hơn tổng tổng ( 2+i.) và đặt trừ ( -.) tổng một phần, để lại một chuỗi hình dài hơn theo định nghĩa. Cuối cùng, chúng tôi rút ngắn hoặc theo chu kỳ mở rộng danh sách theo chiều dài n.

Kết quả là 2 4trở thành3 7 , và điều này được loại bỏ 2..8khỏi 2 4 5 6 8. Sau một vòng khác, 2 4 5 6 8trở 3 7 12 18 26thành

2 4 5 6 8 9 10 11 13 14 15 16 17 19 20 21 22 23 24 25 27

Theo cách này, chúng tôi liên tục mở rộng trình tự hình. Các $hành vi chiều dài chỉ là một tiết kiệm nhân vật cách không tầm thường chờ đợi cho trình tự phát triển theo chiều dài nhoặc cao hơn, và xuất ngiá trị đầu tiên khi họ dừng lại thay đổi. Chúng ta cũng không phải chờ đợi lâu: chúng ta có thể nhận được tới 46336 thuật ngữ từ bốn ứng dụng của động từ bên trong.

Hàm tương tự trong k:

  • k2, 37 ký tự: {{x#y@&~_lin[y:1+!1+/y;1+\y]}[x]/2 4}
  • k4, 36 ký tự: {{x#y@&~(y:2+!1+/y)in\:1+\y}[x]/2 4}

2

Java - 183 158

Đây là lần tôi chơi golf nhiều nhất, và tôi tự hào về điều đó! (Mặc dù nó không ở gần đầu bảng xếp hạng (vì đó là Java))

Cảm ơn Peter Taylor đã góp ý

class f{public static void main(String[]a){int q=1,m=Byte.valueOf(a[0]),w=2,n[]=new int[m*m*2];for(n[q+=w]=1;m-->0;){System.out.println(w);for(;n[++w]>0;);}}}

to hơn -

public class f {
    public static void main(String[] a) {
        int q = 1, m = Byte.valueOf(a[0]), w = 2, n[] = new int[m * m * 2];
        for (n[q += w] = 1; m-- > 0;) {
            System.out.println(w);
            for (; n[++w] > 0;)
                ;
        }
    }
}

Vòng lặp for bên trong đó khá khó hiểu, nhưng tôi nghĩ bạn có thể tiết kiệm được một vài byte. Byte.valueOflưu ba và vì câu hỏi không chỉ định phạm vi đầu vào nên tôi nghĩ nó nên được chấp nhận. Bên ngoài các vòng lặp, mchỉ được sử dụng để khởi tạo n, vì vậy k++<mcó thể m-->0, loại bỏ khoàn toàn. int[] ncó thể được khởi tạo int n[]và sáp nhập vào trình khởi tạo trước đó. nkhông bao giờ giữ các giá trị khác hơn 1, vì vậy n[...]!=0có thể được n[...]>0. Bộ khởi tạo sau đó có thể trở thành phần khởi tạo của forvòng lặp đầu tiên .
Peter Taylor

Và nếu bạn thoát khỏi uvà chỉ sử dụng ++w, không cần phải thiết lập n[q]hoặc n[w]. Có một lỗi, trong đó bạn hết thời ngian m==2, dường như được khắc phục tốt nhất bằng cách khởi tạo n=new int[2*m*m], nhưng tôi nghĩ rằng nó giảm xuống còn 157 byte.
Peter Taylor

Ý tôi là về trình khởi tạo trở thành phần khởi tạo của vòng lặp đầu tiên là for(int q=1,w=2,m=...,n[]=...;m-->0;){...lưu dấu chấm phẩy.
Peter Taylor

1

Python 2 - 77 byte


Mã số:

n=input();x=1;b=range(2,n*n)
while n:v=b.pop(0);x+=v;print v;b.remove(x);n-=1

Hoạt động tương tự như giải pháp của @ histocrat, ngoại trừ đầu vào đến từ stdin.


1

Con trăn 2 - 68

R=[1]
s=0
n=input()
while n:s+=1+(s+1in R);R+=[R[-1]+s];print s;n-=1

0

Thạch , 15 byte

SƤŻ‘µṀ‘Rḟ
2dz¡ḣ

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

Lỗi bộ nhớ ở đầu vào 6.

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

SƤŻ‘µṀ‘Rḟ  Aux. link (monad). Input: part of the desired sequence
SƤŻ‘       Sum of prefixes, then prepend a zero and increment
           This is a list of numbers to exclude from the next iteration
    µ      Re-focus on the above
     Ṁ‘Rḟ  Create range 1..Max + 1, then remove all elements of the above
           +1 is needed to progress from [2] to [2,4]

2dz¡ḣ  Main link (monad). Input: n, number of terms
2dz¡   Starting from 2, apply aux. link n times
    ḣ  Take n elements from the beginning

Phiên bản hiệu quả hơn, 16 byte

SƤŻ‘µṀ‘Rḟḣ³
2ÇÐL

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

Sử dụng một ý tưởng từ câu trả lời J này . Cắt ngắn theo chiều dài mong muốn mỗi lần lặp và lấy điểm cố định. Tôi đã nghĩ sử dụng S(tổng) thay vì Ṁ‘(tối đa 1), nhưng tôi không thể đảm bảo tính chính xác của nó.


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.