Klasik bir sıralama kodu golf sorusu


11

Bu bir kod golf sorusu.

Giriş

Hangi formatta olursa olsun negatif olmayan tamsayıların listesi en uygun olanıdır.

Çıktı

Aynı liste, hangi formatta olursa olsun, sıralı sırayla en uygun olanıdır.

kısıtlama

  • Kodunuz O çalıştırmak (n log) zaman gerekir kötü durumdan girişteki tamsayılar sayısıdır. Bu, örneğin rasgele dağılmış çabuk sıranın dışarıda olduğu anlamına gelir. Ancak, aralarından seçim yapabileceğiniz birçok başka seçenek var.
  • Hiçbir sıralama kitaplığı / işlevi / benzeri kullanmayın. Ayrıca sıralamanın çoğunu sizin için bir yığın kitaplığı gibi yapan hiçbir şey kullanmayın. Temel olarak, ne uygularsanız uygulayın, sıfırdan uygulayın.

İsterseniz bir işlev tanımlayabilirsiniz, ancak daha sonra gerçekten çalışan tam bir programda bunun bir örneğini gösterin. Aşağıdaki tüm test senaryolarında başarılı ve hızlı bir şekilde çalışmalıdır.

Test senaryoları

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]

Cevapların

Lütfen uyguladığınız sıralama algoritmasını ve çözümünüzün uzunluğunu cevabınızın başlığında belirtin.

O (n log n) zaman sıralama algoritmaları

Var olan birçok O (n log n) zaman algoritması vardır. Bu tabloda bazılarının bir listesi vardır .


intersectDiziyi otomatik olarak sıralamak gibi bazı ayar işlevleri . Sanırım bunları da dışlamak istiyorsun. Nasıl olur unique(kopyaları kaldır, sonucu sıralar)?
Luis Mendo

@DonMuesli Ben .. intersectotomatik olarak dizi sıralar eğer "benzer" altında geliyor düşünüyorum . Kopyaları kaldırırsanız, yanlış çıktı verirsiniz.

Yanlış giriş verme hakkında, bunu bana bırak :-) Sonra "kopyaları kaldırmak ve sıralama" kullanılabilir mi?
Luis Mendo

3
Nitpick: 0 pozitif bir tam sayı değil. ( Giriş Altında )
beher

1
Sorunun performansla bir ilgisi olur olmaz, bu hala kod golfü olmasına ve en kısa çözümün hala kazanmasına rağmen herkes golf dillerinden uzaklaşıyor.
Cyoce

Yanıtlar:


8

Haskell, 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(:[])

Bu, aşağıdan yukarıya doğru uygulanan birleştirme sıralamasıdır. ilk önce her öğeyi kendi listesine paketliyoruz ve sonra bunları ikier birer birleştiriyoruz ve tek bir listeyle bırakılıncaya kadar tekrar iki kez birleştiriyoruz.

(%)birleştirme işlevi
jlistelerdeki çiftleri birleştirir listelerin
rtam bir listesini birleştirir
ssıralama işlevidir.

Kullanım: Bir tercüman çalıştırın ve girin s [3,5,2,6,7].

Düzenleme: bir şeyleri daha önce birleştirdiğim yol doğru sipariş değildi, bu yüzden düzeltmek için 9 karaktere daha ihtiyacım vardı.


1
@Lembik programı test etmek istiyorsanız ve Haskell'i yüklemek istemiyorsanız, ideone'yi kullanabilir main = print (s [5,3,6,8])ve sıralama sonucunu yazdırmak için ana ayarlayacak gibi bir satır ekleyebilirsiniz .
gururlu haskeller

Sanırım ihtiyacın yok []%s=s, çünkü eğer ilk eleman varsa [], (x:a)maç başarısız olur ve son durum unsurları çevirir, böylece s%[]başarılı olur.
nimi

Sen kazanansın! Daha az bayt kullanan tek yanıt O (n log n) içinde çalışmadı.

@Lembik Doğru, Jelly cevabının uymadığını unuttum.
gururlu haskeller

1
Şimdi öyle görünüyor :)

5

JavaScript (ES6), 195 193 191 189 188 186 183 182 179 174 172 bayt

Bu bir yığın uygulamasıdır. Birinin daha kısa bir birleşim bulmasını bekliyorum, ama bunu beğendim: P

Güncelleme: R mergesort dayak yemiş. Sıradaki Ruby: 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)}

Test (Firefox)


Ben bir yığın cevap yazmak isterdim, ama Haskell ile gerçekten iyi çalışmıyor. Bir sonraki denemem JS olurdu, ama başardın. Belki de yine de yapacağım. Idk
proud haskeller

@proudhaskeller Ah evet .. az önce baktım stackoverflow.com/a/2186785/2179021 .

3

Python3, 132 bayt

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]

Basit birleştirme. Bunun yalnızca algoritmada çalıştığından emin olmak için çok sayıda bayt harcandı, yalnızca algoritmanın olması gerekiyor , ancak uygulamanın O (n günlüğü n) olması gerekmiyorsa , bu kısaltılabilir:

