การจัดเรียงแบบสุ่มคนตาบอด


18

นี่เป็นรูปแบบที่พบได้ทั่วไปสำหรับการเรียงลำดับอัลกอริทึม:

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]

ขั้นตอนวิธีการเหล่านี้ทำงานได้ดีเพราะดัชนีiและได้รับการแต่งตั้งอย่างรอบคอบบนพื้นฐานของรัฐของรายการjl

อย่างไรก็ตามจะเกิดอะไรขึ้นถ้าเรามองไม่เห็นlและต้องเลือกสุ่มสี่สุ่มห้า เราจะเรียงลำดับรายการได้เร็วแค่ไหน?


lความท้าทายของคุณคือการเขียนฟังก์ชั่นที่ผลคู่แบบสุ่มของดัชนีได้รับเพียงความยาวของ โดยเฉพาะคุณต้องเอาท์พุทสองดัชนีด้วยi, j 0 <= i < j < len(l)ฟังก์ชั่นของคุณควรทำงานกับความยาวของรายการใด ๆ แต่จะได้คะแนนในรายการความยาว 100

คะแนนของคุณคือจำนวนตัวเลือกดัชนีเฉลี่ยที่จำเป็นในการเรียงลำดับรายการสับแบบสุ่มอย่างสม่ำเสมอตามรูปแบบด้านบนซึ่งดัชนีจะถูกเลือกตามฟังก์ชั่นของคุณ

ฉันจะให้คะแนนการส่งโดยใช้จำนวนตัวเลือกดัชนีเฉลี่ยมากกว่า 1,000 ครั้งในรายการที่มีการสับแบบสุ่มที่มีความยาว 100 โดยไม่มีการป้อนซ้ำ

ฉันขอสงวนสิทธิ์ในการเรียกใช้การทดลองน้อยลงหากการส่งนั้นชัดเจนไม่ใช่การแข่งขันหรือไม่ยุติลงและฉันจะทำการทดลองเพิ่มเติมเพื่อแยกความแตกต่างของคู่แข่งชั้นนำเพื่อค้นหาผู้ชนะคนเดียว หากการส่งยอดนิยมหลายรายการยังคงอยู่ภายในระยะขอบของข้อผิดพลาดที่ขีด จำกัด ของทรัพยากรการคำนวณของฉันฉันจะประกาศผู้ชนะการส่งก่อนหน้านี้จนกว่าจะสามารถนำทรัพยากรการคำนวณอื่น ๆ มาใช้ได้


นี่คือตัวอย่างโปรแกรมการให้คะแนนใน Python:

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

ฟังก์ชั่นของคุณอาจไม่รักษาสถานะที่ไม่แน่นอนใด ๆ โต้ตอบกับตัวแปรทั่วโลกส่งผลกระทบต่อรายการlอื่น ๆ ฟังก์ชั่นของคุณการป้อนข้อมูลจะต้องมีความยาวของรายการlและจะต้องส่งออกคู่ได้รับคำสั่งของจำนวนเต็มในช่วง[0, len(l)-1](หรือที่เหมาะสมสำหรับภาษาของคุณ การจัดทำดัชนีรายการ) อย่าลังเลที่จะถามว่ามีบางอย่างได้รับอนุญาตในความคิดเห็นหรือไม่

การส่งอาจเป็นภาษาที่ใช้งานฟรี โปรดรวมสายรัดเกณฑ์การให้คะแนนหากยังไม่ได้โพสต์สำหรับภาษาของคุณ คุณสามารถโพสต์คะแนนชั่วคราว แต่ฉันจะแสดงความคิดเห็นด้วยคะแนนอย่างเป็นทางการ

การให้คะแนนคือจำนวนขั้นตอนเฉลี่ยในรายการที่เรียงลำดับในรายการที่มีการสับแบบสุ่มที่มีความยาว 100 โชคดี


