古典的な分類コードとゴルフの質問


11

これはコードゴルフの質問です。

入力

最も便利な任意の形式の非負整数のリスト。

出力

最も便利な形式でソートされた順序で同じリスト。

制限

  • 入力の整数の数が最悪の場合、コードはO(n log n)時間で実行する必要がnあります。これは、例えば、ランダム化されたクイックソートが出ていることを意味します。ただし、他にも多くの選択肢があります。
  • 並べ替えライブラリ/関数/類似物を使用しないでください。また、ヒープライブラリのように、ほとんどの並べ替え作業を行うものは使用しないでください。基本的に、実装するものは何でも、ゼロから実装します。

必要に応じて関数を定義できますが、実際に動作する完全なプログラムでその例を示してください。以下のすべてのテストケースで正常かつ迅速に実行されるはずです。

テストケース

In: [9, 8, 3, 2, 4, 6, 5, 1, 7, 0]
Out:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In: [72, 59, 95, 68, 84]
Out:[59, 68, 72, 84, 95]

In: [2, 2, 1, 9, 3, 7, 4, 1, 6, 7]
Out:[1, 1, 2, 2, 3, 4, 6, 7, 7, 9]

In: [2397725, 1925225, 3304534, 7806949, 4487711, 8337622, 2276714, 3088926, 4274324,  667269]
Out:[667269,1925225, 2276714, 2397725,3088926, 3304534, 4274324, 4487711, 7806949, 8337622]

あなたの答え

実装したソートアルゴリズムとソリューションの長さを回答のタイトルに記載してください。

O(n log n)時間ソートアルゴリズム

多くのO(n log n)時間アルゴリズムが存在します。この表には、それらのいくつかのリストがあります。


intersect配列の自動ソートなどの一部のセット関数。あなたもそれらを除外したいと思います。どうですかunique(重複を削除し、結果を並べ替えます)?
ルイスメンドー

@DonMuesli私は.. intersect配列を自動的にソートする場合、「類似」に分類されると思います。重複を削除すると、間違った出力が表示されます。

間違った入力を与えることについては、私に任せてください:-)その後、「重複を削除してソート」を使用できますか
ルイスメンドー

3
Nitpick:0は正の整数ではありません。(入力
ビーカー

1
これがまだコードゴルフであり、最短の解決策がまだ勝つだろうが、質問がパフォーマンスに関係するとすぐに、誰もがゴルフ言語から集まってくるのが好きです。
チョイス

回答:


8

ハスケル、87 80 89

s%[]=s
(x:a)%q|x<=q!!0=x:a%q
p%q=q%p
j(x:y:s)=x%y:j s
j a=a
r[x]=x
r s=r$j s
s=r.map(:[])

これはマージソートであり、ボトムアップで実装されます。まず、すべての要素を独自のリストにパッケージ化し、次にそれらを2行2列にマージし、再び2行2列にマージして、1つのリストが残るようにします。

(%)マージ機能
jはリストのリスト内のペアをマージし、リストの
r完全なリストは
sソート機能です。

使用法:インタープリターを実行し、と入力しs [3,5,2,6,7]ます。

編集: 私が前に物事をマージしていた方法は正しい順序ではなかったので、それを修正するために、私はさらに9文字が必要でした。


1
@Lembikプログラムをテストしたいが、Haskellをインストールしたくない場合は、ideoneを使用し、のような行を追加してmain = print (s [5,3,6,8])、ソートの結果を印刷するようにmainを設定します。
誇りに思ってhaskeller

[]%s=s最初の要素がの[]場合、(x:a)マッチは失敗し、最後のケースは要素を反転するので、それはs%[]成功するので、あなたは必要ないと思う。
nimi

あなたが勝者です!より少ないバイトを使用する唯一の答えは、O(n log n)で実行されませんでした。

@Lembikそう、ゼリーの答えが守られなかったことを忘れた。
誇りに思ってhaskeller

1
今ではそうです:)

