连续整数之和


27

在任何人说任何事,类似的类似的。但这不是骗子。


一些正整数可以写为至少两个连续的正整数之和。例如,9=2+3+4=4+5。编写一个函数,将一个正整数作为其输入,并输出与之相加的最长连续正整数的最长序列作为输出(任何格式都是可以接受的,但是如果输出是由递增序列隔开的-5字节,则+如上所示) 。如果不存在这样的顺序,则应打印数字本身。

这是代码高尔夫。适用标准规则。以字节为单位的最短代码获胜。


样本(请注意格式会有所不同)

Input:   9
Output:  2,3,4

Input:   8
Output:  8

Input:   25
Output:  [3,4,5,6,7]

2
输出的数字是否必须按特定顺序排列(例如递增)?
xnor 2015年

2
数字是否必须> 0:6 = 0 + 1 + 2 + 3或6 = 1 + 2 + 3
Damien 2015年

5
附带说明一下,如果存在密切相关的挑战,则说“这不是骗子”并不能使人们相信,如果他们确实认为这是骗子。如果您解释了为什么认为不是这样,那会更有帮助。
马丁·恩德

1
@Damien“正”通常表示> 0。如果包含0,则将其称为“非负”。
马丁·恩德

3
cc @Vixen ^(同样,如果允许使用负数,则最佳解将始终是从-n+1到的范围n
Martin Ender

Answers:


11

Python,67个字节

f=lambda n,R=[1]:n-sum(R)and f(n,[R+[R[-1]+1],R[1:]][sum(R)>n])or R

一个奇怪的简单策略:用正确的和搜索间隔R。

  • 如果总和太小,请通过追加下一个最高数字将间隔的右端点向上移动一个。
  • 如果总和太大,则通过删除最小的元素来向左端点上移
  • 如果总和正确,则输出R。

由于间隔的底端仅增加,因此在较短的间隔之前会找到较长的间隔。


效率也很奇怪。递归堆栈最终确实会溢出,例如n = 8192。
primo

7

Pyth,12个 10字节

j\+hfqsTQ}M^SQ2

该代码长15个字节,有资格获得-5个字节的奖励。在Pyth编译器中在线尝试。

感谢@Jakube高尔夫球了2个字节!

怎么运行的

j\+hfqsTQ}M^SQ2    (implicit) Store evaluated input in Q.

            S      Compute [1, ..., Q].
           ^  2    Get all pairs of elements of [1, ..., Q].
         }M        Reduce each pair by inclusive range. Maps [a, b] to [a, ..., b].
    f              Filter; for each pair T:
      sT             Add the integers in T.
     q  Q            Check if the sum equals Q.
                   Keep the pair if it does.
   h               Retrieve the first match.
                   Since the ranges [a, ..., b] are sorted by the value of a,
                   the first will be the longest, in ascending order.
j\+                Join, using '+' as separator.

1
对于我们这些在Pyth领域没有开悟的人,您能补充一下解释吗?:)
ETHproductions 2015年

我已经编辑了答案。
丹尼斯

很好,谢谢!我喜欢你的技巧。
ETHproductions's

1
输入1000:30分钟并计数...
primo

3

Mathematica,73 68 65 56 43字节