2
@JoKing แน่นอน - การส่งของคุณเป็นการกระจาย
isaacg

2
ทำไมคุณไม่อนุญาตให้มีสถานะที่ไม่แน่นอน การอนุญาตหมายความว่าการส่งสามารถปรับแต่งอัลกอริทึมของพวกเขาได้ดีขึ้นเมื่อเทียบกับการหวังว่าจะเลือกรายการที่เหมาะสม
Nathan Merrill

3
@NathanMerrill หากสถานะไม่แน่นอนได้รับอนุญาตผู้ชนะก็จะเป็นเครือข่ายการเรียงลำดับซึ่งเป็นปัญหาที่ศึกษากันอยู่แล้ว
Anders Kaseorg

3
@NathanMerrill หากคุณต้องการโพสต์คำถามรู้สึกฟรี อย่างไรก็ตามไม่ใช่คำถามนี้
isaacg

3
@ NathanMerrill โอ้แน่นอน ความท้าทาย "ออกแบบเครือข่ายการเรียงลำดับที่ดีที่สุด" ในขณะที่คำถามที่น่าสนใจได้รับการศึกษามากมายในโลกการวิจัย CS ผลที่ได้คือสิ่งที่ดีที่สุดที่อาจจะเป็นเพียงแค่การนำเอางานวิจัยมาใช้เช่นการเรียงลำดับบิตนิกของแบทช์ คำถามที่ฉันถามที่นี่เป็นต้นฉบับเท่าที่ฉันรู้และควรมีพื้นที่สำหรับนวัตกรรมเพิ่มเติม
isaacg

คำตอบ:


10

Python คะแนน = 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 ยืนยันแล้ว

Python คะแนน = 1,059

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

เห็นได้ชัดว่าการจัดเรียงฟองแบบสุ่มไม่ได้ทำทุกสิ่งที่เลวร้ายยิ่งกว่าการจัดเรียงฟองปกติ

การแจกแจงที่เหมาะสมที่สุดสำหรับความยาวขนาดเล็ก

ไม่มีวิธีนี้สามารถขยายได้ถึงความยาว 100 แต่ก็น่าสนใจที่จะดู ฉันคำนวณการแจกแจงที่เหมาะสมที่สุดสำหรับกรณีเล็ก ๆ (ความยาว≤ 7) โดยใช้การไล่ระดับสีแบบลาดชันและพีชคณิตเมทริกซ์มากมาย k TH แสดงคอลัมน์น่าจะเป็นของแต่ละแลกเปลี่ยนในระยะทางที่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

คะแนนของคุณ: 11009
isaacg

2
คุณช่วยอธิบายครึ่งชีวิตของคุณ 3 ตอบได้ไหม? เป็นจุดที่จะมีอคติกับตัวเลขสุ่มไปทางด้านหน้าของรายการหรือไม่
สูงสุด

1
การกระจายที่เหมาะสมที่สุดสำหรับความยาวขนาดเล็กนั้นน่าสนใจมาก - ฉันสังเกตว่าการเอนเอียงไปทางศูนย์กลางนั้นมีประโยชน์โดยเฉพาะอย่างยิ่งสำหรับระยะทางในการแลกเปลี่ยนที่มากขึ้น
isaacg

@ Max ปัญหาทั้งหมดเกี่ยวกับการให้น้ำหนักหมายเลขสุ่มด้วยวิธีที่มีประโยชน์ วิธีนี้เกิดขึ้นเพื่อเป็นประโยชน์ โปรดทราบว่าhเป็นระยะห่างระหว่างองค์ประกอบที่สลับกัน มันไม่ได้เป็นตัวแทนของด้านหน้าหรือด้านหลัง
Anders Kaseorg

1
คะแนนครึ่งชีวิตของคุณ: 4508 ใน 10,000 ตัวอย่าง
isaacg

7

คะแนน: 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)

ลองออนไลน์!

