配列のサーバーソート


44

チャレンジ

整数の空でない配列が与えられた場合、例えば:

[5, 2, 7, 6, 4, 1, 3]

最初に、前のアイテムよりも大きいアイテムがない配列(つまり、非昇順配列)にそれを切断します。

[5, 2] [7, 6, 4, 1] [3]

次に、各配列を逆にします。

[2, 5] [1, 4, 6, 7] [3]

最後に、それらをすべて連結します。

[2, 5, 1, 4, 6, 7, 3]

これは、プログラムの出力/関数が返すものでなければなりません。この手順を十分に繰り返すと、配列が完全にソートされます。

ルール

  • 入力および出力は、任意の標準的な方法で提供され、適切な配列形式で行われます。
  • 入力配列が空になることはありませんが、マイナスや重複が含まれる場合があります。
  • 各整数の絶対値は常に2 31未満です。

テストケース

うまくいけば、これらはすべてのエッジケースをカバーします:

[1] -> [1]
[1, 1] -> [1, 1]
[1, 2] -> [1, 2]
[2, 1] -> [1, 2]
[2, 3, 1] -> [2, 1, 3]
[2, 1, 3] -> [1, 2, 3]
[2, 1, 2] -> [1, 2, 2]
[2, 1, 1] -> [1, 1, 2]
[3, 1, 1, 2] -> [1, 1, 3, 2]
[3, 2, 1, 2] -> [1, 2, 3, 2]
[3, 1, 2, 2] -> [1, 3, 2, 2]
[1, 3, 2, 2] -> [1, 2, 2, 3]
[1, 0, 5, -234] -> [0, 1, -234, 5]
[1, 0, 1, 0, 1] -> [0, 1, 0, 1, 1]
[1, 2, 3, 4, 5] -> [1, 2, 3, 4, 5]
[5, 4, 3, 2, 1] -> [1, 2, 3, 4, 5]
[2, 1, 5, 4, 3] -> [1, 2, 3, 4, 5]
[2, 3, 1, 5, 4] -> [2, 1, 3, 4, 5]
[5, 1, 4, 2, 3] -> [1, 5, 2, 4, 3]
[5, 2, 7, 6, 4, 1, 3] -> [2, 5, 1, 4, 6, 7, 3]
[-5, -2, -7, -6, -4, -1, -3] -> [-5, -7, -2, -6, -4, -3, -1]
[14, 5, 3, 8, 15, 7, 4, 19, 12, 0, 2, 18, 6, 11, 13, 1, 17, 16, 10, 9] -> [3, 5, 14, 8, 4, 7, 15, 0, 12, 19, 2, 6, 18, 11, 1, 13, 9, 10, 16, 17]

得点

これはであるため、バイト単位の最短コードが優先されます。


4
このソート方法の大事な点は何ですか?
mbomb007 16

1
@ mbomb007 big-o表記法はあまり理解していませんが、1回の反復はO(n)であると思います。それに最悪の場合のn回の反復を掛けると、O(n ^ 2)が得られます(最悪の場合、最高の場合は1回の反復でO(n)になります)。
ETHproductions 16

1
右の私には音、しかしそれの価値配列を逆転させることは非常に効率的な操作ではないと指摘、それは遅いですので、O(n^2)
DJMcMayhem

2
@WheatWizardが配列を反転させるには、配列のコピーのためのスペースは必要なく、単一の要素のためのスペースのみが必要です。とですO(n)。最初と最後の要素を交換し、次に中間停止点に到達したときに2番目と2番目の要素を交換します。
Jasen

逆転はですがO(n)、逆転はアルゴリズムに直接組み込むことができます(これが私のJSの答えです)。各反復は配列内の各項目を1回ループするため、単一の反復はO(n)です。(私は思う...)
ETHproductions

回答:


19

JavaScript(ES6)、64バイト

f=([n,...a],z=[],q=[n,...z])=>a+a?n<a[0]?[...q,...f(a)]:f(a,q):q

