不明な値のリストを比較の量が最も少ないもので並べ替えます


8

この最適化の課題では、stdoutでユーザーにstdinで比較結果を入力するように要求することで要素を比較するだけで単一の配列をソートするプログラムを記述します。

以下のプロトコルは行ベースなので、標準出力に出力したり、標準入力から読み込んだりするたびに、改行が続くと想定されます。以下の質問全体を通して、ユーザー(読み取り:スコアリングプログラム)には、0から始まるインデックス付き配列と呼ばれる配列にソートしたい配列があると想定されていますarray。技術的な理由から、私はすべての印刷後にスタウトにフラッシュすることをお勧めします。

  1. 最初のステップとして、プログラムはnstdinから配列サイズを読み取る必要があります。
  2. その後、a < b何度でも、2つの整数を使用してstdoutに出力できます0 <= a, b < n。その後、ユーザーが入力されます1場合は標準入力でarray[a] < array[b]、そして0それ以外の場合は。
  3. 最後に、プログラムが配列の順序を正しく推定したと確信すると、プログラムはa ...stdoutに出力する必要があります...。したがって、プログラムが出力a 3 0 1 4 2する場合は、プログラムが推定したことを意味します

    array[3] <= array[0] <= array[1] <= array[4] <= array[2]
    

    あなたのプログラムはの内容を決して知らず、決して知らないことに注意してくださいarray

<stdinで配列をソートするように要求することしかできません。これらの同値により、他の比較演算を取得できます。

a > b        b < a
a <= b       !(b < a)
a >= b       !(a < b)
a != b       (a < b) || (b < a)
a == b       !(a < b) && !(b < a)

最後に、プログラムがstdoutのスコアリングプログラムと対話するため、デバッグ情報をstderrに出力します。


プログラムは、次のPythonプログラムを使用して採点されます。

from __future__ import print_function
from subprocess import Popen, PIPE
import sys, random

def sort_test(size):
    array = [random.randrange(0, size) for _ in range(size)]
    pipe = Popen(sys.argv[1:], stdin=PIPE, stdout=PIPE, bufsize=0, universal_newlines=True)
    print(str(size), file=pipe.stdin); pipe.stdin.flush()
    num_comparisons = 0
    while True:
        args = pipe.stdout.readline().strip().split()
        if args and args[0] == "a":
            answer_array = [array[int(n)] for n in args[1:]]
            if list(sorted(array)) != answer_array:
                raise RuntimeError("incorrect sort for size {}, array was {}".format(size, array))
            return num_comparisons
        elif len(args) == 3 and args[1] == "<":
            a, b = int(args[0]), int(args[2])
            print(int(array[a] < array[b]), file=pipe.stdin); pipe.stdin.flush()
            num_comparisons += 1
        else:
            raise RuntimeError("unknown command")

random.seed(0)
total = 0
for i in range(101):
    num_comparisons = sort_test(i)
    print(i, num_comparisons)
    total += num_comparisons
print("total", total)

プログラムを採点するには、と入力しますpython score.py yourprogram。スコアリングは、プログラムに各サイズ0から100のランダム配列を1つソートさせ、プログラムが要求する比較の量をカウントすることによって行われます。これらのランダムな配列は重複する可能性があり、アルゴリズムは等しい要素を処理できる必要があります。重複がある場合、等しい要素の順序に関する要件はありません。したがって、配列の場合は、または[0, 0]を出力しても問題ありません。a 0 1a 1 0

スコアリングプログラムが生成する特定の配列に合わせて最適化することはできません。RNGシードはいつでも変更できます。組み込みのソートアルゴリズムを使用した回答は、興味を引くために投稿することが許可されていますが、競合するものではありません。

最もスコアの低いプログラムが勝利します。


1
どのバージョンのPythonを使用していますか?
Leaky Nun

スコアリングアルゴリズムの実行にはどのくらい時間がかかりましたか?
Leaky Nun

入力配列の最大サイズをどのように想定できるでしょうか。
helloworld922 2016

@ helloworld922理論的には、なし-あなたの答えはどのようなサイズでも機能するはずです。しかし、それがCのような言語で労力を節約するのであれば、100要素までサポートし、100要素を含める必要があります。
orlp

Python 2と3は異なるランダムシーケンスを生成するため、スコアリングプログラムで使用されるPythonバージョンを明確にすることが重要です。あるいは、ランダム性がhashlibなどの明確に指定された決定論的なソースからのものである場合、それはより良いでしょう。
Anders Kaseorg 16

回答:


3

Python、スコア23069

これは、Ford-Johnsonマージ挿入ソートアルゴリズムを使用します。

from __future__ import print_function
import sys

def less(x, y):
    print(x, '<', y)
    sys.stdout.flush()
    return bool(int(input()))

def insert(x, a, key=lambda z: z):
    if not a:
        return [x]
    m = len(a)//2
    if less(key(x), key(a[m])):
        return insert(x, a[:m], key) + a[m:]
    else:
        return a[:m + 1] + insert(x, a[m + 1:], key)

