获取序列步骤


17

挑战

给定一个数字序列,创建一个返回序列步骤的函数。

  • 假设一个序列将是 N >= 3
  • 序列将至少重复一次该步骤
  • 序列将仅包含自然数
  • 您的函数或程序应返回最短的步骤顺序

例:

输入: [1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17]

输出: [1, 1, 2]

说明:初始序列来自1 => 2 (1 step), 2 => 3 (1 step), 3 => 5 (2 steps)。然后重复。输出是[1 step, 1 step, 2 steps] => [1, 1, 2]

另一个例子:

输入: [2, 5, 6, 7, 8, 11, 12, 13, 14, 17, 18, 19, 20]

输出: [3, 1, 1, 1]

[2, 5, 6, 7, 8, 11, 12, 13, 14, 17, 18, 19, 20]
 \  /\ /\ /\ / 
  3   1  1  1  Then it repeats...

测试用例

Input: [1, 4, 8, 9, 10, 13, 17, 18, 19, 22, 26, 27, 28] => Output: [3,4,1,1]

Input: [6, 11, 13, 18, 20, 25, 27, 32, 34, 39, 41] => Output: [5,2]

Input: [2, 6, 10, 13, 17, 21, 25, 28, 32, 36, 40, 43, 47] => Output: [4,4,3,4]

Input: [5, 6, 7] => Output: [1]


澄清说明

  • 输入长度-1可被输出长度整除
  • 假设顺序总是会增加

这是,因此最短的答案以字节为单位。



6
我看到您最近发布了一些挑战,并提出了许多澄清的评论,并且有两句以“不清楚”结尾,随后在进行了适当的编辑后重新打开。你有没有考虑在发布这些沙箱几天/周?我很喜欢您的挑战,因为它们很容易接近,但是所有挑战,无论多么简单或发布者,都可以使用改进。
朱塞佩

2
@Giuseppe感谢您的建议。我在沙盒中发布了其他一些挑战(通常,如果我没有正确的方法来创建挑战,我会删除它)。对于这些挑战,我认为它们已经足够清楚了,这就是为什么我立即发布,但是我将首先开始在沙箱中发布它们。谢谢
路易斯·费利佩·德·耶稣·穆诺兹

2
@LuisMendo异端!0是自然数!比利·乔尔(Billy Joel)甚至还有一整个专辑献给了Peano Man!
ngm

1
@AdmBorkBork,这与处理任意长度的操作列表更相关
彼得·泰勒

Answers:


10

果冻9 7个字节

IsJEƇḢḢ

在线尝试!

怎么运行的

IsJEƇḢḢ  Main link. Argument: A (array)

I        Increment; compute D, the array of A's forward differences.
  J      Indices; yield [1, ..., len(A)].
 s       Split D into chunks of length k, for each k in [1, ..., len(A)].
   EƇ    Comb equal; keep only partitions of identical chunks.
     Ḣ   Head; extract the first matching parititon.
      Ḣ  Head; extract the first chunk.

9

JavaScript(ES6),58个字节

输出以逗号分隔的字符串(带有前导逗号)。

a=>(a.map(p=x=>-(p-(p=x)))+'').match(/N((,\d+)*?)\1*$/)[1]

在线尝试!

56个字节,如果我们用,-隔膜和我们假设顺序总是严格增加。

怎么样?

我们首先使用以下命令将输入​​数组a []转换为连续差异列表:

a.map(p = x => -(p - (p = x)))

因为p最初设置为非数值(map()的回调函数),所以第一次迭代会生成NaN

例:

[6, 11, 13, 18, 20, 25, 27, 32, 34, 39, 41]
[ NaN, 5, 2, 5, 2, 5, 2, 5, 2, 5, 2 ]

然后,我们将结果强制为字符串:

"NaN,5,2,5,2,5,2,5,2,5,2"

最后,我们寻找最短的1个模式,以逗号分隔的整数(,\d+)从“ NaN”之后开始,一直重复到字符串的结尾:

match(/N((,\d+)*?)\1*$/)

1:使用非贪婪 *?


