Tạo n chữ số của chuỗi Gijswijt


19

Giới thiệu

Trình tự của Gijswijt ( A090822 ) thực sự nổi tiếng, THỰC SỰ chậm. Để minh họa:

  • 3 đầu tiên xuất hiện trong nhiệm kỳ thứ 9 (ổn).
  • 4 đầu tiên xuất hiện trong nhiệm kỳ thứ 220 (một khoảng cách xa, nhưng khả thi).
  • 5 đầu tiên xuất hiện ở (khoảng) thời hạn 10 ^ (10 ^ 23) (chỉ không có).
  • Không ai thực sự biết 6 người đầu tiên ở đâu ... người ta nghi ngờ đó là ...

    2 ^ (2 ^ (3 ^ (4 ^ 5))) thuật ngữ thứ.

Bạn có thể cho rằng bạn sẽ không phải đối phó với một số có hai chữ số.

Trình tự được tạo như vậy:

  1. Thuật ngữ đầu tiên là 1.
  2. Mỗi thuật ngữ sau đó là số lượng "khối" lặp lại trước đó (nếu có nhiều "khối" lặp lại, số lượng khối lặp lại lớn nhất sẽ được sử dụng).

Để làm rõ, đây là một vài điều khoản đầu tiên.

1 -> 1, 1(một khối lặp lại ( 1), vì vậy chữ số được ghi là 1)

1, 1 -> 1, 1, 2(hai khối lặp lại ( 1), vì vậy chữ số được ghi là 2)

1, 1, 2 -> 1, 1, 2, 1(một khối lặp lại ( 2hoặc 1, 1, 2), vì vậy chữ số được ghi là 1)

1, 1, 2, 1 -> 1, 1, 2, 1, 1 (bạn hiểu ý)

1, 1, 2, 1, 1 -> 1, 1, 2, 1, 1, 2

1, 1, 2, 1, 1, 2 -> 1, 1, 2, 1, 1, 2, 2(hai khối lặp lại ( 1, 1, 2), vì vậy chữ số được ghi là 2)

Bài tập

Nhiệm vụ của bạn là, như đã nêu trong câu hỏi, để tạo ra n chữ số của chuỗi Gijswijt.

Hướng dẫn

  • Đầu vào sẽ là một số nguyên n.
  • Mã của bạn có thể xuất các chữ số dưới bất kỳ hình thức nào (một danh sách, nhiều đầu ra, v.v.).

Đây là mã golf, vì vậy mã ngắn nhất trong byte thắng.

Câu trả lời:


7

Pyth, 25 22 21 byte

t_u+eSmtfxG*Td1._GGQN

OP xác nhận rằng chúng tôi chỉ cần xử lý các số có một chữ số. Điều này cho phép lưu trữ danh sách dưới dạng một chuỗi các chữ số. -> Đã lưu 3 byte

Dùng thử trực tuyến: Trình diễn

Giải trình:

t_u+...GQN      implicit: Q = input number
         N      start with the string G = '"'
  u     Q       do the following Q times:
    ...            generate the next number
   +   G           and prepend it to G
 _              print reversed string at the end
t               remove the first char (the '"')

Và đây là cách tôi tạo số tiếp theo:

eSmtfxG*Td1._G
           ._G    generate all prefixes of G
  m               map each prefix d to:
    f     1          find the first number T >= 1, so that:
       *Td              d repeated T times
     xG                 occurs at the beginning of G
 S                  sort all numbers
e                   take the last one (maximum)   

21 byte với danh sách

_u+eSmhhrcGd8SlGGtQ]1

Dùng thử trực tuyến: Trình diễn

Sử dụng cùng một ý tưởng của Martin và Peter. Ở mỗi bước, tôi chia chuỗi thành các phần có độ dài 1, các phần có độ dài 2, ... Sau đó, tôi mã hóa phạm vi độ dài và sử dụng lần chạy tối đa đầu tiên làm số tiếp theo.

20 byte với chuỗi

t_u+eSmhhrcGd8SlGGQN

Dùng thử trực tuyến: Trình diễn