5

JavaScript(ES6)、195 193 191 189 188 186 186 183 182 179 174 172バイト

これはヒープソートの実装です。私は誰かがより短いマージソートを思い付くと期待していますが、私はこれが好きです:P

更新:R mergesortが破られました。次はルビー:D

S=l=>{e=l.length
W=(a,b)=>[l[a],l[b]]=[l[b],l[a]]
D=s=>{for(;(c=s*2+1)<e;s=r<s?s:e)s=l[r=s]<l[c]?c:s,W(r,s=++c<e&&l[s]<l[c]?c:s)}
for(s=e>>1;s;)D(--s)
for(;--e;D(0))W(0,e)}

テスト(Firefox)


私はヒープソートの回答を書きたいと思っていましたが、Haskellではうまく機能しません。私の次の試みはJSでしょうが、あなたはそれをやった。たぶん私はまだそれをします。Idk
誇り高いハスケラー

@proudhaskeller Ah yes .. stackoverflow.com/a/2186785/2179021を調べたところです。

3

Python3、132バイト

def S(l):
 if len(l)<2:return l
 a,b,o=S(l[::2]),S(l[1::2]),[]
 while a and b:o.append([a,b][a[-1]<b[-1]].pop())
 return a+b+o[::-1]

シンプルなマージソート。バイトの多くは確か場合にのみ、これは実際には、(N Nログ)Oで実行させるために費やされたアルゴリズムではなく、実装は:O(N Nログ)にする必要があり、これを短縮することができます

Python3、99バイト

def m(a,b):
 while a+b:yield[a,b][a<b].pop(0)
S=lambda l:l[1:]and list(m(S(l[::2]),S(l[1::2])))or l

O(n)であるため、これはO(n log n .pop(0))ではなく、マージ関数をO(n ^ 2)にします。しかし、これはかなり人工的なもので、.pop(0)簡単にO(1)になる可能性があります。


これありがとう。私は間違いなく、アルゴリズムと実装がO(n log n)であることを意味しました。

明確にするために、これは132バージョンは問題ないが、99バイトバージョンは準拠していないことを意味します。

2

ジュリア、166バイト

m(a,b,j=1,k=1,L=endof)=[(j<=L(a)&&k<=L(b)&&a[j]<b[k])||k>L(b)?a[(j+=1)-1]:b[(k+=1)-1]for i=1:L([a;b])]
M(x,n=endof(x))=n>1?m(M(x[1:(q=ceil(Int,n÷2))]),M(x[q+1:n])):x

プライマリ関数が呼び出されM、ヘルパー関数が呼び出されますm。最悪の場合の複雑さとしてOn log n)を持つmerge sortを使用します

使用例:

x = [9, 8, 3, 2, 4, 6, 5, 1, 7, 0]
println(M(x))              # prints [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
println(M(x) == sort(x))   # prints true

ゴルフをしていない:

function m(a, b, i=1, k=1, L=endof)
    return [(j <= L(a) && k <= L(b) && a[j] < b[k]) || k > L(b) ?
            a[(j+=1)-1] : b[(k+=1)-1] for i = 1:L([a; b])]
end

function M(x, n=endof(x))
    q = ceil(Int, n÷2)
    return n > 1 ? m(M(x[1:q]), M([q+1:n])) : x
end

ここでジュリアに会えてうれしい。今、nimとrustも必要です:)

1
@Lembik Sp3000とDoorknobは、それぞれ私たちの住むNimとRustの専門家だと思います。うまくいけば、彼らも楽しみに参加します。;)
アレックスA.

2

R、181バイト、マージソート

L=length;s=function(S)if(L(S)<2){S}else{h=1:(L(S)/2);A=s(S[h]);B=s(S[-h]);Z=c();if(A[L(A)]>B[1])while(L(A)&L(B))if(A[1]<B[1]){Z=c(Z,A[1]);A=A[-1]}else{Z=c(Z,B[1]);B=B[-1]};c(Z,A,B)}

