Kör Rastgele Sıralama


18

İşte algoritmaları sıralamak için oldukça yaygın bir model:

def sort(l):
    while not is_sorted(l):
         choose indices i, j
         assert i < j
         if l[i] > l[j]:
             l[i], l[j] = l[j], l[i]

Bu algoritmalar iyi çalışır çünkü indeksler ive jlistenin durumuna göre dikkatlice seçilir l.

Ancak, göremedik lve körü körüne seçmek zorunda kalsaydık? Listeyi ne kadar hızlı sıralayabiliriz?


Zorluğunuz, sadece uzunluğu göz önüne alındığında, rastgele bir indeks çifti veren bir fonksiyon yazmaktır l. Özellikle, çıkış iki endeksleri, zorunluluk i, jile 0 <= i < j < len(l). İşleviniz herhangi bir liste uzunluğu üzerinde çalışmalıdır, ancak 100 uzunluk listesinde puanlanacaktır.

Skorunuz, indekslerin fonksiyonunuza göre seçildiği, yukarıdaki desene göre, rastgele rastgele karıştırılmış bir listeyi sıralamak için gerekli ortalama indeks seçenekleri sayısıdır.

Başvuruları puanlayacağım, tekrarlanan girişler olmadan 100 rastgele bir şekilde karıştırılmış 100 uzunluklu bir listede 1000 denemenin ortalama endeks seçeneği sayısını alacağım.

Gönderi açıkça rekabetçi değilse veya feshedilmezse daha az deneme yapma hakkımı saklıyorum ve en iyi rakipleri tek bir kazanan bulmak için farklılaştırmak için daha fazla deneme yapacağım. Hesaplama kaynaklarımın sınırında birden fazla en üst bildirim hata payı içinde kalırsa, daha fazla hesaplama kaynağı getirilinceye kadar kazananı daha önce bildireceğim.


İşte Python'da bir örnek puanlama programı:

import random
def is_sorted(l):
    for x in range(len(l)-1):
        if l[x] > l[x+1]:
            return False
    return True

def score(length, index_chooser):
    steps = 0
    l = list(range(length))
    random.shuffle(l)

    while not is_sorted(l):
        i, j = index_chooser(length)
        assert (i < j)
        if l[i] > l[j]:
            l[i], l[j] = l[j], l[i]
        steps += 1
    return steps

İşleviniz, etkileşim küresel değişkenler, herhangi değişken durumunu korumak listesini etkilemeyebilir l, vb Kişisel işlevin sadece giriş listesinin uzunlukta olmalıdır lve çıkış aralığında tamsayılar bir sipariş çifti gerekir [0, len(l)-1](veya dil yıllardan için mülk liste indeksleme). Yorumlarda bir şeye izin verilip verilmediğini sormaktan çekinmeyin.

Başvurular herhangi bir ücretsiz dilde olabilir. Eğer diliniz için henüz bir tane yayınlanmamışsa lütfen bir puanlama koşum takımı ekleyin Geçici bir puan gönderebilirsiniz, ancak resmi puanla bir yorum bırakacağım.

Puanlama, eşit olarak rastgele karıştırılmış uzunluk 100 listesinde sıralanmış bir listeye yapılan ortalama adım sayısıdır. İyi şanslar.


2
@JoKing Gerçekten - gönderiminiz bir dağıtımdır
isaacg

2
Değişken duruma neden izin vermiyorsun? İzin vermek, gönderimlerin doğru öğelerin seçilmesini ummak yerine algoritmalarında daha iyi ayar yapabileceği anlamına gelir.
Nathan Merrill

3
@NathanMerrill Değişebilir duruma izin verildiyse, kazanan sadece zaten iyi çalışılmış bir sorun olan bir sıralama ağı olacaktır .
Anders Kaseorg

3
@NathanMerrill Bu soruyu göndermek istiyorsanız, çekinmeyin. Ancak bu soru değil.
isaacg