Kết hợp các ý tưởng của hai mã ở trên.


1
Cảm ơn vì đã dạy cho tôi. Tôi luôn quên ._chức năng và các chức năng hữu ích khác trong Pyth.
Leaky Nun

Cá nhân tôi thích giải pháp ban đầu hơn, nhưng eh.
clismique

@Jakube À. Tôi có thể nhìn được không? Nếu có, thì cảm ơn!
clismique

@DerpfacePython Có thể chơi thêm một byte cho giải pháp ban đầu của tôi. Tôi cũng đã đăng giải pháp mã hóa độ dài chạy dựa trên Martin, và sau đó có thể kết hợp hai cách tiếp cận để tạo ra giải pháp 20 byte.
Jakube

5

CJam, 33 31 30 27 byte

Cảm ơn Peter Taylor đã tiết kiệm 1 byte.

1sri({),:)1$W%f/:e`$W=sc+}

Kiểm tra nó ở đây.

Giải trình

1s      e# Initialise the sequence as "1".
ri(     e# Read input N and decrement.
{       e# For each I from 0 to N-1...
  )     e#   Increment to get I from 1 to N.
  ,     e#   Turn into a range [0 1 ... I-1].
  :)    e#   Increment each element to get [1 2 ... I].
  1$    e#   Copy sequence so far.
  W%    e#   Reverse the copy.
  f/    e#   For each element x in [1 2 ... I], split the (reversed) sequence
        e#   into (non-overlapping) chunks of length x. These are the potentially
        e#   repeated blocks we're looking for. We now want to find the splitting
        e#   which starts with the largest number of equal blocks.
  :e`   e#   To do that, we run-length encode each list blocks.
  $     e#   Then we sort the list of run-length encoded splittings, which primarily
        e#   sorts them by the length of the first run.
  W=    e#   We extract the last splitting which starts with the longest run.
  sc    e#   And then we extract the length of the first run by flattening
        e#   the list into a string and retrieving the first character.
  +     e#   This is the new element of the sequence, so we append it.
}/

+1 cho :) (5 ngày nữa để đi ...)
Leaky Nun

5

CJam ( 30 29 27 24 byte)

'1ri{{)W$W%/e`sc}%$W>+}/

Bản demo trực tuyến

Đây là rất nhiều nỗ lực chung với Martin.

  • Việc sử dụng thông minh mã hóa độ dài chạy ( e`) để xác định các lần lặp lại là của Martin
  • Việc sử dụng W$ để đơn giản hóa việc quản lý ngăn xếp
  • Tôi đã loại bỏ một vài thao tác tăng / giảm bằng cách sử dụng $W>+vỏ đặc biệt, như được giải thích trong phần mổ xẻ dưới đây

Cách tiếp cận 30 byte đầu tiên của tôi:

1ari{,1$f{W%0+_@)</{}#}$W>+}/`

Bản demo trực tuyến

Mổ xẻ

1a        e# Special-case the first term
ri{       e# Read int n and iterate for i=0 to n-1
  ,1$f{   e#   Iterate for j=0 to i-1 a map with extra parameter of the sequence so far
    W%0+  e#     Reverse and append 0 to ensure a non-trivial non-repeating tail
    _@)</ e#     Take the first j+1 elements and split around them
    {}#   e#     Find the index of the first non-empty part from the split
          e#     That's equivalent to the number of times the initial word repeats
  }
  $W>+    e#   Add the maximal value to the sequence
          e#   NB Special case: if i=0 then we're taking the last term of an empty array
          e#   and nothing is appended - hence the 1a at the start of the program
}/
`         e# Format for pretty printing

3

Haskell, 97 byte

f 1=[1]
f n|x<-f$n-1=last[k|k<-[1..n],p<-[1..n],k*p<n,take(k*p)x==([1..k]>>take p x)]:x
reverse.f

Dòng thứ ba định nghĩa một hàm ẩn danh lấy một số nguyên và trả về một danh sách các số nguyên. Xem nó trong hành động.

Giải trình

Hàm trợ giúp fxây dựng chuỗi theo chiều ngược lại, bằng cách kiểm tra đệ quy xem chuỗi trước đó có bắt đầu bằng một khối lặp lại hay không. klà số lần lặp lại, và plà chiều dài của khối.

f 1=[1]                                   -- Base case: return [1]
f n|x<-f$n-1=                             -- Recursive case; bind f(n-1) to x.
  last[k|k<-[1..n],                       -- Find the greatest element k of [1..n] such that
  p<-[1..n],                              -- there exists a block length p such that
  k*p<n,                                  -- k*p is at most the length of x, and
  take(k*p)x                              -- the prefix of x of length p*k
    ==                                    -- is equal to
  ([1..k]>>take p x)                      -- the prefix of length p repeated k times.
  ]:x                                     -- Insert that k to x, and return the result.
reverse.f                                 -- Composition of reverse and f.


1

Võng mạc , 66 60 byte

+1`((\d+)?(?<1>\2)*(?<!\3(?>(?<-1>\3)*)(?!.*\2)(.+)))!
$1$#1