インデント、改行あり:

L=length
s=function(S)
    if(L(S)<2){
        S
    }else{
        h=1:(L(S)/2)
        A=s(S[h])
        B=s(S[-h])
        Z=c()
        if(A[L(A)]>B[1])
#Merge helper function incorporated from here ...
            while(L(A)&L(B))
                if(A[1]<B[1]){
                    Z=c(Z,A[1])
                    A=A[-1]
                }else{
                    Z=c(Z,B[1])
                    B=B[-1]
                }
#...to here. Following line both finishes merge function and handles 'else' case:
        c(Z,A,B)
    }

テストケース:

> L=length;s=function(S)if(L(S)<2){S}else{h=1:(L(S)/2);A=s(S[h]);B=s(S[-h]);Z=c();if(A[L(A)]>B[1])while(L(A)&L(B))if(A[1]<B[1]){Z=c(Z,A[1]);A=A[-1]}else{Z=c(Z,B[1]);B=B[-1]};c(Z,A,B)}
> s(c(2397725, 1925225, 3304534, 7806949, 4487711, 8337622, 2276714, 3088926, 4274324,  667269))
 [1]  667269 1925225 2276714 2397725 3088926 3304534 4274324 4487711 7806949 8337622
> s(c(2, 2, 1, 9, 3, 7, 4, 1, 6, 7))
 [1] 1 1 2 2 3 4 6 7 7 9
> s(c(72, 59, 95, 68, 84))
 [1] 59 68 72 84 95
> s(c(9, 8, 3, 2, 4, 6, 5, 1, 7, 0))
 [1] 0 1 2 3 4 5 6 7 8 9

2

Scala、243バイト関数(315バイトのスタンドアロンアプリ)、Mergesort

この回答は機能を目的としていますが、スタンドアロンアプリケーションに拡張することもできます。

機能のみ(243バイト):

