Gijswijtのシーケンスのn桁を生成


19

前書き

Gijswijtのシーケンス(A090822)は有名で、本当に遅いです。説明する:

  • 最初の3つは9番目の用語に表示されます(申し分ありません)。
  • 最初の4つは220期目に表示されます(かなり先ですが、実現可能です)。
  • 最初の5つは(ほぼ)10 ^(10 ^ 23)番目の項に表示されます(noのみ)。
  • 最初の6がどこにあるのかさえ、誰も本当に知りません...それがどこにあるのか疑われています...

    2 ^(2 ^(3 ^(4 ^ 5)))番目の項。

2桁の数字を扱う必要はないと想定できます。

シーケンスは次のように生成されます。

  1. 最初の項は1です。
  2. その後の各用語は、それより前の反復「ブロック」の量です(複数の反復「ブロック」がある場合、反復ブロックの最大量が使用されます)。

明確にするために、ここに最初のいくつかの用語があります。

1 -> 1, 1(1つの繰り返しブロック(1)。したがって、記録される数字は1

1, 1 -> 1, 1, 2(2つの繰り返しブロック(1)。したがって、記録される数字は2

1, 1, 2 -> 1, 1, 2, 1(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(2つの繰り返しブロック(1, 1, 2)。したがって、記録される数字は2

仕事

あなたのタスクは、質問で述べたように、Gijswijtシーケンスのn桁を生成することです。

説明書

  • 入力は整数になりnます。
  • コードは、任意の形式(リスト、複数の出力など)で数字を出力できます。

これはコードゴルフであるため、バイト単位の最短コードが優先されます。

回答:


7

Pyth、25 22 21バイト

t_u+eSmtfxG*Td1._GGQN

OPは、1桁の数字のみを処理する必要があることを確認しました。これにより、リストを数字の文字列として保存できました。-> 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

オンラインで試す:デモンストレーション

マーティンとピーターの同じ考えを使用しています。各ステップで、文字列を長さ1の断片に分割し、長さ2の断片に分割します。次に、それらをrange-length-encodeでエンコードし、最初の最大実行を次の番号として使用します。

文字列を含む20バイト

t_u+eSmhhrcGd8SlGGQN

オンラインで試す:デモンストレーション

上記の2つのコードのアイデアを組み合わせます。


1
教えてくれてありがとう。._Pythの関数やその他の便利な関数はいつも忘れています。
漏れの修道女

私はもともとのソリューションが好きでしたが、ええ。
clismique

@ジャクベああ 見てもいいですか?はいの場合、ありがとう!
clismique

@DerpfacePython私の元のソリューションに1バイト追加することができました。また、Martinに基づいたランレングスエンコーディングソリューションを投稿し、2つのアプローチを組み合わせて20バイトのソリューションを生成することができました。
寂部

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

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

Haskell、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

3行目は、整数を受け取り、整数のリストを返す匿名関数を定義します。 実際にご覧ください。

説明

ヘルパー関数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進数の入力を取るバージョンがあります。

テストの目的で、これはわずかな変更で大幅に高速化できます。これにより、入力220を1分以内にテストできます。

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

オンラインでお試しください!10進数バージョン。

さらに大きな数をテストしたい場合は、大量の入力を与えて:、最初のの後に置くことをお勧めします+。これにより、Retinaは、新しい桁の計算を完了するたびに現在のシーケンスを印刷します(すべての桁が1つずつずれる)。

説明

解決策は、結果が変化しなくなるまで繰り返し入力に適用される単一の正規表現置換で構成されます。この場合、正規表現が一致しなくなるために起こります。+冒頭には、このループを紹介しています。これ1は、Retinaに最初の一致のみを置き換えるように指示する制限です(これは最初の反復にのみ関連します)。各反復で、ステージは1つ!(左から)をシーケンスの次の数字に置き換えます。

いつものように、バランスをとるグループの入門書が必要な場合は、SOの回答を参照してください

正規表現の注釈付きバージョンは次のとおりです。目標は、groupで繰り返されるブロックの最大数をキャプチャすること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進数にする必要があることを指定することで、そのことを自由に覆すことができます(この場合、解決策を変更させていただきます)。
マーティンエンダー

ああ、説明してくれてありがとう。ただし、好奇心から、10進数の答えを(コメントに)入れることはできますか?もしそうなら、ありがとう。
clismique

@DerpfacePython 10進入力を使用した個別のリンクを追加しました。
マーティンエンダー

ゴルフをしたときの説明は?
CalculatorFeline

0

ルビー、84バイト

Retinaの回答は、配列内のシーケンスを数えるのではなく、正規表現ベースのソリューションを見つけるように促しましたが、天才の少ない(数量詞を持つ負の後ろ読みはRubyでは許可されていないようですので、とにかくRetinaの答えを直接移植できました)

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

既に生成されたシーケンスを考えるとs、それi1toからs.lengthnこの場合はバイトを節約するために使用されていた)からすべてにマップし、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.