我发布了基于相同正则表达式思想的解决方案,但实现方式却大不相同。当然,在开发我的产品之前,我没有看过其他解决方案,而且看起来已经足够不同了,也许这是我第一次在这里获得比您更好的得分。
edc65

1
53个字节:/(,.+?)\1*$/
尼尔

6

Brachylog,11个字节

s₂ᶠ-ᵐṅᵐ~j₍t

在线尝试!

如果有内置的连续差异,将为5个字节。

说明

Example input: [6, 11, 13, 18, 20, 25, 27, 32, 34, 39, 41] 

s₂ᶠ             Find all substrings of length 2: [[6,11],[11,13],…,[34,39],[39,41]]
   -ᵐ           Map subtraction: [-5,-2,-5,-2,-5,-2,-5,-2,-5,-2]
     ṅᵐ         Map negate: [5,2,5,2,5,2,5,2,5,2]
       ~j₍      Anti-juxtapose the list of differences; the shortest repeated list is found
                  first, with the biggest number of repetitions: [5,[5,2]]
            t   Tail: [5,2]

您可以否定尾巴以节省一个字节?
罗德

@Rod我仍然需要映射它,所以它的长度是相同的。Negate是两个数字之间的谓词,它不会像其他语言一样自动矢量化到列表(否则,它将不能与声明性程序中常见的未知输入/输出配合使用)
Fatalize

5

Pyth,11个字节

<J.+Qf.<IJT

在这里尝试

说明

<J.+Qf.<IJT
 J.+Q          Call the sequence of differences in the input J.
     f         Find the first positive integer T...
      .<IJT    ... where rotating J by T doesn't change it.
<J             Take that many elements of J.

5

Japt14 12字节

äa
¯@eUéX}aÄ

尝试一下


说明

              :Implicit input of array U
äa            :Consecutive absolute differences
\n            :Reassign to U
 @    }aÄ     :Return the first positive integer X that returns true
   UéX        :  Rotate U right X times
  e           :  Check equality with U
¯             :Slice U to that element

原版的

äa
@eUîX}a@¯XÄ

尝试一下


5

R49 46字节

完整程序:

d=diff(scan());while(any((s=d[1:T])-d))T=T+1;s

在线尝试!

R72 58 54字节

将所有测试用例放在一个位置的原始函数提交:

function(a,d=diff(a)){while(any((s=d[1:T])-d))T=T+1;s}

在线尝试!

感谢JayCe建议功能的完整程序路径和-4字节,并感谢Giuseppe提供了-3。


通过滥用内置程序并使之成为完整程序,可以达到-9个字节。挑战允许一个完整程序。
JayCe

@JayCe也不需要a<-在这里
Giuseppe

4

J22 19字节

感谢FrownyFrog,节省了3个字节!

0{"1[:~./:|."{}.-}:

在线尝试!

[在线尝试!] [TIO-ji2uiwla]

怎么样?

                 -      find the successive differences by subtracting 
                  }:    the list with last element dropped
               }.       from the list with the first element dropped 
           |."{         rotate the list of differences
         /:             0..length-1 times (the input graded up)
     [:~.               remove duplicating rows
 0{"1                   take the first element of each row

如果您/:不是#\,则可以0{"1[:~.保存1个字节。
FrownyFrog

并且"0 1"{
FrownyFrog

@FrownyFrog再次感谢!
Galen Ivanov

1
这太好了。
约拿(Jonah)

@Jonah是的,感谢FrownyFrog!
Galen Ivanov

4

05AB1E,8个字节

感谢Kevin Cruijssen保存了3个字节。

¥.œʒË}нн

在线尝试!


05AB1E,11个字节

āεI¥ô}ʒË}нн

在线尝试!

完整程序。
ā长度范围。按[1 ... len(inp)]。
 对于每个...
  I¥ô...将三角洲切成相应大小的碎片
      Keep仅保留所有元素相等的元素。
         并首先检索第一个元素的第一个元素。

13字节

IMO一个可爱的选择:

¥©ηʒDg®ôÙ˜Q}н

在线尝试!

