重建算术序列


23

给定一个正整数的有限算术序列,其中一些项从中间删除,请重构整个序列。

任务

考虑一个算术序列:一个正整数列表,其中两个连续元素之间的差是相同的。

2 5 8 11 14 17

现在,假设受以下约束,从序列中删除一个或多个整数:

  • 删除的整数将是该序列的连续项。
  • 序列中的第一个和最后一个整数将不会被删除。
  • 序列中至少保留三个整数。

对于上述顺序,可能的删除包括:

2 5 8 14 17  (removed 11)
2 5 17       (removed 8 11 14)
2 14 17      (removed 5 8 11)

您的任务:给定这些部分序列之一,重建原始的完整序列。

细节

您可能会认为输入有效(有解决方案)并且至少缺少一个术语。序列中的所有数字均为正(> 0)整数。序列在项之间可以具有正或负差(即,可以增加或减少)。它不是一个恒定的序列(例如5 5 5)。

您的解决方案可能是完整程序或功能。任何默认的输入和输出方法都是可以接受的。

您的输入和输出可以是字符串(带有任何合理的定界符),字符串列表或数字列表。您可以使用方便的语言来代表数字。

请在您的提交中提及任何异常的I / O方法/格式,以便其他人能够更轻松地测试您的代码。

测试用例

In: 2 5 8 14 17
Out: 2 5 8 11 14 17
In: 2 5 17
Out: 2 5 8 11 14 17
In: 2 14 17
Out: 2 5 8 11 14 17
In: 21 9 6 3
Out: 21 18 15 12 9 6 3
In: 10 9 5
Out: 10 9 8 7 6 5
In: 1 10 91 100
Out: 1 10 19 28 37 46 55 64 73 82 91 100

这是;每种语言中最短的答案将获胜。



以表格的形式输入会很有趣2 5 ... 17
schnaader

Answers:


9

Haskell,63个字节

f(a:b:c)|s<-[a,b..last c],all(`elem`s)c=s
f a=r$f$r a
r=reverse

在线尝试!

基本上是通过尝试从正面构建结果,如果失败则从背面构建结果。这利用了以下事实:输入的第一个和最后一个成员将始终是正确的,已删除的成员必须是连续的,并且输入中将始终至少存在三个项目。我所要做的就是假设第二名或倒数第二名的成员都是准确的,并检查其是否有效。幸运的是,Haskell具有用于创建算术级数的非常漂亮的语法。

编辑:感谢@xnor指出了一个错误并提供了解决方案!


5
尽管这很漂亮,但似乎并不总是有效:[1,3,4,5]给出[1,3,5]
xnor

1
而且我认为all(`elem`s)c应该使用相同的字节数来修复它。
xnor

6

05AB1E9 8字节

Ÿs¥¿Äô€н

在线尝试!

说明

  • 构造范围[first,...,last]的差异为+/- 1
  • 计算输入的增量
  • 获取增量的gcd的绝对值
  • 将整个范围拆分为该大小的块
  • 获取每个块的第一个元素

使用gcd of deltas代替节省了1个字节min delta,受到user202729的启发


5

Brachylog v2,9个字节

⊆.s₂ᵇ-ᵐ=∧

在线尝试!

这是函数提交。通过将Brachylog解释器Z作为命令行参数,可以使它像完整程序一样对函数进行评估。在这种情况下,输入以例如格式指定,[1, 2, 4]而输出以类似格式返回,例如Z = [1, 2, 3, 4]。(当然,对于函数提交,输入和输出根本没有任何格式;它们只是列表。)

实际上,这比OP所要求的解决了一个更棘手的问题:它计算出包含指定顺序的指定值的最短整数算术序列,而不管删除是否连续。因为它使用蛮力,所以如果删除许多值,它可能会非常慢。

说明

该程序分为三个主要部分。

查找输入的超序列(即,将输入作为子序列的序列)。如果Brachylog程序有多个可能的输出,则选择的输出是按抢七顺序排列的第一个输出,并且抢七顺序由程序中有意见的第一个命令确定;在这种情况下,请指定一个顺序,该顺序优先于短输出而不是长输出。因此,我们得到的输出将是输入中最短的超序列,服从程序其余部分的限制。

.用于输出它视为输入的值(在这种情况下,即超序列),但也可以断言它具有特定条件。换句话说,我们将输出符合特定条件的最短超序列(并忽略用于查看其是否符合条件的任何中间结果)。

最后,我们有一个条件s₂ᵇ-ᵐ =,即“序列的所有增量都相等”,这是我们要应用于输出的条件。(从中返回的值是增量列表,而不是超序列本身,这就是为什么我们需要.来确保输出正确的事物。)

