Sắp xếp danh sách các giá trị chưa biết với số lượng so sánh ít nhất


8

Trong thử thách tối ưu hóa này, bạn sẽ viết một chương trình sắp xếp một mảng duy nhất bằng cách chỉ so sánh các phần tử thông qua việc yêu cầu người dùng trên thiết bị xuất chuẩn với kết quả so sánh đầu vào trên stdin.

Giao thức dưới đây dựa trên dòng, vì vậy mỗi khi bạn in ra thiết bị xuất chuẩn hoặc đọc từ stdin, nó được giả sử là một dòng mới theo sau. Trong suốt câu hỏi dưới đây, người dùng (đọc: chương trình chấm điểm) có một mảng mà nó muốn được sắp xếp trong một mảng được lập chỉ mục dựa trên 0 được gọi array. Vì lý do kỹ thuật, tôi khuyên bạn nên xả nước sau mỗi lần in.

  1. Bước đầu tiên, chương trình của bạn phải đọc kích thước mảng ntừ stdin.
  2. Sau đó, như bạn muốn, bạn có thể in a < bra thiết bị xuất chuẩn, với hai số nguyên 0 <= a, b < n. Sau đó, người dùng sẽ nhập 1vào stdin nếu array[a] < array[b], và 0nếu không.
  3. Cuối cùng, một khi chương trình của bạn bị thuyết phục, nó đã suy ra chính xác thứ tự của mảng, nó phải in a ...ra thiết bị xuất chuẩn, trong đó ...một danh sách các số nguyên được phân tách bằng dấu cách chỉ ra thứ tự. Vì vậy, nếu chương trình của bạn xuất ra, a 3 0 1 4 2điều đó có nghĩa là chương trình của bạn đã suy ra

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

    Lưu ý rằng chương trình của bạn không bao giờ biết nội dung arrayvà sẽ không bao giờ.

Bạn chỉ có thể yêu cầu <trên stdin để sắp xếp mảng. Bạn có thể có được các hoạt động so sánh khác bằng các tương đương sau:

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

Cuối cùng, vì chương trình của bạn tương tác với chương trình chấm điểm trên thiết bị xuất chuẩn, hãy in thông tin gỡ lỗi sang thiết bị lỗi chuẩn.


Chương trình của bạn sẽ được ghi bằng chương trình Python sau:

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)

Bạn ghi điểm chương trình của bạn bằng cách gõ python score.py yourprogram. Việc chấm điểm được thực hiện bằng cách yêu cầu chương trình của bạn sắp xếp một mảng ngẫu nhiên có kích thước từ 0 đến 100 và tính số lượng so sánh mà chương trình của bạn yêu cầu. Các mảng ngẫu nhiên này có thể có các bản sao , thuật toán của bạn phải có khả năng xử lý các phần tử bằng nhau. Trong trường hợp có các bản sao, không có yêu cầu về thứ tự của các phần tử bằng nhau. Vì vậy, nếu mảng là [0, 0]không quan trọng nếu bạn xuất a 0 1hoặc a 1 0.

Bạn không thể tối ưu hóa cụ thể cho các mảng cụ thể mà chương trình tính điểm tạo ra. Tôi có thể thay đổi hạt giống RNG bất cứ lúc nào. Câu trả lời sử dụng thuật toán sắp xếp tích hợp được phép đăng lên vì lợi ích, nhưng không cạnh tranh.

Chương trình có số điểm thấp nhất sẽ thắng.


1
Bạn đang sử dụng phiên bản Python nào?
Nữ tu bị rò rỉ

Mất bao lâu để chạy thuật toán chấm điểm của bạn?
Nữ tu bị rò rỉ

Chúng ta có thể đưa ra giả định nào về kích thước tối đa của mảng đầu vào?
hellowworld922

@ helloworld922 Về mặt lý thuyết, không - câu trả lời của bạn nên hoạt động với mọi kích cỡ. Nhưng nếu nó tiết kiệm nỗ lực trong một ngôn ngữ như C hỗ trợ mọi thứ lên đến và bao gồm 100 yếu tố là bắt buộc.
orlp

Điều quan trọng là làm rõ phiên bản Python được sử dụng bởi chương trình tính điểm, bởi vì Python 2 và 3 tạo ra các chuỗi ngẫu nhiên khác nhau. Hoặc có lẽ sẽ tốt hơn nếu tính ngẫu nhiên đến từ một nguồn xác định được chỉ định rõ như hashlib.
Anders Kaseorg

Câu trả lời:


3

Con trăn, điểm 23069

Điều này sử dụng thuật toán sắp xếp chèn hợp nhất Ford mật 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 điểm

Sắp xếp nhanh chóng. Pivot là mục ngoài cùng bên trái.

Điểm số dự kiến, bởi vì:

\ 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()

Điểm cho từng kích thước được kiểm tra:

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 ở đây , dòng cuối cùng dịch thành "WindowsError: [Error 193]% 1 không phải là ứng dụng Win32 chính xác."
Nữ tu bị rò rỉ

1

Python 2 (không cạnh tranh), điểm 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()

Điểm cho từng kích thước được kiểm tra:

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

Tôi nghĩ Python đã thực hiện một chức năng sắp xếp rất tốt, xem xét số lượng so sánh tối ưu ở đây: en.wikipedia.org/wiki/iêu Có vẻ như đây sẽ là một tài liệu tham khảo cho một đường cơ sở rất tốt.
cần

1

Python, điểm số 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()

Đây là một chương trình ví dụ, thực hiện dạng bong bóng đơn giản nhất, luôn luôn thực hiện n*(n-1)so sánh trên mỗi mảng.

Tôi đã ghi điểm chương trình này bằng cách lưu nó sort.pyvà gõ python score.py python sort.py.


Nếu chính xác, đó là Python 3. Tôi thấy bằng cách printtrông giống như một hàm.
dùng48538

1
@ zyabin101 Bây giờ là cả hai :)
orlp 20/07/2016
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.