Tối đa hóa tour Sudoku King


16

Lý lịch

Sudoku là một câu đố số nơi, do một n×n lưới chia thành hộp kích thước n , mỗi số 1 đến n sẽ xuất hiện đúng một lần trong mỗi hàng, cột và hộp.

Trong trò chơi Cờ vua, Nhà vua có thể di chuyển đến bất kỳ (nhiều nhất) 8 ô liền kề trong một lượt. "Liền kề" ở đây có nghĩa là liền kề theo chiều ngang, chiều dọc hoặc đường chéo.

Các tour du lịch của nhà vua là một tương tự của tour của Hiệp sĩ; đó là một con đường (có thể mở) truy cập vào mọi ô chính xác một lần trên bảng đã cho bằng các chuyển động của Vua cờ.

Bài tập

Hãy xem xét lưới Sudoku 6 x 6:

654 | 321
123 | 654
----+----
462 | 135
315 | 246
----+----
536 | 412
241 | 563

và một tour du lịch của nhà vua (từ 01đến 36):

01 02 03 | 34 35 36
31 32 33 | 04 05 06
---------+---------
30 23 28 | 27 26 07
22 29 24 | 25 09 08
---------+---------
21 19 16 | 10 14 13
20 17 18 | 15 11 12

Các tour du lịch tạo thành số 36 chữ số 654654564463215641325365231214123321.

Tham gia một tour du lịch khác nhau của King cho số lượng lớn hơn; ví dụ, tôi có thể tìm thấy một con đường bắt đầu bằng con đường 65<6>56446556...chắc chắn lớn hơn con đường trên. Bạn có thể thay đổi bảng Sudoku để nhận số cao hơn:

... | ...
.6. | ...
----+----
..6 | ...
.5. | 6..
----+----
.45 | .6.
6.. | 5..

Bảng không đầy đủ này đưa ra chuỗi bắt đầu trong 666655546...đó là chuỗi tối ưu gồm 9 chữ số bắt đầu.

Nhiệm vụ của bạn là tìm số lượng lớn nhất như vậy cho Sudoku 9 x 9 tiêu chuẩn với các hộp 3 nhân 3 , tức là

... | ... | ...
... | ... | ...
... | ... | ...
----+-----+----
... | ... | ...
... | ... | ...
... | ... | ...
----+-----+----
... | ... | ...
... | ... | ...
... | ... | ...

Lưu ý rằng thách thức này không phải là ; trọng tâm là thực sự tìm ra các giải pháp hơn là viết một chương trình nhỏ hoạt động trên lý thuyết.

Ghi điểm & tiêu chí chiến thắng

Điểm của bài nộp là số 81 chữ số được tìm thấy bởi chương trình của bạn. Bài nộp với số điểm cao nhất sẽ thắng. Chương trình của bạn cũng nên xuất lưới Sudoku và chuyến tham quan của King ở dạng có thể đọc được; vui lòng bao gồm chúng trong trình của bạn.

Chương trình của bạn có thể xuất nhiều kết quả; điểm số của bạn là tối đa của họ.

Không có giới hạn thời gian cho chương trình của bạn. Nếu chương trình của bạn tiếp tục chạy và tìm thấy số cao hơn sau đó, bạn có thể cập nhật điểm của bài nộp bằng cách chỉnh sửa bài. Tiebreaker là thời gian sớm nhất để đạt được điểm số, tức là thời gian đăng bài (nếu nó chưa được chỉnh sửa) hoặc thời gian chỉnh sửa khi điểm số được cập nhật (nếu không).


2
Về việc bạn tự đề cử thử thách này cho Best of PPCG, bạn đề cập rằng "Đây có lẽ là [thử thách mã] đầu tiên để hỏi trực tiếp giải pháp tối ưu hóa, thay vì một số điểm kết hợp với độ dài mã hoặc như vậy." Tôi chỉ muốn cho bạn biết rằng điều đó không đúng - có Chuỗi thoát mê cung phổ quát ngắn nhất được đăng vào năm 2015.
Trái cây Esolanging

Câu trả lời:


19

Python + Z3 , 999899898789789787876789658767666545355432471632124566352413452143214125313214321, tối ưu

Chạy trong khoảng nửa giờ, sản xuất

