Gijswijt 시퀀스의 n 자리 생성


19

소개

Gijswijt의 시퀀스 ( A090822 )는 정말 정말 느립니다. 설명하기 위해 :

  • 첫 번째 3은 9 번째 용어에 나타납니다.
  • 첫 번째 4 개는 220 번째 용어로 먼 거리에 있지만 실현 가능합니다.
  • 처음 5는 10 ^ (10 ^ 23) 번째 항 ( 대략)에 나타납니다 .
  • 아무도 처음 6이 어디에 있는지 알지 못합니다.

    2 ^ (2 ^ (3 ^ (4 ^ 5))) 번째 항입니다.

두 자리 숫자를 다룰 필요가 없다고 가정 할 수 있습니다.

시퀀스는 다음과 같이 생성됩니다.

  1. 첫 번째 용어는 1입니다.
  2. 그 이후의 각 용어는 이전의 반복 "블록"의 양입니다 (반복되는 "블록"이 여러 개인 경우 가장 많은 양의 반복 블록이 사용됨).

명확히하기 위해 처음 몇 가지 용어가 있습니다.

1 -> 1, 1(반복 블록 하나 ( 1)이므로 기록 된 숫자는 1)

1, 1 -> 1, 1, 2(두 개의 반복 블록 ( 1)이므로 기록 된 숫자는 2)

1, 1, 2 -> 1, 1, 2, 1(반복 블록 하나 ( 2또는 1, 1, 2)이므로 기록 된 숫자는 1)

1, 1, 2, 1 -> 1, 1, 2, 1, 1 (당신은 아이디어를 얻는다)

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

1, 1, 2, 1, 1, 2 -> 1, 1, 2, 1, 1, 2, 2(두 개의 반복 블록 ( 1, 1, 2)이므로 기록 된 숫자는 2)

직무

질문에 명시된 바와 같이 귀하의 작업은 Gijswijt 시퀀스의 n 자리를 생성하는 것입니다.

명령

  • 입력 값은 정수 n입니다.
  • 코드는 숫자를 모든 형식 (목록, 여러 출력 등)으로 출력 할 수 있습니다.

이것은 코드 골프이므로 바이트 단위의 가장 짧은 코드가 이깁니다.

답변:


7

Pyth, 25 22 21 바이트

t_u+eSmtfxG*Td1._GGQN

OP는 한 자리 숫자 만 처리하면된다는 것을 확인했습니다. 이를 통해 목록을 문자열로 저장할 수있었습니다. -> 3 바이트 저장

온라인으로 사용해보십시오 : 데모

설명:

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

그리고 다음 숫자를 생성하는 방법은 다음과 같습니다.

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 바이트

_u+eSmhhrcGd8SlGGtQ]1

온라인으로 사용해보십시오 : 데모

Martin과 Peter의 동일한 아이디어를 사용합니다. 각 단계에서 문자열을 길이 1 조각, 길이 2 조각으로 나눕니다 ... 그런 다음 길이를 길이로 인코딩하고 최대 첫 실행을 다음 숫자로 사용합니다.

문자열이있는 20 바이트

t_u+eSmhhrcGd8SlGGQN

온라인으로 사용해보십시오 : 데모

위의 두 코드의 아이디어를 결합합니다.


1
가르쳐 주셔서 감사합니다. 나는 항상 ._Pyth 의 기능과 다른 유용한 기능을 잊어 버렸습니다.
Leaky Nun

나는 개인적으로 원래 솔루션을 더 좋아했지만 어.
clismique

@ 자쿠 베 아. 좀 봐도 돼? 그렇다면 감사합니다!
clismique

@DerpfacePython 원래 솔루션에 1 바이트를 더 추가 할 수있었습니다. 또한 Martin을 기반으로 실행 길이 인코딩 솔루션을 게시 한 다음 두 가지 접근 방식을 결합하여 20 바이트 솔루션을 생성 할 수있었습니다.
Jakube

5

CJam, 33 31 30 27 바이트

1 바이트를 절약 해 준 Peter Taylor에게 감사합니다.

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

여기에서 테스트하십시오.

설명

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 : +5 (가는 것이 5 개 더 있습니다.)
Leaky Nun

5

CJam ( 30 29 27 24 바이트)

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

온라인 데모