def sort(a, key=lambda z: z):
    if len(a) <= 1:
        return a
    m = len(a)//2
    key1 = lambda z: key(z[-1])
    b = sort([insert(x, [y], key) for x, y in zip(a[:m], a[m:2*m])], key=key1)
    if len(a) % 2:
        b += [[a[-1], None]]
    for k in range(m, len(a)):
        l, i, (x, y) = max((-i.bit_length(), i, t) for i, t in enumerate(b) if len(t) == 2)
        b[:i + 1] = insert([x], b[:i], key=key1) + [[y]]
    if len(a) % 2:
        b.pop()
    return [x for x, in b]

print('a', ' '.join(map(str, sort(range(int(input()))))))

1

Python 3、28462スコア

クイックソート。ピボットは左端のアイテムです。

次の理由により、スコアが予想されます。

\ displaystyle \ sum_ {i \ mathop = 0} ^ {100} i \ log_2i = 29945.648687873225

from __future__ import print_function
import sys
size = int(input())

def less(a, b):
    print(a, "<", b); sys.stdout.flush()
    return bool(int(input()))

def quicksort(array):
    if len(array) < 2:
        return array
    pivot = array[0]
    left = []
    right = []
    for i in range(1,len(array)):
        if less(array[i],pivot):
            left.append(array[i])
        else:
            right.append(array[i])
    return quicksort(left)+[pivot]+quicksort(right)

array = list(range(size))
array = quicksort(array)

print("a", " ".join(str(i) for i in array)); sys.stdout.flush()

テストした各サイズのスコア:

size score
0 0
1 0
2 1
3 3
4 6
5 8
6 11
7 12
8 15
9 17
10 23
11 33
12 29
13 32
14 37
15 45
16 58
17 47
18 52
19 79
20 72
21 60
22 85
23 138
24 87
25 98
26 112
27 107
28 128
29 142
30 137
31 136
32 158
33 143
34 145
35 155
36 169
37 209
38 163
39 171
40 177
41 188
42 167
43 260
44 208
45 210
46 230
47 276
48 278
49 223
50 267
51 247
52 263
53 293
54 300
55 259
56 319
57 308
58 333
59 341
60 306
61 295
62 319
63 346
64 375
65 344
66 346
67 370
68 421
69 507
70 363
71 484
72 491
73 417
74 509
75 495
76 439
77 506
78 484
79 458
80 575
81 505
82 476
83 500
84 535
85 501
86 575
87 547
88 522
89 536
90 543
91 551
92 528
93 647
94 530
95 655
96 580
97 709
98 671
99 594
100 637
total 28462

@orlp ここでは、最後の行は「WindowsError:[Error 193]%1 is not a correct Win32 application。」に変換されます。
Leaky Nun

1

Python 2(非競合)、23471スコア

from __future__ import print_function
import sys
size = int(input())

def cmp(a, b):
    print(a, "<", b); sys.stdout.flush()
    return [1,-1][bool(int(input()))]

array = list(range(size))
array = sorted(array,cmp=cmp)

print("a", " ".join(str(i) for i in array)); sys.stdout.flush()

テストした各サイズのスコア:

size score
0 0
1 0
2 1
3 4
4 5
5 7
6 9
7 14
8 17
9 20
10 21
11 26
12 30
13 35
14 37
15 41
16 45
17 51
18 52
19 57
20 63
21 63
22 72
23 79
24 79
25 80
26 91
27 93
28 96
29 105
30 110
31 116
32 124
33 123
34 131
35 130
36 142
37 144
38 156
39 154
40 163
41 168
42 177
43 178
44 183
45 183
46 192
47 194
48 212
49 207
50 216
51 221
52 227
53 239
54 238
55 243
56 255
57 257
58 260
59 270
60 281
61 284
62 292
63 293
64 303
65 308
66 312
67 321
68 328
69 328
70 342
71 348
72 352
73 358
74 367
75 371
76 381
77 375
78 387
79 400
80 398
81 413
82 415
83 427
84 420
85 435
86 438
87 448
88 454
89 462
90 462
91 479
92 482
93 495
94 494
95 502
96 506
97 520
98 521
99 524
100 539
total 23471

Pythonはすでに非常に優れた並べ替え関数を実装していると思います。比較の最適な数をここで確認します:en.wikipedia.org/wiki/…これは非常に優れたベースラインのリファレンスになるようです。
16

1

Python、333300スコア

from __future__ import print_function
import sys

size = int(input())

def less(a, b):
    print(a, "<", b); sys.stdout.flush()
    return bool(int(input()))

array = list(range(size))
for _ in range(size):
    for i in range(0, size-1):
        if less(array[i+1], array[i]):
            array[i], array[i+1] = array[i+1], array[i]

print("a", " ".join(str(i) for i in array)); sys.stdout.flush()

これはサンプル・プログラムであり、最も単純な形式のバブルn*(n-1)ソートを実装し、常に配列ごとに比較を行います。

名前を付けてこのプログラムを保存してsort.py入力しましたpython score.py python sort.py


正確に言えば、それはPython 3です。私はprint関数のように見えます。
user48538

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