1 3 4 8 9 7 6 2 5
2 9 7 1 5 6 8 3 4
5 6 8 4 2 3 7 9 1
4 7 6 2 1 5 9 8 3
8 5 1 6 3 9 2 4 7
9 2 3 7 8 4 1 5 6
3 8 5 9 6 1 4 7 2
6 4 9 5 7 2 3 1 8
7 1 2 3 4 8 5 6 9
81 79 78 14 15 16 54 57 56
80 12 13 77 52 53 17 55 58
34 33 11 51 76 75 18  1 59
35 10 32 50 74 72  2 19 60
 9 36 49 31 73  3 71 61 20
 8 48 37 30  4 69 70 62 21
47  7 38  5 29 68 65 22 63
46 43  6 39 28 67 66 64 23
44 45 42 41 40 27 26 25 24
999899898789789787876789658767666545355432471632124566352413452143214125313214321

import z3


def adj(a):
    x, y = a
    for x1 in range(max(0, x - 1), min(9, x + 2)):
        for y1 in range(max(0, y - 1), min(9, y + 2)):
            if (x1, y1) != a:
                yield x1, y1


solver = z3.SolverFor("QF_FD")

squares = list((x, y) for x in range(9) for y in range(9))
num = {(x, y): z3.Int(f"num{x}_{y}") for x, y in squares}
for a in squares:
    solver += 1 <= num[a], num[a] <= 9
for cells in (
    [[(x, y) for y in range(9)] for x in range(9)]
    + [[(x, y) for x in range(9)] for y in range(9)]
    + [
        [(x, y) for x in range(i, i + 3) for y in range(j, j + 3)]
        for i in range(0, 9, 3)
        for j in range(0, 9, 3)
    ]
):
    solver += z3.Distinct([num[x, y] for x, y in cells])
    for k in range(1, 10):
        solver += z3.Or([num[x, y] == k for x, y in cells])

move = {
    ((x0, y0), (x1, y1)): z3.Bool(f"move{x0}_{y0}_{x1}_{y1}")
    for x0, y0 in squares
    for x1, y1 in adj((x0, y0))
}
tour = {(x, y): z3.Int(f"tour{x}_{y}") for x, y in squares}
for a in squares:
    solver += 0 <= tour[a], tour[a] < 81
for a in squares:
    solver += z3.PbEq([(move[a, b], 1) for b in adj(a)] + [(tour[a] == 80, 1)], 1)
for b in squares:
    solver += z3.PbEq([(move[a, b], 1) for a in adj(b)] + [(tour[b] == 0, 1)], 1)
solver += z3.Distinct([tour[a] for a in squares])
for t in range(81):
    solver += z3.Or([tour[a] == t for a in squares])
for a in squares:
    for b in adj(a):
        solver += move[a, b] == (tour[a] + 1 == tour[b])

value = [z3.Int(f"value{t}") for t in range(81)]
for t in range(81):
    solver += 1 <= value[t], value[t] <= 9
for a in squares:
    for t in range(81):
        solver += z3.Implies(tour[a] == t, num[a] == value[t])

assert solver.check() != z3.unsat
opt = 0
while opt < 81:
    model = solver.model()
    for y in range(9):
        print(*(model[num[x, y]] for x in range(9)))
    for y in range(9):
        print(*(f"{model[tour[x, y]].as_long() + 1:2}" for x in range(9)))
    best = [model[value[t]].as_long() for t in range(81)]
    print(*best, sep="")
    print()
    while opt < 81:
        improve = z3.Bool(f"improve{opt}_{best[opt]}")
        solver += improve == (value[opt] > best[opt])
        if solver.check(improve) != z3.unsat:
            break
        solver += value[opt] == best[opt]
        opt += 1

Chắc chắn tôi đã đánh giá quá cao vấn đề quá nhiều. Và tôi hoàn toàn quên mất ma thuật đen tối của Z3 ...
Bubbler

@Bubbler chắc chắn là một giải pháp tối ưu nằm ngoài tầm tay là điều khó khăn. Bản thân tôi cũng mắc lỗi tương tự - và tôi đã tồn tại ít thời gian hơn trước khi ai đó đăng một giải pháp tối ưu ... codegolf.stackexchange.com/a/51974/20283
trichoplax

Của tôi không thể cứu vãn được, nhưng tôi tự hỏi liệu thử thách này có thể hoạt động như một biến thể với một bàn cờ lớn hơn và một quân cờ khác không (có lẽ là một thử thách tiếp theo liên kết với cái này)
trichoplax
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.