[1,1,4,16]ดัชนีสุ่มเอาท์พุทที่มีระยะทางห่างกันได้รับการแต่งตั้งจากสม่ำเสมอ ความคิดคือการมีการผสมผสานของการแลกเปลี่ยน 1 ขั้นตอนกับการแลกเปลี่ยนในระดับที่มีขนาดใหญ่ขึ้น

ฉันทำการปรับแต่งค่าเหล่านี้สำหรับรายการความยาว 100 และมีแนวโน้มที่จะไม่เหมาะสม การค้นหาเครื่องบางอย่างอาจปรับการกระจายในระยะทางให้เหมาะสมสำหรับกลยุทธ์การสุ่มจับคู่กับระยะทางที่เลือก


1
คะแนนของคุณ: 4627 จาก 10,000 ตัวอย่าง ฉันจะรันอีกครั้งพร้อมตัวอย่างเพิ่มเติมหากคุณอยู่ในกลุ่มผู้นำหลังจากผ่านไปสองสามวัน
isaacg

3

คะแนน: 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])

ลองออนไลน์!

โซลูชันนี้เพียงเลือกค่าที่แตกต่างกันxและyสุ่มจากช่วงและส่งกลับตามลำดับ เท่าที่ฉันสามารถบอกได้สิ่งนี้ทำงานได้ดีกว่าการเลือกxจากนั้นเลือกyจากค่าที่เหลืออยู่


คะแนนของคุณ:
28493

3

Python คะแนน: 39525

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

ก่อนอื่นให้เลือกค่าสุ่มในช่วงสำหรับ -index หลังจากนั้นมันจะเลือกค่าสุ่มอื่นที่มากกว่าในช่วงสำหรับ -index[0,l1)xx [ x + 1 , l ) y
x[x+1,l)y

ลองออนไลน์


คะแนนของคุณ: 39525
isaacg

2

Python คะแนน≈ 5,000

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

พยายามด้วยค่าเอปไซลอนจำนวนมาก 0.25 น่าจะดีที่สุด

คะแนน≈ 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

แนวทางที่แตกต่าง ไม่ดีเท่าไหร่และมันตายอย่างน่ากลัวด้วยความยาวไม่สามารถหารด้วยจำนวนเซ็กเมนต์ แต่ก็ยังสนุกที่จะสร้าง


คะแนนของคุณ: ระยะทางเอ็กซ์โพเนนเชียล: 5055. การสลับแบบแบ่งกลุ่ม: 8901
isaacg

1

คะแนน: 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)

ลองออนไลน์!

ฉันไม่รู้ว่าทำไม ผมวนเวียนอยู่เพียงแค่พยายามที่ระบุไว้ในวิกิพีเดีย artical สำหรับShellsort และอันนี้ดูดีที่สุด มันได้รับคะแนนที่คล้ายกันด้วยXNOR หนึ่งโพสต์


คะแนนของคุณ: 4583 บน 10,000 ตัวอย่าง ฉันจะรันอีกครั้งพร้อมตัวอย่างเพิ่มเติมหากคุณอยู่ในกลุ่มผู้นำในอีกไม่กี่วัน
isaacg

นอกจากนี้ฉันกำลังเรียกใช้โปรแกรมที่เร็วกว่าซึ่งสุ่มตัวอย่างการแจกแจงแบบเดียวกันดังนั้นฉันจะได้ตัวอย่างมากขึ้น
isaacg

2
@isaacg เพื่อประสิทธิภาพในการทดสอบที่ดีขึ้นการเลื่อนcandidatesออกจากฟังก์ชั่นเป็นตัวแปรทั่วโลกควรใช้งานได้
tsh

1
ขอบคุณนั่นเร็วกว่าที่ฉันทำอยู่มาก
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)])

ลองออนไลน์!


คะแนนของคุณ: 4871 ใน 10,000 ตัวอย่าง
isaacg
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.