Brachylog由于没有任何可处理增量计算的内建函数,对列表中的重叠对进行运算等而受到阻碍。取而代之的是,我们必须明确地说出我们的意思:s₂ᵇ找到长度为2()的所有()个子串(s)(需要使用来保持子串和超序列中的未知数之间的链接;更常用的会破坏此链接)。然后-ᵐ对这些对中的每一个进行减法运算以产生增量。必须为s₂ᵇ-ᵐ大多数现代高尔夫语言内置的内容写出五个字节是很烦人的,但是我想这就是代码高尔夫有时的样子。


4

Python 2,104 97 89 83 71 67 60字节

感谢Chas Brown节省了4个字节。
感谢ovs保存7个字节。

通过参数输入列表。

lambda a,b,*c:range(a,c[-1],min(b-a,c[0]-b,key=abs))+[c[-1]]

在线尝试!

说明:

由于移除的是连续的,因此足以检查两对连续元素之间的差异。


替换b if b%c else c为可以节省3个字节[c,b][b%c>0]
Chas Brown

@ChasBrown谢谢,尽管我很快想出了一个更好的方法。
Colera Su

1
尼斯key=abs!看来,f=除非使用了递归函数,否则人们常常会省略该部分。这样您可以节省2个字节。
Chas Brown

1
另外,替换a[-1]-a[-2]a[2]-a[1]-逻辑相同,您又得到2个字节。
Chas Brown


4

Pyth,11个字节

%hS.+SQ}hQe

在这里尝试!

感谢Steven H.节省了一个字节!

Pyth,12个字节

%.aiF.+Q}hQe

在这里尝试!

怎么运行的

%.aiF。+ Q} hQe〜完整程序。

     。+ Q〜获取增量。
   iF〜通过GCD减少。
 .a〜绝对值。
%〜模块化。获取...的第n个元素
        }〜之间的包含数字范围...
         hQ〜第一个元素,然后...
           e〜最后一个元素。

预先分类Q,所以你可以排序和采取的第一个元素,而不是abs(GCD(Q))%hS.+SQ}hQe为11个字节。测试套件
Steven H.

3

果冻,8字节

ṂrṀmIg/$

在线尝试!

笔记:

  • 仅适用于旧版本的Jelly。(例如,此提交)(在guse中fractions.gcd,其结果符号与输入符号相同,而不是math.gcd总是返回正值的)。

  • 上面的TIO链接是Python 3 TIO链接,Python代码由我上面提到的提交中的Jelly源代码组成,但所有内容(3个文件)打包到同一个文件中(供TIO运行)除外,dictionary.py并且已简化为只有几行。然而dictionary.py,与该答案无关,因为它不使用压缩字符串。(“...»构造)

说明:

首先,由于删除了一个连续的段并剩余了至少3个元素,因此旧列表中保留了两个连续的数字,并且增量将都是该步骤的倍数。因此gcd,差异(I,增量)列表的将是步骤的绝对值。

幸运的gcd是已签名(请参阅上面的注释)

因此程序执行以下操作:

ṂrṀ

最小到最大的递增整数范围

m

模块化,选择第n个元素。

Ig/$

Monadic($)链组合I(增加,g/减少)和(减少gcd列表中的元素)。如果增量为正,gcd则将为正,返回列表将为从左到右(递增),反之亦然。


好极了!用1个字节击败05AB1E答案!
user202729

使用gcd而不是min让我们打领带。太糟糕了,我会收到带有标志的gcd,否则我将是7点;)
Emigna

3

MATL,13字节

1)0GdYkG0)3$:

在线尝试!

说明:

Consider the example input [2 14 17]:
           # implicit input, STACK: [[2 14 17]]
1)         # push 1, index, STACK: [2]
0G         # push 0, duplicate input, STACK: [2, 0, [2 14 17]]
d          # take differences, STACK: [2, 0, [12, 3]]
Yk         # get value in [12, 3] nearest to 0, STACK: [2, 3]
G0)        # get last element in input, STACK: [2, 3, 17]
3$:        # 3-input :, computes 2:3:17, the range from 2 to 17 by 3
           # STACK: [[2 5 8 11 14 17]], implicit output.


3

JavaScript(ES6),92 90

编辑保存的2个字节

很容易,因为足以检查前两个和后两个之间的差异。但是仍然长得令人难以置信。

s=>(e=(z=s.pop(a=s[0]))-s.pop(d=s[1]-a),[...Array((z-(a-=d=e*e>d*d?d:e))/d)].map(_=>a+=d))

少打高尔夫球

s=>{
  a =s[0]
  b =s[1]
  z = s.pop()
  y = s.pop()
  d = b-a
  e = z-y
  d = e*e>d*d?d:e  
  n = (z-a)/d+1
  return [...Array(n)].map((_,i) => a + i*d)
}

测试

var F=
s=>(e=(z=s.pop(a=s[0]))-s.pop(d=s[1]-a),[...Array((z-(a-=d=e*e>d*d?d:e))/d)].map(_=>a+=d))