Cases[Range~Array~{#,#},i_/;Tr@i==#,{2},1]&

1
+1昨晚我得到了类似的解决方案,但是我的互联网中断了。您也可以制作Tuples一个中缀表达式。
LegionMammal978 2015年

3

Haskell,49个48字节

f n=[[a..b]|a<-[1..n],b<-[a..n],sum[a..b]==n]!!0

1
保存1个字节:使用[...]!!0代替head[...]
nimi

2

MATLAB,87 79字节

我知道已经有一个MATLAB答案,但是这个方法有很大的不同。

x=input('');m=1:x;n=.5-m/2+x./m;l=max(find(~mod(n(n>0),1)));disp(m(1:l)+n(l)-1)

这也适用于Octave。您可以在此处尝试在线。我已经将代码添加到consecutiveSum.m链接的工作区中,因此只需consecutiveSum在命令提示符下输入,然后输入值(例如25)。

我仍在努力减少它(也许稍微调整一下方程式),但基本上它会找到一个最大值n,该值m是一个整数,然后显示以m开头的第一个数字n

那么为什么这项工作呢?好吧,基本上,有一个数学方程式控制所有这些数字。如果您认为它们都是连续的,并且从某个点开始,则可以基本上说:

n+(n+1)+(n+2)+(n+3)+...+(n+p)=x

现在,p由此可见,该序列基本上只是第一个三角形数字(包括第0个数字),被添加到p+1很多n。现在,如果让m=p+1我们可以说:

m*(n+(m-1)/2)==x

这实际上是可以解决的。我仍在寻找最短的代码实现方式,我有一些想法可以尝试减少上述代码。


对于25的输入,输出为:

3     4     5     6     7

2
关于三角形的观点,这个挑战实际上是在寻找输入值具有正差的三角形,以使序列中三角形的索引1,3,6,10,...最大化。
Arcturus

1

Python 2,94字节

n=input()
r=int((2*n)**.5)
while r:
 if~r%2*r/2==n%r:print range(n/r-~-r/2,n/r-~r/2);r=1
 r-=1

输入来自标准输入。该解决方案适用于非常大的输入。

这会迭代可能的解决方案长度r,其中r≤√(2n),并明确检查解决方案。为了存在解,如果r为奇数,则n mod r必须为零,如果r为偶数,则n mod r必须为r / 2


样品用量

$ echo 8192 | python sum-con-int.py
[8192]

$ echo 1000002 | python sum-con-int.py
[83328, 83329, 83330, 83331, 83332, 83333, 83334, 83335, 83336, 83337, 83338, 83339]

$ echo 1000000006 | python sum-con-int.py
[250000000, 250000001, 250000002, 250000003]

我特意选择了输出相对较小的示例。


1

八度,89字节

这是我在Octave中可以做的最好的事情。该算法与xnor的算法相同。

x=input('');k=i=1;while x;s=sum(k:i);if s<x;i++;elseif s>x;k++;else;x=0;end;end;disp(k:1)

在MATLAB中,这将是95个字节:

x=input('');k=1;i=1;while x;s=sum(k:i);if s<x;i=i+1;elseif s>x;k=k+1;else x=0;end;end;disp(k:i)

在MATLAB此运行在大约0.1秒输入2000000和用于输入1秒1000002


1

awk,51个字节

{while($0!=s+=s<$0?++j:-++i);while(++i-j)r=r i"+"}$0=r j

该代码为56字节,输出格式为负5字节。我必须额外使用4个字节来生成该格式,所以我实际上节省了1个字节。万岁!;)

实际上,这是从1开始直到总和大于输入的总和的辛苦工作。然后,它开始减去从1开始的数字,直到该数字小于输入。它一直以这种方式更改开始和结束编号,直到找到结果为止,然后进行打印。

使用范例

echo 303 | awk '{while($0!=s+=s<$0?++j:-++i);while(++i-j)r=r i"+"}$0=r j'

示例输出

48 + 49 + 50 + 51 + 52 + 53

我已经尝试过输入,1e12并且464562+...+1488562几乎立即给出了正确的结果()。虽然当然花了一些时间...


喜欢Awk的方法。我很难确定绑定中的优先顺序。您介意添加一个带有更多括号的版本以使其更明显吗?:)
通配符

1
希望这会有所帮助:{while($0!=s)s+=(s<$0) ? (++j) : -(++i); while(++i<j)r=r i"+"}$0=r j i始终是从链的开头减去的最后一个整数,j始终是在链的末尾添加的最后一个整数
Cabbie407

0

Japt,33个字节

它使用了丹尼斯的Pyth技术,尽管它的时间要长得多。

1oU à2 £W=Xg o1+Xg1¹x ¥U©W} rª ªU

在线尝试! 警告:对于较大的输入(<= 20),需要一段时间才能完成,并冻结浏览器,直到出现问题为止。

脱节和解释

1oU à2 £    W=Xg o1+Xg1¹ x ¥ U© W} rª  ª U
1oU à2 mXYZ{W=Xg o1+Xg1) x ==U&&W} r|| ||U

          // Implicit: U = input integer
1oU à2    // Generate a range from 1 to U, and take all combinations of length 2.
mXYZ{     // Map each item X in this range to:
W=Xg o    //  Set variable W to the range of integers starting at the first item in X,
1+Xg1)    //  and ending at 1 + the second item in X.
x ==U&&W  //  If the sum of this range equals U, return W; otherwise, return false.
r||       // Reduce the result with the || operator, returning the first non-false value.
||U       // If this is still false, there are no consecutive ranges that sum to U,
          // so resort to U itself.
          // Implicit: output last expression

赚钱版本:(38字节-5 = 33)

1oU à2 £W=Xg o1+Xg1¹x ¥U©W} rª ªU² q'+

0

朱莉娅92字节

x->(t=filter(i->all(j->j==1,diff(sort(i))),partitions(x));collect(t)[indmax(map(length,t))])

这是一个接受整数并返回数组的匿名函数。要给它起个名字,例如f=x->...

取消高尔夫:

function f(x::Integer)
    # Get all arrays of integers that sum to x
    p = partitions(x)

    # Filter these down to only consecutive runs by checking whether
    # all differences are 1
    t = filter(i -> all(j -> j == 1, diff(sort(i))), p)

    # Find the index of the longest element of t
    i = indmax(map(length, t))

    return collect(t)[i]