Đầu vào là một số nguyên unary sử dụng ! dưới dạng chữ số (mặc dù có thể thay đổi thành bất kỳ ký tự không phải số nào khác). Đầu ra chỉ đơn giản là một chuỗi các chữ số.

Hãy thử trực tuyến!(Ngoài ra, để thuận tiện, đây là phiên bản lấy đầu vào thập phân. )

Đối với mục đích thử nghiệm, điều này có thể được tăng tốc rất nhiều với một sửa đổi nhỏ, cho phép thử nghiệm đầu vào 220 trong vòng một phút:

+1`((\d+)?(?<1>\2)*(?=!)(?<!\3(?>(?<-1>\3)*)(?!.*\2)(.+)))!
$1$#1

Hãy thử trực tuyến!( Phiên bản thập phân. )

Nếu bạn muốn kiểm tra số lượng lớn hơn nữa, tốt nhất là chỉ cung cấp cho nó một số đầu vào lớn và đặt một : sau đầu tiên +. Điều này sẽ khiến Retina in chuỗi hiện tại mỗi khi nó hoàn thành việc tính toán một chữ số mới (với tất cả các chữ số ngoài từng chữ số).

Giải trình

Giải pháp này bao gồm một thay thế regex duy nhất, được áp dụng cho đầu vào liên tục cho đến khi kết quả dừng thay đổi, trong trường hợp này xảy ra do regex không còn phù hợp. Lúc +bắt đầu giới thiệu vòng lặp này. Các1 là một giới hạn chỉ cho Retina thay thế trận đấu đầu tiên (điều này chỉ phù hợp với lần lặp đầu tiên). Trong mỗi lần lặp, giai đoạn thay thế một! (từ bên trái) bằng chữ số tiếp theo của chuỗi.

Như thường lệ, nếu bạn cần một mồi về các nhóm cân bằng, tôi giới thiệu cho bạn câu trả lời SO của tôi .

Đây là một phiên bản chú thích của regex. Lưu ý rằng mục tiêu là thu được số khối lặp lại tối đa trong nhóm 1.

(                 # Group 1, this will contain some repeated block at the end
                  # of the existing sequence. We mainly need this so we can
                  # write it back in the substitution. We're also abusing it
                  # for the actual counting but I'll explain that below.
  (\d+)?          # If possible (that is except on the first iteration) capture
                  # one of more digits into group 2. This is a candidate block
                  # which we're checking for maximum repetitions. Note that this
                  # will match the *first* occurrence of the block.
  (?<1>\2)*       # Now we capture as many copies of that block as possible
                  # into group 1. The reason we use group 1 is that this captures
                  # one repetition less than there is in total (because the first
                  # repetition is group 2 itself). Together with the outer
                  # (unrelated) capture of the actual group one, we fix this
                  # off-by-one error. More importantly, this additional capture
                  # from the outer group isn't added until later, such that the
                  # lookbehind which comes next doesn't see it yet, which is
                  # actually very useful.
                  # Before we go into the lookbehind note that at the end of the
                  # regex there's a '!' to ensure that we can actually reach the
                  # end of the string with this repetition of blocks. While this 
                  # isn't actually checked until later, we can essentially assume
                  # that the lookbehind is only relevant if we've actually counted
                  # repetitions of a block at the end of the current sequence.

  (?<!            # We now use a lookbehind to ensure that this is actually the
                  # largest number of repetitions possible. We do this by ensuring
                  # that there is no shorter block which can be matched more
                  # often from the end than the current one. The first time this
                  # is true (since, due to the regex engine's backtracking rules,
                  # we start from longer blocks and move to shorter blocks later),
                  # we know we've found the maximum number of repetitions.
                  # Remember that lookbehinds are matched right-to-left, so
                  # you should read the explanation of the lookbehind from
                  # bottom to top.
    \3            # Try to match *another* occurrence of block 3. If this works,
                  # then this block can be used more often than the current one
                  # and we haven't found the maximum number of repetitions yet.
    (?>           # An atomic group to ensure that we're actually using up all
                  # repetitions from group 1, and don't backtrack.
      (?<-1>\3)*  # For each repetition in group 1, try to match block 3 again.
    )
    (?!.*\2)      # We ensure that this block isn't longer than the candidate
                  # block, by checking that the candidate block doesn't appear
                  # right of it.
    (.+)          # We capture a block from the end into group 3.
  )               # Lookbehind explanation starts here. Read upwards.
)
!                 # As I said above, this ensures that our block actually reaches
                  # the end of the string.

Cuối cùng, sau khi hoàn thành xong, chúng tôi viết lại $1(từ đó xóa !) cũng như số lần chụp trong nhóm $#1tương ứng với số lần lặp lại tối đa.


Tại sao Retina có giải pháp đơn phương thay vì số?
clismique

@DerpfacePython Vì nó rẻ hơn và được sự đồng thuận cho phép . Bạn có thể ghi đè lên bằng cách chỉ định rằng đầu vào phải là số thập phân (trong trường hợp đó tôi rất vui lòng thay đổi giải pháp).
Martin Ender

Ah, cảm ơn đã làm rõ. Tuy nhiên, chỉ vì tò mò, bạn có thể đặt (trong các bình luận) một câu trả lời cho số thập phân không? Nếu vậy, cảm ơn.
clismique

@DerpfacePython Đã thêm các liên kết riêng bằng cách sử dụng đầu vào thập phân.
Martin Ender

Giải thích khi tôi chơi golf xong?
Máy

0

Ruby, 84 byte

Câu trả lời Retina đã truyền cảm hứng cho tôi thực hiện một giải pháp dựa trên regex để tìm ra chuỗi tốt nhất thay vì bằng cách nào đó đếm các chuỗi trong một mảng, nhưng với ít thiên tài hơn (những cái nhìn tiêu cực với các bộ lượng hóa dường như không được phép trong Ruby, vì vậy tôi nghi ngờ Tôi có thể trực tiếp chuyển câu trả lời của Retina qua mọi cách)

->n{s='';n.times{s+=(1..n).map{|i|s=~/(\d{#{i}})\1+$/?$&.size/i: 1}.max.to_s};s[-1]}

Đưa ra một chuỗi đã được tạo s, nó ánh xạ tất cả itừ 1đến s.length( nđược sử dụng trong trường hợp này để lưu byte kể từ đó n>=s.length) và sau đó sử dụng biểu thức chính này để giúp tính toán số lần lặp lại của một chuỗi có độ dài i:

/(.{#{i}})\1+$/
/(                 # Assign the following to group 1
  .{#{i}}          # Match `i` number of characters
         )         # End group 1
          \1+      # Match 1 or more repetitions of group 1
             $/    # Match the end of string

Nếu một trận đấu được tìm thấy chiều dài đó, nó tính toán số lần lặp lại bằng cách chia chiều dài của trận đấu cho $&bằng i, chiều dài của dãy con; nếu không tìm thấy kết quả khớp, nó được coi là 1. Sau đó, hàm sẽ tìm thấy số lần lặp lại tối đa từ ánh xạ này và thêm số đó vào cuối chuỗi.

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.