var test=`In: 2 5 8 14 17 Out: 2 5 8 11 14 17
In: 2 5 17 Out: 2 5 8 11 14 17
In: 2 14 17 Out: 2 5 8 11 14 17
In: 21 9 6 3 Out: 21 18 15 12 9 6 3
In: 10 9 5 Out: 10 9 8 7 6 5
In: 1 10 91 100 Out: 1 10 19 28 37 46 55 64 73 82 91 100`.split`\n`
.map(r=>r.split`Out`.map(x=>x.match(/\d+/g)))

test.forEach(([i,k])=>{
  var o=F(i.slice(0))
  var ok = o+''==k
  console.log(ok?'OK':'KO',i+' => '+o)
})


a-=d=e*e>d*d?d:e应该工作并保存2个字节。
Arnauld

@Arnauld确实可以工作,谢谢
edc65

2

Wolfram语言(Mathematica),50个字节

Range[#&@@#,#[[-1]],#&@@Differences@#~SortBy~Abs]&

在线尝试!


“数字列表”是否包括将数字作为单独的参数?如果是这样,看起来您可以节省很多字节。
numbermaniac

@numbermaniac我不这么认为,因为没有内置函数可以获取最后的输入...
JungHwan Min

啊...是的。忘了那个。
numbermaniac

您可以使用{##}Last@{##}但我能得到的最好的结果是51个字节。
numbermaniac



1

J49,47 46字节

(0-[:<./2|@-/\]){.@[&]\({.<.{:)+[:i.{:(+*)@-{.

受Emigna解决方案的启发。

怎么运行的:

 (0-[:<./2|@-/\]){.@[&]\({.<.{:)+[:i.{:(+*)@-{. - fork of 3 verbs

                        ({.<.{:)+[:i.{:(+*)@-{. - generates a list in the entire range of values
                                     {:     -{. - last minus first element  
                                       (+*)@    - adds the signum of the difference
                                 [:i.           - makes a list 
                       ({.<.{:)                 - the smallest of first and last elements                                     
                               +                - adds the offset to the list (translates all elements according to the first one)

 (0-[:<./2|@-/\])                               - finds the step
         2|@-/\]                                - the absolute differences between all consecutive elements
    [:<./                                       - the smallest one
  0-                                            - negate (for splitting)

                 {.@[&]\                        - splits the list from the right verb into left verb's result sublists and takes their first elements

在线尝试!


1

外壳,9个字节

m←C▼Ẋ≠⁰…⁰

在线尝试!

非常感谢H.PWiz将字节数减半,因为指出在列表上进行排序很容易!...


@ HP.Wiz X_X我不知道Husk会列出这样的范围...您确定不希望将其发布为自己的单独答案吗?
Xcoder先生

@ HP.Wiz感谢loooot
Xcoder先生17年

另外,可以F⌋?代替。
H.PWiz

@ H.PWiz @ _ @为什么还行?
Xcoder先生

最小(绝对)差异将是原始差异。的唯一原因gcd是应对负增量
H.PWiz

1

C#(.NET Core)167 + 13 = 180 145 + 13 = 158字节

a=>{int x=a[1]-a[0],y=a[2]-a[1],d=x*x<y*y?x:y,s=Math.Abs((a[a.Length-1]-a[0])/d),i=0,j=a[0];var r=new int[s+1];for(;i<=s;j+=d)r[i++]=j;return r;}

在线尝试!

+13 using System;

令人惊讶的是,这一挑战比我最初预期的要细微得多。

致谢

由于@DLosc进行了一些简单的简化,因此节省了-22个字节。

去高尔夫

a=>{
    int x = a[1]-a[0],        // difference between first and second numbers
        y = a[2]-a[1],        // difference between second to last and last numbers
        d = x*x < y*y? x : y, // smallest absolute value difference
        s = Math.Abs((a[a.Length-1] - a[0]) / d), // number of steps in the reconstructed sequence (not the number of elements)
        i = 0,                // step position
        j = a[0];             // next number in reconstructed sequence

    var r = new int[s+1];

    // reconstruct the sequence
    for(; i <= s; j+=d)
        r[i++]=j;

    return r;
}

0

Python 2 2,147字节

from fractions import*
a=input()
b=[j-i for i,j in zip(a[:-1],a[1:])]
l=min(gcd(i,j)for i in b for j in b)
print list(range(a[0],a[-1]+l/abs(l),l))

在线尝试!





0

Japt,12个字节

ÌõUg Uäa ñ g

试试吧


说明

õ从输入数组(Ì)的最后一个元素到第一个(Ug)生成一个整数()数组。计算元素之间的步长,方法是从输入中获取所有两个元素对,并通过绝对差(Uäa)减少它们,然后ñ对该数组进行排序(),并获取第一个元素(g)。

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.