差分リストを並べ替える


22

整数のリストの差分リストは、連続するメンバーのリストの差分です。

たとえば、

1, 3, 2 ,4

2, -1, 2

あなたのタスクは、入力として差分リストを取得し、元のリストがソートされた場合の差分リストの外観を出力することです。

たとえば、差分リスト

2, 1, -2, -1

リストを表す場合があります

2 4 5 3 2

ソートされるとき

2 2 3 4 5

の違いリストがあります

0 1 1 1

これはため、回答はバイト単位でスコアリングされ、バイト数が少ない方が優れています。


ソリューションは一意であることが保証されていますか?
H.PWiz

@ H.PWizはい、そうです。
小麦ウィザード


1
@ H.PWizクイックプルーフ:リストは差分リスト(DL)から最初の要素値と完全に再構築可能であるため、Lから(FV、DL)への1対1の変換があります。FVを任意の量だけ増やすことは、その量をLのすべての要素に追加することと同じであるため、その比較が適切に単調である場合、Lのソートを変更することはできません。(つまり、追加する数値が整数オーバーフローを引き起こさない限り、ソートには影響しません)。
CR Drost

1
さらにいくつかのテストケースを追加できますか?[-2, 100, -2, -1]たとえば、に対して異なる出力を提供するソリューションがいくつかあります。
シャギー

回答:


16

05AB1E、4バイト