再帰FTW!ここで使用される基本的なアルゴリズムは、配列内の現在の非昇順の実行を追跡し、昇順の要素が見つかるたびにそれを「返す」ことです。アイテムがなくなるまで、これを再帰的に繰り返し、結果を連結します。各実行を([n,...z]ではなく[...z,n])逆に作成することにより、時間.reverse()がかからずに費用をかけずに済みます。

テストスニペット


配列が最初のパラメータにどのように解析されるか説明できますか[n,...a]。なにn?それはあなたの配列の最初のアイテムですか?
オリバー

1
@obarakon正しい。nは配列の最初の項目であり、配列aの残りの部分です。詳細はこちらをご覧ください。
ETHproductions 16

ありがとうございました。それはとても役に立ちました。最初のパラメーターは配列なので、なぜ...a?を含める必要があるのですか?それはちょうどあなたが利用できるようにするためですnか?お電話の際は、もう一つは、f(a,q)、ないqパラメータに設定されますかz
オリバー

1
まあ@obarakon、f=([n])=>...最初の要素だけをキャプチャするだろう、とf=([n,a])=>...だけ最初にキャプチャしますnと第二をa。何をするかの別の方法f=([n,...a])=>,,,はそうでしょうf=a=>(n=a.unshift(),...
ETHproductions

1
またz、関数の2番目のパラメーターであるため、f(a,q)が呼び出されると、fと見なされzます。お役に立てれば!
ETHproductions 16


11

ゼリー、8バイト

Ṁ;<œṗ³UF

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

説明:

Ṁ;         Prepend the list [a1, a2… an] with its maximum.
  <        Elementwise compare this with the original list:
           [max(a) < a1, a1 < a2, …, a(n-1) < an, an]
           The first element is always 0.
   œṗ³     Partition the original list (³) at the indices
           of the non-zero values in the working list.
           (The spurious `an` at the end of the left argument,
           resulting from comparing lists of different sizes,
           is ignored by this operation, thankfully.)
      U    Reverse each part.
       F   Flatten.

1
あなたの答えを見たとき、私はSave Editsを押す寸前でした...よくやった。
デニス

@Dennis Heh、あなたはDyalogをパーティションに追加しましたが、APL2パーティションはどうですか?
アダム16

11

JavaScript(ES6)、70バイト

確かに、これはすでにETHproductionsの回答beatられていますが、これは再帰を使用せずにこれまでに考え出した最高の方法です。

a=>a.map((n,i)=>a[x=[...o,...r=[n,...r]],i+1]>n&&(o=x,r=[]),r=o=[])&&x

注:との両方roまったく同じオブジェクトに初期化するとr = o = []、危険なアイデアのように見える場合があります。ただし、を使用した最初の反復でrすぐに独自のインスタンス(の最初の要素を含む)が割り当てられるため、ここで行うのは安全です。ar = [n, ...r]

テストケース


2
心配いりません。さまざまなアプローチを見るのが大好きです。そして、ある人はゴルフの後、他の人よりも短くなることがよくあります:
ETHproductions

8

MATL、15バイト

lidO>vYsGhXSOZ)

入力は、形式の列ベクトルです[5; 2; 7; 6; 4; 1; 3](セミコロンは行区切り文字です)。

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

[5; 2; 7; 6; 4; 1; 3]例として入力を取ります。

説明

l     % Push 1
      % STACK: 1
i     % Push input
      % STACK: 1, [5; 2; 7; 6; 4; 1; 3]
d     % Consecutive differences
      % STACK: 1, [-3; 5; -1; -2; -3; 2]
O>    % Test if greater than 0, element-wise
      % STACK: 1, [0; 1; 0; 0; 0; 1]
v     % Concatenate vertically
      % STACK: [1; 0; 1; 0; 0; 0; 1]
Ys    % Cumulative sum
      % STACK: [1; 1; 2; 2; 2; 2; 3]
G     % Push input again
      % STACK: [1; 1; 2; 2; 2; 2; 3], [5; 2; 7; 6; 4; 1; 3]
