产生Gijswijt序列的n位数字


19

介绍

Gijswijt的序列(A090822)确实非常慢。为了显示:

  • 前三个出现在第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(一个重复的块(21, 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
  • 您的代码可以以任何形式输出数字(列表,多个输出等)。

这是代码高尔夫,因此以字节为单位的最短代码获胜。

Answers:


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

在线尝试:演示

使用与马丁和彼得相同的想法。在每一步中,我将字符串分成长度为1的片段,长度为2的片段,然后对它们进行范围长度编码,并使用最大的第一个游程作为下一个数字。

带字符串的20个字节

t_u+eSmhhrcGd8SlGGQN

在线尝试:演示

结合了上面两个代码的思想。


1
谢谢教我 我总是忘记._Pyth中的功能和其他有用的功能。
Leaky Nun

我个人更喜欢原始解决方案,但是。
clismique '16

@Jakube啊 我能看看吗?如果是的话,谢谢!
clismique 2016年

@DerpfacePython能够使我的原始解决方案再增加一个字节。我还发布了基于Martin的行程编码解决方案,然后能够将这两种方法结合起来以生成20字节的解决方案。
雅库布,2016年

5

CJam,33 31 30 27字节

感谢Peter Taylor节省了1个字节。

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>+}/

在线演示

这与马丁非常共同。

  • 游程长度编码(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

第三行定义了一个匿名函数,该函数接受一个整数并返回一个整数列表。 看到它在行动。

说明

辅助函数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

输入是!用作数字的一元整数(尽管可以将其更改为任何其他非数字字符)。输出只是一串数字。

在线尝试!(或者,为方便起见,这是一个需要十进制输入的版本。

出于测试目的,这可以加快很多具有小的修改,其允许在一分钟下测试输入220:

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

在线尝试!十进制版本。

如果您想测试更大的数字,最好只输入一些大量的输入,:然后在初始输入后加上a +。这将使Retina每次完成计算新数字(所有数字一一对应)时打印当前序列。

说明

该解决方案由单个正则表达式替换组成,该替换将反复应用于输入,直到结果停止更改为止,在这种情况下,这是因为正则表达式不再匹配。在+一开始介绍这个循环。这1是一个限制,告诉Retina仅替换第一个匹配项(这仅与第一次迭代有关)。在每次迭代中,阶段用!序列的下一位替换(从左开始)。

像往常一样,如果您需要有关平衡组的入门知识,请参考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 2016年

@DerpfacePython,因为它更便宜,并且得到了共识。您可以通过指定输入必须为十进制数字来否决该问题(在这种情况下,我很乐意更改解决方案)。
Martin Ender

嗯,谢谢您的澄清。但是,出于好奇,您能否在注释中放入十进制答案?如果是这样,谢谢。
clismique 2016年

@DerpfacePython使用十进制输入添加了单独的链接。
Martin Ender

我打完高尔夫球的解释?
CalculatorFeline

0

Ruby,84个字节

Retina的答案启发了我去做一个基于正则表达式的解决方案,以找到最佳序列,而不是以某种方式对数组中的序列进行计数,但是天才更少(Ruby中似乎不允许使用带有量词的负后置,所以我怀疑无论如何,我都可以直接移植视网膜的答案)

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

给定一个已经生成的序列s,将其映射在所有i1s.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。然后,该函数从该映射中找到最大重复次数,并将该次数添加到字符串的末尾。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.