이것은 Martin과의 공동 노력입니다.

  • e`반복을 식별하기 위해 실행 길이 인코딩 ( )을 영리하게 사용 하는 것은 Martin의 것입니다.
  • 따라서 W$스택 관리를 단순화 하는 데 사용 됩니다
  • $W>+아래 절에서 설명한대로 특수 케이스 를 사용하여 몇 가지 증감 작업을 제거했습니다.

내 첫 30 바이트 접근 방식 :

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

온라인 데모

해부

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

하스켈, 97 바이트

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

세 번째 줄은 정수를 사용하고 정수 목록을 반환하는 익명 함수를 정의합니다. 실제로 참조하십시오.

설명

도우미 함수 f는 이전 시퀀스가 ​​반복 블록으로 시작하는지 여부를 재귀 적으로 확인하여 시퀀스를 역순으로 구성합니다. k반복 횟수이며 p블록의 길이입니다.

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

망막 , 66 60 바이트

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

입력은 !숫자로 사용하는 단항 정수입니다 (비 숫자가 아닌 다른 문자로 변경 될 수 있음). 출력은 단순히 문자열입니다.

온라인으로 사용해보십시오! (또는 편의상 여기에 10 진수를 입력하는 버전이 있습니다. )

테스트 목적으로, 이것은 약간의 수정 으로 많은 속도를 낼 수 있으며 , 1 분 안에 입력 220을 테스트 할 수 있습니다.

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

온라인으로 사용해보십시오! ( 십진수 버전. )

더 큰 숫자를 테스트하려면 대량의 입력을 공급 :하고 초기 다음에을 넣는 것이 가장 좋습니다 +. 이렇게하면 새로운 숫자 계산이 끝날 때마다 Retina가 현재 시퀀스를 인쇄합니다 (모든 숫자가 하나씩 해제 됨).

설명

솔루션은 단일 정규식 대체로 구성되며 결과가 변경을 멈출 때까지 반복적으로 입력에 적용됩니다.이 경우 정규식이 더 이상 일치하지 않기 때문에 발생합니다. +처음에이 루프를 소개합니다. 는 1(이것은 매우 첫 번째 반복 만 관련) 망막은 첫 경기를 교체 알려주는 한계입니다. 각 반복에서 스테이지는 하나의 !(왼쪽에서) 시퀀스의 다음 숫자로 바뀝니다 .

평소와 같이 밸런싱 그룹에 대한 입문서가 필요하면 SO 답변을 참조하십시오 .

다음은 주석이 달린 정규식 버전입니다. 목표는 그룹에서 최대 반복 블록 수를 캡처하는 것입니다 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.

마지막으로,이 작업이 모두 끝나면 그룹의 캡처 횟수와 최대 반복 횟수에 해당하는 캡처 수를 다시 기록합니다 $1(따라서 !) $#1.


왜 Retina는 숫자 대신 단항 솔루션을 사용합니까?
clismique

@DerpfacePython 저렴 하고 합의에 의해 허용 되기 때문 입니다. 입력을 10 진수 로 지정하면 자유롭게 해결할 수 있습니다 (이 경우 솔루션을 변경하게되어 기쁩니다).
Martin Ender

아, 설명해 주셔서 감사합니다. 하지만 궁금한 점이 있다면 10 진수에 대한 답을 주석에 넣을 수 있습니까? 그렇다면 감사합니다.
clismique

@DerpfacePython 10 진수 입력을 사용하여 별도의 링크를 추가했습니다.
Martin Ender

골프를 다했을 때의 설명?
CalculatorFeline

0

루비, 84 바이트

Retina의 대답은 배열에서 시퀀스를 계산하는 대신 최상의 시퀀스를 찾기 위해 정규식 기반 솔루션을 만들도록 영감을 주었지만 천재는 적습니다 (양자화가있는 음수 모양은 루비에서는 허용되지 않는 것 같습니다. 어쨌든 Retina의 답변을 직접 포팅 할 수 있습니다)

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

이미 생성 된 시퀀스가 ​​주어지면 s모든 ifrom 1에서 s.length( n이 경우 바이트를 절약하기 위해 사용되었습니다)에 매핑 n>=s.length한 다음이 정규 표현식을 사용하여 길이가있는 하위 시퀀스의 반복 횟수를 계산합니다 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

일치하는 그 길이가 발견되면, 그것은 주어진 매치의 길이로 나누어 반복 수를 계산 $&하여 i서브 시퀀스의 길이; 일치하는 것이 없으면로 취급됩니다 1. 그러면 함수는이 매핑에서 최대 반복 횟수를 찾아 해당 숫자를 문자열 끝에 추가합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.