h     % Concatenate horizontally
      % STACK: [1 5; 1 2; 2 7; 2 6; 2 4; 2 1; 3 3]
XS    % Sort rows in lexicographical order
      % STACK: [1 2; 1 5; 2 1; 2 4; 2 6; 2 7; 3 3]
OZ)   % Get last column. Implicitly display
      % STACK: [2; 5; 1; 4; 6; 7; 3]

Octaveへの回答を翻訳して31バイト節約しました!
rahnema1 16


5

Python 2、100バイト

本当にひどいゴルフですが、私は自分の解決策を投稿したかったのです(1つは単純にゴルフデニスに勝るものではありません) ...

d=input();L=[];x=0;d+=-~d[-1],
for i in range(1,len(d)):
 if d[i]>d[i-1]:L+=d[x:i][::-1];x=i
print L

repl.itでテストしてください!

入力は、などのPythonリストリテラルとして指定する必要があります[5, 3, 4, 2, 6, 1]

基本的な考え方は、Pythonのスライス構文を多用し、配列から必要な各セクションをスライスし、それを逆にして、新しい配列に追加することです。


私は最初の行ができると思いますd,L,x=input(),[],0;d+=...
ダニエル

まったく同じバイトカウントの
@Dopapp


4

網膜、163バイト

はい、私はこれがどれほど恐ろしいことか知っています。ゼロとネガをサポートすることだったスーパー楽しいです。バイトカウントはISO 8859-1エンコーディングを前提としています。

\d+
$*
(?<=-1*)1
x
-