.¥{¥

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

説明

.¥{¥
.¥   # Undelta the input list
  {  # Sort it
   ¥ # And get the deltas

Undelta05AB1Eには、最もニッチなビルトインがあります。O0
totallyhuman

2
ああ、がらくた、私に打ち負かされた。私はいつもアンデルタを使いたいと思っていました。
魔法のタコUr

16
Undeltaಠ___ಠ
ビジネスキャット

1
「非デルタ」は単なる累積合計ですよね?
-Zgarb

2
@Zgarb Undeltaは、リストの最初の要素として0を追加します。次に、前述のとおり、累積合計または逆デルタを追加します。
魔法のタコUr

9

パイソン3numpyの56の 54、53バイト

@Artyerのおかげで2バイトオフになりました(sort標準ではなくNumpyのものsorted)。おかげオフ1バイト@notjagan(移動0中にcumsum

lambda x:diff(sort(cumsum([0]+x)))
from numpy import*

コードは、リストまたはNumpy配列を入力し、Numpy配列を出力する匿名関数を定義します。

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


1
うわー、今日は何か新しいことを教えてくれた。私のアプローチnumpyはずっと長くなりました。明日また来て、これに賛成する。非常に素晴らしい!
氏Xcoder

@ Mr.Xcoderありがとう!私はNumpyの専門家ではありません。Matlabでやったことをたどっただけですdiff(sort([0 cumsum(x)]))(Matlabでは[ ]連結です)
ルイスメンドー

任務完了!
ミスターXcoder

を-1バイトに移動0しますcumsum
-notjagan



4

、4バイト

Ẋ-O∫

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

説明

      -- implicit input, e.g                               [2,1,-2,-1]
   ∫  -- cumulative sum                                    [0,2,3,1,0]
  O   -- sort                                              [0,0,1,2,3]
Ẋ     -- apply function to all adjacent pairs in the list  [(0,0),(0,1),(1,2),(2,3)]
 -    --   subtract                                        [0,1,1,1]

アンデルタがある別の言語?または、より洗練された組み込みの?
氏Xcoder

@氏。Xcoderそれはcumsumがundelta
H.PWiz

@ H.PWiz実際には、空のプレフィックスを考慮に入れない限り、それは私たちがcumsumと呼ぶものではありません。
エリックアウトゴルファー

@EriktheOutgolferはい、scanl(+)0Haskellのように、それが殻です。
H.PWiz

4

Pyth、9バイト

@EriktheOutgolferのおかげで-1バイト

.+S+0sM._

テストスイート。

Pyth、10バイト

.+S.u+YNQ0

オンラインでお試しください!または、さらにテストケースを試してください


私の(削除された)答えの+0sM._ように.u+YNQ0、-1の代わりに使用できます。
エリックアウトゴルファー

@EriktheOutgolferなぜ削除したのですか?
氏Xcoder

核となるアイデアはあなたのものにあまりにも似ていると思った。
エリックアウトゴルファー

@EriktheOutgolferわかりました、ありがとう
Xcoder氏

m=+Zはの長さと同じですsM._が、悲しいことに、もっと短くなるとは思えません。
FryAmTheEggman

4

JavaScript(ES6)、57 56バイト

@ETHproductionsのおかげで1バイト節約

a=>a.map(n=>t-=n,p=t=0).sort((a,b)=>b-a).map(n=>p-(p=n))

デモ


.sort((a,b)=>a-b)それがデルタを取得する方法ですか?減算で並べ替えますか?:P
完全に人間

@totallyhuman最初map()はデルタを提供します。このコードはそれらをソートします。2番目のマップは、新しいデルタを再構築します。JS sort()メソッドは、デフォルトで辞書式順序を使用します。そのため、9を超える(悲しいことに)専用のコールバックが必要です。
アーナルド

それ-p+(p=n)は私のギアを粉砕しますが、悲しいことに、より良い方法はありません...限り
...-ETHproductions

ちょっと、送信ボタンを押さなかった> _ <しかし、とにかく、その編集でバイトを保存できると思います
...-ETHproductions

@ETHproductionsのおかげで:-)
アルノー

3

Java 8、123バイト

標準ソリューション:累積合計入力、並べ替え、差分。実質的な実装のトリックもありません。

l->{int s=l.length,d[]=new int[s+1],i=0;while(i<s)d[i+1]=d[i]+l[i++];for(java.util.Arrays.sort(d);i-->0;)l[i]=d[i+1]-d[i];}

にキャストしConsumer<int[]>ます。出力は変更された入力です。

オンラインで試す

ゴルフされていないラムダ

l -> {
    int
        s = l.length,
        d[] = new int[s + 1],
        i = 0
    ;
    while (i < s)
        d[i + 1] = d[i] + l[i++];
    for (java.util.Arrays.sort(d); i-- > 0; )
        l[i] = d[i + 1] - d[i];
}

謝辞

  • 不浄な自動インクリメントのマスター、オリビエグレゴワールのおかげで-3バイト
  • Nevayのおかげで-1バイト

1
:あなたは、あなたの刻みとあなたの全体的な計算を行う位置を再配置することにより、ゴルフ3つのバイトをすることができますl->{int s=l.length,d[]=new int[s+1],i=0;for(;i<s;)d[i+1]=d[i]+l[i++];java.util.Arrays.sort(d);for(i=0;i<s;)l[i]=-d[i]+d[++i];}(コピー/貼り付け時にSEの目に見えない文字を注意してください)
オリヴィエ・グレゴワール

1
私の新しいタイトルをありがとう;)ここに祝うための不浄さの減少for(;i>0;)l[i-1]=d[i]-d[--i];(最後のループ)
オリヴィエグレゴワール

私は自分でループを作り直しfor(;i-->0;)l[i]=d[i+1]-d[i];、同じ長さに到達しました。更新予定。
ヤコブ

2
を使用して1バイトを保存できますl->{int s=l.length,d[]=new int[s+1],i=0;while(i<s)d[i+1]=d[i]+l[i++];for(java.util.Arrays.sort(d);i-->0;l[i]=d[i+1]-d[i]);}
ネヴァイ

ああ、もちろん。ありがとう!
ヤコブ


2

R31 32バイト

-4バイト、@ user2390246のおかげで diffinv

Jarkoから+5バイト cat

cat(diff(sort(diffinv(scan()))))

stdinから読み取り、stdoutに書き込みます。diffinvは、diff指定された開始値の逆数です(デフォルトでは0)。それはだからdiff、再び編、その値が何であるかは重要ではありません。

Jarko Dubbeldamが指摘したように、5バイトのコストで結果を適切に出力する必要がありました。ああ。

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


それも私が念頭に置いていたものです。ただし、これを完全なプログラムとして(を介してsource)実行すると、何も出力されないため、印刷を処理する必要があります。
-JAD

1
使用する場合ではdiffinvなく、cumsumゼロを追加する必要はありません。
user2390246

@ user2390246うわー、とても素敵!diffinvに関するTIL。
ジュゼッペ

私も!私はそれを適用することができる以前の答えがあったかどうかを確認するために簡単な検索をしていた。
user2390246


1

Perl 6、46バイト

{[\+](0,|@_).sort.rotor(2=>-1).flat.map(*R-*)}

それを試してみてください

拡張:

{  # bare block lambda with implicit signature :(*@_)

  [\+](         # triangle reduce using &infix:«+»
    0,          # start with 0
    |@_         # Slip in the arguments from the outer block
  )             #                  (0, 2, 3, 1, 0)

  .sort         # sort the results (0,0,1,2,3)
  .rotor(2=>-1) # group in twos    ((0,0),(0,1),(1,2),(2,3))
  .flat         # flatten          (0,0,0,1,1,2,2,3)
  .map(*R-*)    # grab 2 values at a time, and subtract first from second
                # (0, 1, 1, 1)
}


1

TI-Basic(TI-84 Plus CE)、23 バイト

Prompt X
augment({0},cumSum(LX→X
SortA(LX
ΔList(LX

ユーザー入力のプロンプト。リストは、先頭に{、で区切られた数字,があり、オプションの末尾がある入力でなければなりません}

TI-Basicはトークン化された言語です。ΔList(およびcumSum(は2バイトのトークンであり、使用される他のすべてのトークンはそれぞれ1バイトです。

実行例(NAMEプログラム名および{4,-2,7,-4,0}入力として):

prgmNAME
X=?{4,-2,7,-4,0}
               {2 2 1 0 4}

説明:

Prompt X                  # 3 bytes, get list input, store in LX
augment({0},cumSum(LX→X   # 12 bytes, 
          # store the list ({0} prepended to the cumulative sum of LX) to LX
SortA(LX                  # 4 bytes, sort LX ascending
ΔList(LX                  # 4 bytes, implicitly print the difference list of LX

が必要Lですか?
ザカリー

@Zacharýリストを保存するときにそれらを省略できますが、参照時にリストの代わりに数値変数Xを参照する場合は省略します
pizzapants184

1

C ++(gcc)、136バイト

名前のないジェネリックラムダとして、入力が同様であるstd::listと仮定し、参照パラメーターを介して戻る。

[](auto&L){auto r=L.begin(),l=L.insert(r,0);while(r!=L.end())*r+++=*l++;for(L.sort(),l=r=--L.end();--l!=L.begin();*r---=*l);L.erase(l);}

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

ゴルフをしていない:

[](auto&L){
 auto r=L.begin(),
      l=L.insert(r,0); //adds a zero right in front
 while(r!=L.end())
   *r++ += *l++;       //sum left to right
 for(
  L.sort(),            //sorting invalidates the iterators
  l=r=--L.end();       //so, reinit
  --l!=L.begin();      //decrement l beforehand 
  *r-- -= *l           //diff right to left
 );
 L.erase(l);           //l==L.begin(), so this removes the temporary 0
}

1

Pyth、8バイト

.+S+M.uP

デモンストレーション

.+S+M.uP
.+S+M.uPNQ    Implicit variables
     .u  Q    Apply the following function to the input repeatedly until it
              stops changing, then output the list of values, including the
              starting value.
       PN     Remove the last element. No-op if the list is empty.
   +M         Sum each list. This gives the cumulative sums in reverse order,
              including a 0 at the end for the empty list.
  S           Sort
.+            Deltas

+1これは、累積固定小数点を使用した適切な回避策です。私は個人的にこれについても考えませんでした。
ミスターXcoder



1

VB.NET(.NET 4.5)、109バイト

Sub A(n)
Dim c=n.count-1
For i=1To c
n(i)+=n(i-1)
Next
n.Sort()
For i=c To 1 Step-1
n(i)-=n(i-1)
Next
End Sub

入力としてリストを予期し、それを直接変更する関数。その後、元のパラメーターを出力に使用できます

  1. リストを前方に追加して元のリストを再作成します(最初の要素として暗黙的な0を想定しています)
  2. 元のリストを並べ替えます
  3. 後方に移動して差を取得します(したがって、別のリストを追跡する必要はありません)(0の暗黙の最初の要素は、最初の差が最小の要素と同じであることを意味します)

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


TIOリンクを更新しますか?
テイラースコット

@TaylorScottどのように更新しますか?
ブライアンJ

TIOリンクに回答とはまったく異なるコードが表示されます
Taylor Scott

1
@TaylorScott Ahh ....なるほど。TIOはMonoを使用しているため、調整を行う必要がありましたが、.NET 4.5コンパイラを使用していました
ブライアンJ

1

APL(Dyalog)15 14バイト

ngnのおかげで-1バイト。

2-/⍋⊃¨⊂)0,+\

+\ 累計

0, ゼロを追加します

() 次の暗黙関数を適用します:

 同封(複数のアイテムを選択できるようにするため)

⍋⊃¨ 引数を並べ替える各インデックスにその中から選択させます

¯2-/ 逆のペアワイズ差

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


Dyalog '17ユーザーミーティングでCode Golf Hackathon参加者が見つけた元のソリューション:

¯2-/l[⍋l←+\0,⎕]

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

 入力を促す

0, ゼロを追加します

+\ 累計

l← として保存 l

 ソートするインデックスを見つける l

l[…を] 使用してインデックスを作成するl

¯2-/ 逆のペアワイズ差


1
ハッカソンでこれが許可されたかどうかはわかりませんが、ポイントフリースタイルで書き換えると、charを保存できます:(¯2-/⍋⊃¨⊂)0、+ \
ngn

@ngnワークショップのこの部分では、参加者にPPCGを開始しようとしていたため、ここでのルールはPPCGのルールでした。ありがとう。
アダム





0

ロダ、42バイト

{i=0{[0];[i]if i+=_}|sort|slide 2|[_2-_1]}

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

これは、Perl 6の回答に似ています.sort|sort.rotor(2=>-1).flatある|slide 2.map(*R-*)され|[_2-_1]です。

説明:

{
  i=0 /* initialize variable i */
  /* the following block recreates the original list from differences: */
  {
    [0];       /* push 0 to the stream */
    [i]if i+=_ /* add every number in the stream to i and push i back */
  }|
  sort|    /* sort the numbers */
  slide 2| /* for values i1, i2, i3, ... in the stream
              push pairs i1, i2, i2, i3, ... */
  [_2-_1]  /* calculate difference of numbers in each pair in the stream */
}

ステートメント[i]if i+=_は次と同等です

for sfv do
  if i += sfv do
    push(i)
  done
done

+=それはtruthyあるので、オペレータは、ストリームに値をプッシュしていません。また、ある種のブロック(例:)を使用して{|j|i+=j;[i]}_、追加ステートメントとプッシュステートメントを結び付けることもできますが、ifより短いものです。


0

ジュリア0.6.0(34バイト)

RおよびPython 3で行われたことのほとんどコピー

x->diff(sort(cumsum(vcat([0],x))))


0

J、10バイト

/:~&.(+/\)

説明

「スキャン合計の下でソート」:Jでは、Underコン&.ジャンクションは変換を入力の右側に適用し、次に動詞を左側に適用し(この場合はsort /:~)、逆変換を実行します。つまり、Jはスキャン合計を反転する方法を理解します。これはまさにここで必要なものです。連続する違いは、スキャン合計時にそのスキャン合計を生成する入力です。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.