¥©ηʒDg®ôÙ˜Q}н   Full program.
¥               Push the deltas.
 ©              Copy them to the register.
  ηʒ       }    And filter the prefixes by...
    D     Q     ... Is the prefix itself equal to...
     g®ô        ... The deltas, split into chunks of its length...
        Ù˜      ... Deduplicated and flattened?
            н   Head.

1
8个字节通过使用
凯文·克鲁伊森

3

Javascript,49个56字节

编辑保存了7个字节,谢谢(猜猜是谁?)

与Arnauld相同的正则表达式想法,但奇怪的是在实现上却是如此……

返回带有逗号分隔的字符串(和前导逗号)

p=>/N(.+?)\1+$/.exec(p.map(p=v=>[v-p,p=v][0]))[1]

测试

var F=
p=>/N(.+?)\1+$/.exec(p.map(p=v=>[v-p,p=v][0]))[1]

;[[1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17]
,[1, 4, 8, 9, 10, 13, 17, 18, 19, 22, 26, 27, 28]
,[6, 11, 13, 18, 20, 25, 27, 32, 34, 39, 41] 
,[2, 6, 10, 13, 17, 21, 25, 28, 32, 36, 40, 43, 47]
,[5, 6, 7]]
.forEach(x=>console.log(x + ' -> ' + F(x)))


使用match是我的错误决定。你可以再打败我。:-)
Arnauld

3

MATL14 13 12字节

dt5YLFTF#Xu)

在线尝试!

刚刚发现MATL确实具有循环功能!

说明

d -以数组的形式获取连续项之间的差

t5YL-复制该代码,然后使用调用YL('gallery')函数5('circulant')选项。创建一个将给定向量作为第一行的矩阵,然后连续的行将相同的向量循环移位,直到环绕。

FTF#Xu-检查唯一的行并获取其行号(不确定是否有更短的方法)。当重复序列步骤时,循环移位的行将与第一行相同,随后的行将重复。因此,这将在序列步骤开始重复之前获得序列步骤的第一次运行的索引。

) -使用该索引到原始差异数组中以获取答案。


较旧:

d`tt@YS-a}@:)

在线尝试!

(-1字节,感谢Giuseppe)

说明:

d   % Get the differences between successive terms, as an array
`   % Start do-while loop
  tt  % duplicate the difference array twice
  @   % push the current loop index value
  YS  % circularly shift the difference array by that amount
  -   % subtract the shifted diffs from the original diffs
  a   % see if the subtraction resulted in any non-zeros
    % if it did, shifted differences were not equal to original differences, so continue loop 
}@ % if it didn't, then get loop index
:) % get the differences upto the loop index, before they started repeating
   % implicit loop end

2

Python 2,101字节

def f(l):d=[y-x for x,y in zip(l,l[1:])];g=len(l);print[d[:k]for k in range(1,g+1)if g/k*d[:k]==d][0]

在线尝试!

第一产生增量ð,然后找到的第一个前缀pd反复时⌊len(L)/ LEN(P)⌋倍的产量大号,其中大号是输入列表中。



2

Java 10、104100字节

a->{var t="";for(int i=a.length;i-->1;t+=a[i]-a[i-1]+" ");return t.replaceAll("( ?.+?)\\1*$","$1");}

正则表达式,( ?.+?)\1*$用于@Neil@Arnauld的JavaScript(ES6)answer 的评论中的最短重复子字符串。

在线尝试。

说明:

a->{                        // Method with integer-array parameter and String return-type
  var t="";                 //  Temp-String, starting empty
  for(int i=a.length;i-->1; //  Loop backward over the input-array, skipping the first item
    t+=a[i]-a[i-1]          //   Calculate the difference between two adjacent items
       +" ");               //   And append this with a space to the temp-String
  return t.replaceAll("( ?.+?)\\1*$", 
                            //  Find the shortest repeating substring
                     "$1");}//  And only keep one such substring

1

APL + WIN,39个字节

提示输入。

(↑((⍴v)=+/¨(⊂v)=(⍳⍴v)⌽¨⊂v)/⍳⍴v)↑v←-2-/⎕