Python3, 99 bayt

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

Bu O (n günlüğü n) değil .pop(0), çünkü O (n), birleştirme işlevi O (n ^ 2) yapıyor. Ancak bu .pop(0)kolayca O (1) olabileceği gibi oldukça yapaydır .


Bunun için teşekkür ederim. Kesinlikle algoritma demekti ve uygulama O (n log n) olmalıdır.

Açık olmak gerekirse, bu 132 sürümünün iyi olduğu, ancak 99 bayt sürümünün uygun olmadığı anlamına gelir.

2

Julia, 166 bayt

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

Birincil işlev çağrılır Mve bir yardımcı işlev çağırır m. En kötü durum karmaşıklığı olarak O ( n log n ) olan birleştirme sıralaması kullanır .

Örnek kullanım:

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

Ungolfed:

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

Julia'yı burada görmek güzel. Şimdi nim ve pasa da ihtiyacımız var :)

1
@Lembik Bence Sp3000 ve Doorknob bizim asistan Nim ve Rust uzmanlarımız. Umarım onlar da eğlenceye katılırlar. ;)
Alex

2

R, 181 bayt, Mergesort

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)}

Girintili, yeni satırlarla:

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)
    }

Test senaryoları:

> 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 Bayt işlevi (315 Bayt tek başına uygulama), Mergesort

Bu yanıtın bir işlev olması amaçlanmıştır, ancak tek başına bir uygulama olarak genişletilebilir.

Yalnızca işlev (243 bayt):

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
}

Bağımsız uygulama (315 bayt):

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)
}

Kullanımı:

İşlev: G.s(List(**[Paste your array here]**).toStream).toList

Uygulama: sbt "run **[Paste your array here]**"

Örnek Giriş:

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

(OR)

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

Çıktı:

res1: Liste [Int] = Liste (1, 2, 3, 8, 10, 120)

VEYA

Liste (2, 3, 24, 65, 123, 563, 764, 5423)

Kısıtlamalar ve düşünceler:

  • Skalaz gerektirir (çok yaygın kütüphane, burada sıralama için kullanılmaz)
  • % 100 işlevsel mi (değiştirilemez!)

atıf:


2

Jöle, 29 bayt, birleştirme sıralaması

Orlp'nin Python yanıtı gibi, bu list.pop(0)da kaputun altında kullanır O(n), ancak uygulama resmi olarak O(n log n).

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

Burada deneyin.

açıklama

               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]

Lütfen biraz açıklama eklemek ister misiniz?

Açıklanacak çok şey var :) Bakalım son çizgide biraz daha golf yapabilir miyim
Lynn

Uygulamanın O (n log n) olduğunu söylediğinizde, başlık altında list.pop (0) kullandığımda, O (n) kafam karıştı. Ne demek istiyorsun?

Orlp'nin cevabında tam olarak ne yazdığını kastediyorum: Bu O (n log n) değil çünkü .pop(0)O (n), birleştirme fonksiyonunu O (n ^ 2) yapıyor. Ancak bu .pop(0)kolayca O (1) olabileceği gibi oldukça yapaydır .
Lynn

Jelly, Python'da ve olarak uygulanmaktadır .pop(0).
Lynn

1

Yakut, 167 bayt

En kötü durumda O (n log n) olan golf birleştirme sıralama algoritması

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}

Burada test edin!

Kodu test etmek, kopyalamak ve pencereye yapıştırmak için puts f[x]aşağıya ekleyin ; burada x, girişli bir dizidir. (Elbette dil olarak Ruby'yi seçtiğinizden emin olun) Örneğin,puts f[[2, 2, 1, 9, 3, 7, 4, 1, 6, 7]]


Bunun için teşekkür ederim! Siz de çalıştığını gösterebilir misiniz?

1
Test edebilmeniz için bir bağlantı ekledim.
Değer Mürekkebi

1

Yakut, 297 bayt

Sıralamayı birleştir. Bir fonksiyon yerine tam bir program. Çalışma zamanında iki bağımsız değişken gerektirir: her biri satır başına bir öğe olan girdi dosyası ve çıktı dosyası.

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

Kodunuzu kısaltırsa, kodu bir diziyi giriş olarak alan ve sıralı diziyi döndüren bir işlev olarak uyarlamayı düşünmelisiniz. Görünüşe göre sizi bir sürü bayttan kurtaracak.
gururlu haskeller

Bir işlev yerine tam bir program olarak tutacaksanız, sırasıyla giriş / çıkış olarak STDIN ve STDOUT kullanmanızı öneririm? $stdin.readlineszaten daha az bayt open(ARGV[0]).readlines, aynıputsopen(ARGV[1],"w"){|f|f.puts
Değerli

2
Ve if $0==__FILE__bir kod golf gibi şeyler gerçekten gereksizdir. Ayrıca, her birini ;yeni bir satırla değiştirmeyi düşünebilirsiniz - aynı bayt sayısıdır ve (muhtemelen) kodun yatay kaydırmasını kaldırır. Ayrıca, Ruby golf için ipuçları kontrol etmenizi öneririz .
daniero
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.