3
@NathanMerrill Ah, tabi. İlginç bir soru olsa da, "En iyi sıralama ağını tasarlayın" sorunu CS araştırma dünyasında çok çalışılmıştır. Sonuç olarak, en iyi başvurular muhtemelen sadece Batcher'in bitonik türü gibi araştırma makalelerinin uygulamalarından oluşacaktır. Burada sorduğum soru bildiğim kadarıyla orijinal ve bu yüzden inovasyon için daha fazla yer olmalı.
isaacg

Yanıtlar:


10

Python, skor = 4508

def half_life_3(length):
    h = int(random.uniform(1, (length / 2) ** -3 ** -0.5) ** -3 ** 0.5)
    i = random.randrange(length - h)
    return i, i + h

Half-Life 3 doğruladı.

Python, skor = 11009

def bubble(length):
    i = random.randrange(length - 1)
    return i, i + 1

Görünüşe göre rastgele bir kabarcık sıralaması normal kabarcık sıralamasından çok daha kötü değildir.

Küçük uzunluk için optimum dağılımlar

Bunun 100 uzunluğa kadar uzatılmasının bir yolu yok, ama yine de bakmak ilginç. Degrade iniş ve birçok matris cebiri kullanarak küçük durumlar (uzunluk ≤ 7) için en uygun dağılımları hesapladım. K sütunu gösterir inci mesafe her takas olasılığı k .

length=1
score=0.0000

length=2
1.0000
score=0.5000

length=3
0.5000 0.0000
0.5000
score=2.8333

length=4
0.2957 0.0368 0.0000 
0.3351 0.0368 
0.2957 
score=7.5106

length=5
0.2019 0.0396 0.0000 0.0000 
0.2279 0.0613 0.0000 
0.2279 0.0396 
0.2019 
score=14.4544

length=6
0.1499 0.0362 0.0000 0.0000 0.0000 
0.1679 0.0558 0.0082 0.0000 
0.1721 0.0558 0.0000 
0.1679 0.0362 
0.1499 
score=23.4838

length=7
0.1168 0.0300 0.0041 0.0000 0.0000 0.0000 
0.1313 0.0443 0.0156 0.0000 0.0000 
0.1355 0.0450 0.0155 0.0000 
0.1355 0.0443 0.0041 
0.1313 0.0300 
0.1168 
score=34.4257

Puanınız: 11009
isaacg

2
Yarı ömür 3'ün cevabını biraz açıklayabilir misin? Sadece rasgele sayıyı listenin önüne doğru yöneltmek mi?
Maksimum

1
Küçük uzunluk için en uygun dağılımlar çok ilgi çekicidir - merkeze doğru eğilmenin, özellikle daha büyük takas mesafesi için yararlı olduğunu fark ettim.
isaacg

@Max Tüm sorun, rastgele sayıları yararlı şekillerde saptırmakla ilgilidir; bu şekilde faydalı oldu. Not htakas elemanları arasındaki mesafedir; önü veya arkayı temsil etmez.
Anders Kaseorg

1
Yarılanma ömrü skorunuz: 10000 numunede 4508.
isaacg

7

Puan: 4627

def rand_step(n):
	step_size = random.choice([1, 1, 4, 16])
	
	if step_size > n - 1:
		step_size = 1 
	
	start = random.randint(0, n - step_size - 1)
	return (start, start + step_size)

Çevrimiçi deneyin!

Uzaklığı eşit olarak seçilen rasgele indeksler çıktılar [1,1,4,16]. Fikir, daha büyük ölçeklerde 1 adımlı swapların swaplarla karıştırılmasıdır.

100 uzunluklu listeler için bu değerleri el ile ayarladım ve muhtemelen optimal olmaktan uzaklar. Bazı makine aramaları, seçilen mesafe ile rastgele çift stratejisi için mesafeler arasındaki dağılımı muhtemelen optimize edebilir.


1
Puanınız: 10.000 örnek üzerinde 4627. Birkaç gün sonra liderler arasındaysanız, daha fazla örnekle tekrar çalışacağım.
isaacg