在线尝试!由Dyalog Classic提供

说明:

v←-2-/⎕ Prompt for input and take successive differences

(⍳⍴v)⌽¨⊂v create a nested vector ans sequentially rotate by one to length of v

+/¨(⊂v)= compare to original v and sum positions where there is match

(⍴v)= identify where all elements match

(↑(....) identify number of rotations giving a first complete match

(↑(...)↑v take first number of elements from above from v as repeated sequence

1

Python 2中86 85个字节

def f(a,n=1):d=[y-x for x,y in zip(a,a[1:])];return d[:-n]==d[n:]and d[:n]or f(a,n+1)

在线尝试!

将差异构造为d; 如果d与单元尺寸重复n然后d[n:]==d[:-n]; 否则递归。


1

视网膜0.8.2,42字节

\d+
$*
(?<=(1+),)\1

1+(.+?)\1*$
$1
1+
$.&

在线尝试!链接包括测试用例。输出包括前导逗号。说明:

\d+
$*

转换为一元。

(?<=(1+),)\1

计算正向差异,第一个数字除外,该数字被遗忘​​。

1+(.+?)\1*$
$1

匹配重复的差异。

1+
$.&

转换为十进制。


1

05AB1E14 13 字节

¥DηvÐNƒÁ}QD—#

在线尝试验证所有测试用例

我知道@ Mr.Xcoder已经发布了两个简短的05AB1E答案,但是我想尝试使用轮换和相等检查的另一种方法。
可能可以击打几个字节而不会掉线Á

@Emigna提示后的-1个字节删除了global_variable寄存器(©和2x ®),DÐ改为使用Duplicate()和Triplicate()。

说明:

¥             # Calculate the deltas of the input-array
              #  i.e. [1,2,3,5,6,7,9] → [1,1,2,1,1,2]
 D            # Duplicate it
  η           # Push all its prefixes
              #  [1,1,2,1,1,2] → [[1],[1,1],[1,1,2],[1,1,2,1],[1,1,2,1,1],[1,1,2,1,1,2]]
v             # For-each over these prefixes
 Ð            #  Triplicate the (duplicated) deltas-list
  NƒÁ}        #  Rotate the deltas-list N+1 amount of times,
              #  where N is the prefix index (== prefix_length-1)
              #   i.e. [1,1,2] and [1,1,2,1,1,2] (rotate 3 times) → [1,1,2,1,1,2]
      Q       #  If the rotated deltas and initial deltas are equal
              #   [1,1,2,1,1,2] and [1,1,2,1,1,2] → 1
       D—#    #  Print the current prefix-list, and stop the for-each loop

1
这是9(单独的答案,因为它是一个非常不同的算法,尽管它确实共享¥η)。
Grimmy

@Grimy您正在查看我所有的05AB1E答案并打高尔夫球吗,哈哈?; p不错的答案(再次),我的+1。
凯文·克鲁伊森

1
并非所有人,我都只是通过这篇文章中的链接进行介绍。
Grimmy

@肮脏的嗯,这很有道理。:)
凯文·克鲁伊森

1

Haskell,107个字节

let i=map(uncurry(-))$zip(tail x)(init x)in head$filter(\s->take(length i)(concat$repeat s)==i)(tail$inits i)

x是输入数组。


欢迎来到PPCG,尤其是Haskell高尔夫!您不能假定输入存在于某个变量中,尽管可以通过prepending轻松解决f x=。也可以使用initsrequire import Data.List,因为它不是Prelude的一部分:在线尝试!
Laikoni

但是,您可以节省很多字节:(init x)可能只是x因为zip其中一个列表的长度大于另一列表的长度,所以会自动截断。并且map(uncurry(-))$zip存在一个内置的:zipWith(-)。而不是f x=let i=...in你可以使用一种模式后卫:f x|i<-...=
Laikoni

此外,您可以使用列表推导代替filter!!0代替headcycle代替concat$repeat在线尝试!
Laikoni