object G{
type S=Stream[Int]
def m(f:(S,S)):S=f match{
case(x#::a,b@(y#::_))if x<=y=>x#::m(a,b)
case(a,y#::b)=>y#::m(a,b)
case(a,Empty)=>a
case(_,b)=>b}
def s(a:S):S=if(a.length>1)((q:S,w:S)=>m(s(q),s(w))).tupled(a.splitAt(a.length/2))else a
}

スタンドアロンアプリケーション(315バイト):

object G extends App{
type S=Stream[Int]
def m(f:(S,S)):S=f match{
case(x#::a,b@(y#::_))if x<=y=>x#::m(a,b)
case(a,y#::b)=>y#::m(a,b)
case(a,Empty)=>a
case(_,b)=>b}
def s(a:S):S=if(a.length>1)((q:S,w:S)=>m(s(q),s(w))).tupled(a.splitAt(a.length/2))else a
println(s(args(0).split(",").map(_.toInt).toStream).toList)
}

使用法:

関数: G.s(List(**[Paste your array here]**).toStream).toList

応用: sbt "run **[Paste your array here]**"

入力例:

scala> G.s(List(10,2,120,1,8,3).toStream).toList

(OR)

$ sbt "run 5423,123,24,563,65,2,3,764"

出力:

res1:List [Int] = List(1、2、3、8、10、120)

または

リスト(2、3、24、65、123、563、764、5423)

制約と考慮事項:

  • scalazが必要です(非常に一般的なライブラリ、ここでの並べ替えには使用されません)
  • 100%機能している(何も変更できない!)

帰属:


2

ゼリー、29バイト、マージソート

orlpのPythonの答えのように、この用途list.pop(0)でボンネット、下O(n)が、実装が正式ですO(n log n)

ṛð>ṛḢð¡Ḣ;ñ
ç;ȧ?
s2Z߀ç/µL>1µ¡

ここで試してみてください。

説明

               Define f(x, y):    (merge helper)
                 Implicitly store x in α.
ṛ    ð¡          Replace it with y this many times:
 ð>ṛḢ              (x > y)[0].
       Ḣ         Pop the first element off that list (either x or y).
        ;ñ       Append it to g(x, y).

               Define g(x, y):    (merge)
  ȧ?             If x and y are non-empty:
ç                  Return f(x, y)
                 Else:
 ;                 Return concat(x, y).

               Define main(z):    (merge sort)
       µL>1µ¡    Repeat (len(z) > 1) times:
s2                 Split z in chunks of length two.   [[9, 7], [1, 3], [2, 8]]
  Z                Transpose the resulting array.     [[9, 1, 2], [7, 3, 8]]
   ߀              Apply main() recursively to each.  [[1, 2, 9], [3, 7, 8]]
     ç/            Apply g on these two elements.     [1, 2, 3, 7, 8, 9]

説明を追加してください。

ほんの少しより多くの最後の行の下にゴルフ私ができるなら、私は見てみましょう:)説明するためにたくさんあります
リン・

実装がO(n log n)であるが、フードの下でlist.pop(0)を使用していると言うと、それはO(n)です。どういう意味ですか?

私はorlpが彼の答えで正確に書いたものを意味します:これはO(n)なので、O(n log n)ではありません.pop(0)。マージ関数をO(n ^ 2)にします。しかし、これはかなり人工的なもので、.pop(0)簡単にO(1)になる可能性があります。
リン

JellyはPythonで実装され、として実装されてい.pop(0)ます。
リン

1

ルビー、167バイト

最悪の場合のO(n log n)を持つゴルフマージソートアルゴリズム

f=->x{m=->a,b{i,j,l,y,z=0,0,[],a.size,b.size
while i<y&&j<z
c=a[i]<b[j]
l<<(c ?a[i]:b[j])
c ?i+=1:j+=1
end
l+=a[i,y]+b[j,z]}
l=x.size
l>1?m[f[x[0,l/2]],f[x[l/2,l]]]:x}

ここでテストしてください!

テストするには、コードをコピーしてウィンドウに貼り付け、puts f[x]下部に追加します。xは入力のある配列です。(もちろん、言語としてRubyを選択してください)たとえば、puts f[[2, 2, 1, 9, 3, 7, 4, 1, 6, 7]]


これありがとう!それが機能していることを見せてもらえますか?

1
リンクを追加して、テストできるようにしました。
バリューインク

1

ルビー、297バイト

ソートをマージします。関数ではなく、完全なプログラム。実行時に2つの引数が必要です。入力ファイルと出力ファイルで、それぞれ1行に1つの要素があります。

if $0==__FILE__;v=open(ARGV[0]).readlines.map{|e|e.to_i}.map{|e|[e]};v=v.each_slice(2).map{|e|a,b,r=e[0],e[1],[];while true;if(!a)||a.empty?;r+=b;break;end;if(!b)||b.empty?;r+=a;break;end;r<<(a[0]<b[0]?a:b).shift;end;r}while v.size>1;open(ARGV[1],"w"){|f|f.puts(v[0].join("\n"))if !v.empty?};end

コードが短くなる場合は、入力として配列を取得し、ソートされたシーケンスを返す関数にコードを適合させることを検討する必要があります。大量のバイトを削除できるようです。
誇りに思っているhaskeller

関数ではなく完全なプログラムとして保持する場合は、それぞれ入出力としてSTDINとSTDOUTを使用することをお勧めしますか? $stdin.readlinesすでにバイトよりも少ないバイトでopen(ARGV[0]).readlinesputsオーバーと同じopen(ARGV[1],"w"){|f|f.puts
値インク

2
またif $0==__FILE__、コードゴルフでは、このようなものは本当に不要です。また、それぞれ;を改行で置き換えることを検討することもできます。これは同じバイト数であり、(おそらく)コードの水平スクロールを削除します。また、Rubyでのゴルフのヒントを確認することをお勧めします
-daniero
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.