3

Puan: 28493

def x_and_y(l):
    x = random.choice(range(l))
    y = random.choice(range(l))
    while y == x and l != 1: y = random.choice(range(l))
    return sorted([x,y])

Çevrimiçi deneyin!

Bu çözüm , aralık için xve yrastgele farklı değerleri seçer ve bunları sıralı olarak döndürür. Anlayabildiğim kadarıyla, bu kalan değerlerden xseçim yapmaktan daha sonra daha iyi performans gösteriyor y.


Puanınız: 28493
isaacg

3

Python, skor: 39525

def get_indices(l):
    x = random.choice(range(l-1))
    y = random.choice(range(x+1,l))
    return [x,y]

[0,l-1)x
x[x+1,l)y

Çevrimiçi deneyin.


Puanınız: 39525
isaacg

2

Python, skor ≈ 5000

def exponentialDistance(n):
    epsilon = 0.25
    for dist in range(1, n):
        if random.random() < epsilon:
            break
    else:
        dist = 1
    low = random.randrange(0, n - dist)
    high = low + dist
    return low, high

Bir dizi epsilon değeriyle denenmiş, 0.25 en iyisi gibi görünüyor.

Puan ≈ 8881

def segmentedShuffle(n):
    segments = 20
    segmentLength = (n - 1) // segments + 1

    if random.random() < 0.75:
        a = b = 0
        while a == b or a >= n or b >= n:
            segment = random.randrange(segments)
            a = random.randrange(segmentLength) + segment * segmentLength
            b = random.randrange(segmentLength) + segment * segmentLength
        return sorted([a, b])

    highSegment = random.randrange(1, segments)
    return highSegment * segmentLength - 1, highSegment * segmentLength

Farklı bir yaklaşım. O kadar iyi değil ve parça sayısına bölünemeyen, ancak inşa etmek hala eğlenceli olan uzunlukla korkunç bir şekilde ölüyor.


Puanlarınız: Üstel mesafe: 5055. Bölümlenmiş shuffle: 8901
isaacg

1

Puan: 4583

def rand_shell(l):
    steps = [1, 3, 5, 9, 17, 33, 65, 129]
    candidates = [(left, left + step)
            for (step, nstep) in zip(steps, steps[1:])
            for left in range(0, l - step)
            for i in range(nstep // step)
    ]
    return random.choice(candidates)

Çevrimiçi deneyin!

Neden olduğu hakkında hiçbir fikrim yok. Sadece wikipedia'da kabuklar için sanatsal olarak listelenen dizileri denedim . Ve bu en iyisi gibi görünüyor. Gönderilen xnor ile benzer bir puan alır .


Puanınız: 10.000 örnek üzerinde 4583. Birkaç gün içinde liderler arasındaysanız, daha fazla örnekle tekrar çalışacağım.
isaacg

Ayrıca, aynı dağıtım örnekleri daha hızlı bir program çalıştırıyorum, böylece daha fazla örnek alabilirsiniz.
isaacg

2
@isaacg Daha iyi test performansı için, candidatesglobal değişken olarak işlevden çıkmak gerekir.
tsh

1
Teşekkürler, yaptığımdan çok daha hızlı.
isaacg

1

Python 2 , 4871

import random
def index_chooser(length):
    e= random.choice([int(length/i) for i in range(4,length*3/4)])
    s =random.choice(range(length-e))
    return [s,s+e]
def score(length, index_chooser):
    steps = 0
    l = list(range(length))
    random.shuffle(l)
    while True:
        for x in range(length-1):
            if l[x] > l[x+1]:
                break
        else:
            return steps
        i, j = index_chooser(length)
        assert(i < j)
        if l[i] > l[j]:
            l[i], l[j] = l[j], l[i]
        steps += 1

print sum([score(100, index_chooser) for t in range(100)])

Çevrimiçi deneyin!


Puanınız: 4871 on 10000 örnek
isaacg
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.