連続整数の合計


27

誰かが何かを言う前に、似ている似ています。しかし、これはduではありません。


いくつかの正の整数は、少なくとも2つの連続する正の整数の合計として記述できます。たとえば、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

2
数字は0より大きい必要がありますか:6 = 0 + 1 + 2 + 3または6 = 1 + 2 + 3
ダミアン

5
副次的な注意点として、密接に関連する課題がある場合、「これはだまされていません」と言っても、それがだまされていると思う場合、そのことを人々に確信させることはほとんどありません。なぜそうではないと思うのかを説明しておけば、もっと役立つでしょう。
マーティンエンダー

1
@Damienの「ポジティブ」は通常、> 0を意味します。0が含まれている場合、「非負」と呼ばれます。
マーティンエンダー

3
CC @Vixen ^(負の数が許可された場合にも、最適解が常に範囲だろう-n+1n
マーティン・エンダー

回答:


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を検索します。

  • 合計が小さすぎる場合は、次に大きい数値を追加して、間隔の右端を1つ上にシフトします。
  • 合計が大きすぎる場合は、最小の要素を削除して左端をシフトアップします
  • 合計が正しい場合、Rを出力します。

間隔の下端は増加するだけなので、短い間隔の前に長い間隔が見つかります。


奇妙にも効率的です。再帰スタックは最終的にオーバーフローします(例:n = 8192)。
プリモ

7

Pyth、12 10バイト

j\+hfqsTQ}M^SQ2

コードの長さは15バイトで、-5バイトのボーナスの資格がありますPyth Compilerでオンラインで試してください。

@ 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

回答を編集しました。
デニス

素晴らしいです、ありがとう!私はあなたのテクニックが好きです。
ETHproductions

1
入力:1000 30分とカウント...
プリモ

3

Mathematica、73 68 65 56 43バイト

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

1
+1昨夜は同様の解決策になりましたが、インターネットがダウンしました。またTuples、中置式を作成できます。
LegionMammal978

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,...が最大化されるように、入力の正の差を持つ三角形番号を見つけることを本質的に試みています。
アークトゥルス

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≤√ (2n)を持つ可能性のある解の長さrで反復し、明示的に解をチェックします。存在するソリューションのために、場合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 私は常にチェーンの開始から差し引いてしまった最後の整数であり、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

ルビー、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

オンラインでお試しください!

これは、デニスのPythに似たブルートフォースアプローチです。

すべてアップはk、単に入力を読み取りn、レジスタ1にして、リストを作成する[[1],[2,2],[3,3,3],[4,4,4,4],...]までn nの。

次のビットは、レジスタ0に格納されている関数で、ペアを取り、両方の要素をインクリメントし、範囲に変換し、範囲の合計を見つけ、その合計がレジスタ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

最も意味のあるものを投稿しましたが、速度を最適化したとしましょう。
エリックアウトゴルファー


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バイト

Subn予想される整数型の入力を受け取り、セルに合計する連続した数字の最長シーケンスを出力するルーチン[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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.