x,1
x¶1
\b(1+),(1+\1)\b
$1¶$2
,,1
,¶1
x,(¶|$)
x¶¶
(?<=\b\1x+(?=,(x+))),\b
¶
O%$#`.(?=(.*))
$.1
+`¶
,
\bx
-x
(\w+)
$.1
^,
0,
,$
,0
,,
,0,
^$
0

オンラインで試す

説明:

\d+                         # Convert to unary
$*
(?<=-1*)1                   # Replace negatives with x's instead of 1's
x
-                           # Remove minus sign

x,1                         # Separate if negative before positive
x¶1
\b(1+),(1+\1)\b             # or greater positive follows a positive
$1¶$2
,,1                         # or positive follows a zero
,¶1
x,(¶|$)                     # or zero follows a negative
x¶¶
(?<=\b\1x+(?=,(x+))),\b     # or negative follows a negative of greater magnitude.
¶
O%$#`.(?=(.*))              # Swear at the input, then reverse each line
$.1
+`¶                         # Remove breaks, putting commas back
,
\bx                         # Put the minus signs back
-x
(\w+)                       # Replace unary with length of match (decimal)
$.1
^,                          # Do a bunch of replacements to resurrect lost zeros
0,
,$
,0
,,
,0,
^$
0

4

05AB1E19 18 16 14バイト

Luis Mendoのソーティングトリックを使用して2バイトを保存しました

ü‹X¸ì.pO¹)ø{ø¤

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

説明

入力例 [5, 2, 7, 6, 4, 1, 3]

ü‹               # pair-wise less-than
                 # STACK: [0, 1, 0, 0, 0, 1]
  X¸ì            # prepend a 1
                 # STACK: [1, 0, 1, 0, 0, 0, 1]
     .p          # prefixes
       O         # sum
                 # STACK: [1, 1, 2, 2, 2, 2, 3]
        ¹        # push input
                 # STACK: [1, 1, 2, 2, 2, 2, 3], [5, 2, 7, 6, 4, 1, 3]
         )       # wrap stack in list
                 # STACK: [[1, 1, 2, 2, 2, 2, 3], [5, 2, 7, 6, 4, 1, 3]]
          ø      # zip
                 # STACK: [[1, 5], [1, 2], [2, 7], [2, 6], [2, 4], [2, 1], [3, 3]]
           {     # sort
                 # STACK: [[1, 2], [1, 5], [2, 1], [2, 4], [2, 6], [2, 7], [3, 3]]
            ø    # zip
                 # STACK: [[1, 1, 2, 2, 2, 2, 3], [2, 5, 1, 4, 6, 7, 3]]
             ¤   # tail
                 # OUTPUT: [2, 5, 1, 4, 6, 7, 3]

以前の16バイトソリューション

Dü‹X¸ì.pO.¡€g£í˜

それらの改行は素晴らしくそれを説明しました... :-P
Stewie Griffin

@StewieGriffin:ええ、説明を書き直す前にコードを変更して投稿しました:P
Emigna

4

JavaScript(ECMA 6)、121の 128 125 119 108バイト

f=a=>{p=a[0],c=[],b=[];for(e of a){e>p&&b.push(c.reverse(c=[]));c.push(p=e)}return[].concat.call([],...b,c)}

ラムダ式は単一のArrayパラメーターを取りますa

@ETHproductionsが私の最初の間違いを見つけてくれてありがとう。


いいね!return(b+","+c).split`,` 最後に数バイトを節約することができると思います。
ETHproductions 16

1
さらに良いのは、のc.unshift代わりにc.pushを使用して、リバースする必要をなくすことができますc。これを実行した後、94バイトを取得しました。
ETHproductions 16

3

Ruby、60 55バイト

s=->x{x.slice_when{|p,q|p<q}.map{|z|z.reverse}.flatten} 

チャレンジが要求したものとほぼ同じです。私はラムダ定義されたs配列を受け取り、xおよびサーバ次の要素は、より大きくなるであろう小さな部分にそれを(スライス)。これにより列挙子が返され、マップを呼び出してピースの順序を逆にしてから、最後にすべての要素をフラット化して、定義された順序で要素を1つの配列に連結します。

テスト

p s[[1]]===[1]
p s[[1, 1]]===[1, 1]
p s[[1, 2]]===[1, 2]
p s[[2, 1]]===[1, 2]
p s[[2, 3, 1]]===[2, 1, 3]
p s[[2, 1, 3]]===[1, 2, 3]
p s[[2, 1, 2]]===[1, 2, 2]
p s[[2, 1, 1]]===[1, 1, 2]
p s[[3, 1, 1, 2]]===[1, 1, 3, 2]
p s[[3, 2, 1, 2]]===[1, 2, 3, 2]
p s[[3, 1, 2, 2]]===[1, 3, 2, 2]
p s[[1, 3, 2, 2]]===[1, 2, 2, 3]
p s[[1, 0, 5, -234]]===[0, 1, -234, 5]
p s[[1, 0, 1, 0, 1]]===[0, 1, 0, 1, 1]
p s[[1, 2, 3, 4, 5]]===[1, 2, 3, 4, 5]
p s[[5, 4, 3, 2, 1]]===[1, 2, 3, 4, 5]
p s[[2, 1, 5, 4, 3]]===[1, 2, 3, 4, 5]
p s[[2, 3, 1, 5, 4]]===[2, 1, 3, 4, 5]
p s[[5, 1, 4, 2, 3]]===[1, 5, 2, 4, 3]
p s[[5, 2, 7, 6, 4, 1, 3]]===[2, 5, 1, 4, 6, 7, 3]
p s[[-5, -2, -7, -6, -4, -1, -3]]===[-5, -7, -2, -6, -4, -3, -1]
p s[[14, 5, 3, 8, 15, 7, 4, 19, 12, 0, 2, 18, 6, 11, 13, 1, 17, 16, 10, 9]]===[3, 5, 14, 8, 4, 7, 15, 0, 12, 19, 2, 6, 18, 11, 1, 13, 9, 10, 16, 17]

1
ようこそ、素敵な<S>最初の</ S>第二答え、このチェック:codegolf.stackexchange.com/questions/363/...を
GB

どうもありがとう。あなたが提供したリンクで提案されているように、これをラムダに変え、そのようにして5バイトを節約しました。
manonthemat

2

Brachylog、10バイト

~c:{>=r}ac

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

説明

~c            Deconcatenate the Input
  :{>=r}a     Each resulting sublist must be non-increasing, and then reverse it
         c    Concatenate

Brachylog'sはc、逆に実行した場合、必ず最初に少数のリストに分割しようとしますか?

@ ais523はい、そうです。
16

1

Dyalog APL7 15 バイト

が必要⎕ML←3です。これは多くのシステムでデフォルトです。*

{∊⌽¨⍵⊂⍨1+⍵-⌊/⍵}

参加(フラット化)

⌽¨ それぞれ反転

⍵⊂⍨ 引数は、対応する各要素がその前の要素よりも大きい場所をカットすることで分割*

1+ ワンプラス

⍵- 引数マイナス

⌊/⍵ 引数の最小要素


古い7バイトのソリューションは、正でない整数で失敗します。

が必要⎕ML←3です。これは多くのシステムでデフォルトです。*

∊⌽¨⊆⍨⎕

参加(平坦化)

⌽¨ それぞれ反転

⊂⍨ 自己分割*


*パーティション()は、対応する左引数が前の引数よりも大きい場合に、右引数を切り取る関数です。(残念ながら、負でない整数のみを受け入れ、ゼロには特別な意味があります。)バージョン16以降、この機能はグリフを使用してすべてのシステム(を含むシステムでも⎕ML≠3)で使用できます


1

Haskell、49バイト

(a:b)%l|any(<a)l=l++b%[a]|1<2=b%(a:l)
_%l=l
(%[])

使用例:(%[]) [5,2,7,6,4,1,3]-> [2,5,1,4,6,7,3]

再帰的アプローチ。この関数%は、最初のパラメーターとして入力リストを受け取り、lこれまで非昇順のチャンクを追跡するアキュムレーターを(逆順で)受け取ります。入力リストが空で、結果がアキュムレータになると、基本ケースに到達します。入力リストが空ではなく、最初の要素aが現在のチャンクに収まらない場合(any(<a)l)、アキュムレーターを返し、リストの残りの部分にa新しいアキュムレーターとして再帰呼び出しを追加します(l++b%[a])。それ以外の場合は、リストの残りの部分で再帰呼び出しを行い、aアキュムレータの先頭に追加しb%(a:l)ます()。メイン関数(%[])%、空のアキュムレーターで呼び出します。



1

R、64バイト

cat(unlist(lapply(split(x<-scan(),cumsum(c(F,diff(x)>0))),rev)))

stdinから入力を読み取ります。入力をベクトルのリストに分割します。split()これには、入力をグループ化する因子変数が必要です。係数は、差が正の論理ベクトルの累積合計を取ることによって作成されます。

ベクトルを考えます:

x=c(5, 2, 7, 6, 4, 1, 3)

ここで、差分を取得してF実行y=c(F,diff(x)>0)することで先頭に追加すると、次の論理ベクトルが生成されます。

[1] FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE

累積和を取ると、cumsum(y)各グループがsplit関数と組み合わせることができる一意の因子によって表されるベクトルが生成されます。

[1] 0 0 1 1 1 1 2

diffinvではなくを使用して60バイトcumsum
ジュゼッペ

1

オクターブ、75 44バイト

基づいてMATL答え @LuisMendoの

@(a)sortrows([cumsum([1;diff(a)>0]),a])(:,2)

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

前の答え

@(a)[fliplr(mat2cell(f=fliplr(a),1,diff(find([1,diff(f)<0,numel(a)])))){:}]

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

配列を逆にします

f=fliplr(a)

の最初の違いを取る f

d = diff(f);

次の要素が前の要素よりも小さい位置を見つける

p=find([1,diff(f)<0,numel(a)])

位置の最初の差は各サブ配列の長さを返します

len=diff(p)

各サブ配列の長さを使用しmat2cellて、配列をネストされた配列リストに分割します

nest = mat2cell(f,1,len);

ネストされたリストを逆にする

rev_nest = fliplr(nest) 

ネストされたリストをフラット化します

[rev_nest{:}]


0

Perl 6、59バイト

{map |+«*.[0].reverse,m/:s([(\-?\d+)<?{[>=] $0}>] +)+/[0]}

正規表現ベースのソリューション。
これはSparta Perlだから!!

  • m/ /:入力配列を文字列化し、正規表現と照合します。
  • (\-? \d+):番号を照合し、としてキャプチャします$0
  • <?{ [>=] $0 }>$0現在のサブマッチでこれまでにキャプチャされたすべてが非昇順である場合にのみ一致するゼロ幅アサーション。
  • ([ ] +)+:最後の2つのステップをできるだけ頻繁に繰り返します。それ以外の場合は、新しいサブマッチを開始します。
  • map , [0]:サブマッチを繰り返します。
  • |+«*.[0].reverse:それぞれについて、で一致した値のリストを取得し、$0それを逆にし、値を数値に強制し()、それらを外側のリストに入れます(|)。

Perl 6、63バイト

sub f(\a){flat $_,f a[+$_..*]with first {[<=] $_},:end,[\R,] a}

再帰的なリスト処理ソリューション。
思っていたよりも面倒。
この言語には便利なビルトインがたくさんありますが、リストのパーティション分割(Ruby slice_whenやHaskellのような)はありませんtakeWhile


0

スタック、非競合、34バイト

まだこの言語を絶えず開発しています。

{e.b:e b last<}chunkby$revmap flat

議論はTOSにあります。ここで試してみてください!

chunkby関数を受け取り、その関数を満たす連続したデータの配列を収集します。関数は次のとおりです。

{e.b:e b last<}
{e.b:         }  function with arguments [e, <unused>, b]--the element, <the index>, and the
                 chunk being built
     e       <   check if e is less than
       b last    the last element of b

これにより、配列は厳密に減少します。

$revmapは基本的に[rev]map各項目を逆にします。

flat 最後に配列を平坦化します。


実際に配列をソートするためのいくつかの楽しみ:

[{e.b:e b last<}chunkby$revmap flat] @:sortstep
[$sortstep periodloop] @:sort

10:> @arr
arr out
arr shuf @arr
arr out
arr sort out

この出力(例):

(0 1 2 3 4 5 6 7 8 9)
(4 5 1 0 6 7 2 8 9 3)
(0 1 2 3 4 5 6 7 8 9)

0

Python、151 139バイト

@ Flp.Tkcのおかげで12バイトを節約できました!

@ Flp.Tkcの近く、ましてや...

def s(l):
 r=[];i=j=0
 while j<len(l)-1:
  if l[j+1]>l[j]:r+=l[i:j+1][::-1],;i=j+1
  j+=1
 r+=l[i:j+1][::-1],;return[i for s in r for i in s]

追加を使用する代わりに+= data,、末尾のコンマを使用して暗黙的にタプルを作成します。タプルはリストと連結され、リストの最後の要素としてデータが追加されます。この文脈では、やるr+=l[i:j+1][::-1],
FlipTack


0

Python 3、191バイト

a=[int(i)for i in input().split()]
while a!=sorted(a):
 b=[[]]
 for i,j in enumerate(a):
  if a[i-1]<j:b+=[[j]]
  else:b[-1]+=[j]
 a=[]
 for l in[k[::-1]for k in b]:a+=[k for k in l]
print(a)

sortedここでチェックする関数を使用することが許可されているかどうかはわかりませんが、それに対する正当な理由を考えることができず、バイトカウントが約30バイト減少しました。


0

Clojure、105バイト

#(filter number?(mapcat reverse(partition-by not(mapcat(fn[[a b]][a(< b a)])(partition 2 1(conj % 1))))))

連続した番号でペアに分割し、それらの間に入れtrueたりfalse、それらの間にパーティションを配置nottrueたり、番号をとにしfalseたりfalse true、パーティションを反転させて数値を保持します。

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