@Laikoni非常感谢您的改进!没错,我的代码需要函数声明和Data.List.inits的导入。但是我想知道,是否应该将其添加到代码的长度中?我之所以问是因为其他一些代码示例也依赖于一些额外的代码。
misja111

是的,人们普遍认为分数包含这些字节。我们在Haskell提供了有关高尔夫规则指南,其中涵盖了大多数情况。
Laikoni

1

Stax8 6 字节

░»F\☺»

运行并调试

这是解压后的带注释版本,以显示其工作方式。

:-  pairwise differences
:(  all leftward rotations of array
u   keep only unique rotations
mh  output the first element from each unique rotation

运行这个


1

Perl 6、57字节

{~(.rotor(2=>-1).map:{.[1]-.[0]})~~/^(.+?){}" $0"+$/;~$0}

测试一下

输出以空格分隔("1 1 2"

展开:

{      # bare block lambda with implicit parameter $_

  ~(   # stringify (space separated)

    .rotor( 2 => -1 )     # from the input take 2 backup 1, repeat
    .map: { .[1] - .[0] } # subtract each pair to find the differences
  )

  ~~   # smartmatch

  /    # regex

    ^  # beginning of string

    ( .+? ) # match at least one character, but as few as possible
    {}      # make sure $0 is set (probably a compiler bug)
    " $0"+  # match $0 one or more times (with a leading space)

    $  # end of string
  /;

  ~$0  # return the stringified $0
}

整个第一部分可以是~(.skip Z-$_)
乔·金

1

05AB1E,9个字节

¥©η.ΔÞ®Å?

说明:

          # take input implicitly
¥         # deltas, eg [4, 5, 7, 8, 10] -> [1, 2, 1, 2]
 ©        # save this to the global register
  η       # prefixes, eg [1, 2, 1, 2] -> [[1], [1, 2], ...]
   .Δ     # find the first one such that
     Þ    # cycled infinitely, eg [1, 2] -> [1, 2, 1, 2, ...]
       Å? # starts with
      ®   # the global register
          # and implicitly print the found element

备用9字节:

¥η.ΔÞ.¥-Ë

相同的算法,但是没有与增量列表(需要保存/还原)进行比较,而是使用了(undelta)然后与(隐式)输入进行了比较。

在线尝试!


0

K4,30个字节

解:

(*&d~/:c#'(!c:#d)#\:d)#d:1_-':

例子:

q)k)(*&d~/:c#'(!c:#d)#\:d)#d:1_-':2, 5, 6, 7, 8, 11, 12, 13, 14, 17, 18, 19, 20
3 1 1 1
q)k)(*&d~/:c#'(!c:#d)#\:d)#d:1_-':1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17
1 1 2
q)k)(*&d~/:c#'(!c:#d)#\:d)#d:1_-':1, 4, 8, 9, 10, 13, 17, 18, 19, 22, 26, 27, 28
3 4 1 1
q)k)(*&d~/:c#'(!c:#d)#\:d)#d:1_-':6, 11, 13, 18, 20, 25, 27, 32, 34, 39, 41
5 2
q)k)(*&d~/:c#'(!c:#d)#\:d)#d:1_-':2, 6, 10, 13, 17, 21, 25, 28, 32, 36, 40, 43, 47
4 4 3 4
q)k)(*&d~/:c#'(!c:#d)#\:d)#d:1_-':5 6 7
,1

说明:

对于我们要解决的问题,似乎有些沉重。获取输入的增量,然后构建序列并确定与之匹配的最短序列。

(*&d~/:c#'(!c:#d)#\:d)#d:1_-': / the solution
                           -': / deltas 
                         1_    / drop first
                       d:      / save as d
                      #        / take (#) from
(                    )         / do this together
                 #\:d          / take (#) each-left (\:) from d
          (     )              / do this together
              #d               / count length of d
            c:                 / save as c
           !                   / range 0..c-1
       c#'                     / take c copies of each
   d~/:                        / d equal (~) to each right (/:)
  &                            / where true
 *                             / first one


0

Perl -p 5、55个字节

s/\d+ (?=(\d+))/($1-$&).$"/ge;s/\d+$//;s/^(.+?)\1*$/$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.