end

0

Ruby,94个字节

->n{([*1..n].permutation(2).map{|i,j|[*i..j]if(i..j).reduce(:+)==n}-[p]).max_by{|k|k.size}||n}

取消高尔夫:

-> n {
  ([*1..n].permutation(2).map { |i,j|   # Finds all the possible sets of size 2
     [*i..j] if(i..j).reduce(:+) == n   # Adds a set to an array if sum of the set is n.
   }-[p]                                # Removes nil from the array
  ).max_by { |k|                        # Finds the longest sequence
    k.size
  } || n                                # Returns n if no sequence found.
}

用法:

->n{([*1..n].permutation(2).map{|i,j|[*i..j]if(i..j).reduce(:+)==n}-[p]).max_by{|k|k.size}||n}[25]
=> [3, 4, 5, 6, 7]

0

严重的是53-5 = 48个字节

,;;;╝`;u@n╟(D;)`n(XXk`iu@u@x;Σ╛=[])Ii`╗`ñ╜M`M;░p@X'+j

十六进制转储

2c3b3b3bbc603b75406ec728443b29606e2858586b60697540754
0783be4be3d5b5d29496960bb60a4bd4d604d3bb0704058272b6a

在线尝试!

这是暴力手段,类似于Dennis的Pyth。

一切行动k只读取输入n到寄存器1,然后创建列表[[1],[2,2],[3,3,3],[4,4,4,4],...]最多n n的。

接下来的一位是存储在寄存器0中的函数,该函数取一对,将两个元素加1,将它们转换为范围,找到范围的总和,并检查该总和是否为寄存器1中的值。它返回相应的范围,如果不是,则返回一个空列表。

直到最后一次出现的那一部分都M将函数映射到上面描述的列表的奇特列表enumerate上,然后在每个列表上执行,然后在其上映射存储的函数。完成后,我们将获得一个列表列表,每个列表为空或一个范围的总和为n

;░删除空列表。p@X获取剩下的第一个列表(0@E也可以使用)。'+j放在+每个数字之间,因为它将列表转换为奖金字符串。


0

ES6,72个字节

n=>{for(l=u=1;n;)n>0?n-=u++:n+=l++;return[...Array(u).keys()].slice(l);}

@ Cabbie407的awk解决方案的直接端口,但没有格式设置奖励,因为这是一个惩罚。


0

Python 3中,239个 236 215 203字节

这有点麻烦。以后我得打高尔夫球。

def x(n):
 r=[n]
 for i in range(2,n):
  t=[]
  if i%2*(n%i<1):t=[j+n//i-i//2for j in range(i)]
  elif i%2<1and n%i==i//2:t=[j+n//i-i//2+1for j in range(i)]
  if t[:1]>[0]*(sum(t)==n):r+=t,
 return r[-1]

k是因为如果您检查t[0]为空t,Python 会对您发出粗鲁的声音。同样,这需要打高尔夫球。多亏了t[:1],再也没有粗鲁的声音了!您只需要检查另一个数组。


0

果冻,8字节(无竞争)

ẆS⁼¥Ðf⁸Ṫ

在线尝试!

如果我理解正确,则可能是(11-5 = 6)字节的版本:

ẆS⁼¥Ðf⁸Ṫj”+

出于兴趣的考虑,有12种类似的解决方案(包括该解决方案),将非矢量化等式交换为矢量化等式,将左参数更改为第一参数或标识,并用非等号交换等于,并过滤用于矢量化和非矢量化的滤除。:O
HyperNeutrino

假设我发布了最有意义但速度优化的文章。
暴民埃里克(Erik the Outgolfer)'17年

0

05AB1E11-5 = 6个字节(非竞争)

当然获得该奖金:)

LŒʒOQ}é¤'+ý

在线尝试!

LŒʒOQ}é¤'+ý  Argument: n
LŒ           Sublists of range 1 to n
  ʒOQ}       Filter by total sum equals n
      é¤     Get longest element
        '+ý  Join on '+'

0

PHP,70个字节

while(fmod($q=sqrt(2*$argn+(++$p-.5)**2)-.5,1));print_r(range($p,$q));

与管道一起运行-nR在线尝试

递增p直到找到的整数解argument==(p+q)*(q-p+1)/2
然后打印从p到的范围q


0

Excel VBA,119-5 = 114字节

Sub例程,该例程接受n预期类型的​​整数的输入,并将最长的连续数字序列输出至该单元,并将其求和[A1]

Sub a(n)
For i=1To n
s=0
For j=i To n
s=s+j
If s=n Then:For k=i To j-1:r=r &k &"+":Next:[A1]=r &j:End
Next
Next
End Sub
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.