VỪA KNOT hay hay KHÔNG


144

Viết chương trình xử lý biểu diễn nghệ thuật ASCII của một chuỗi rối và quyết định xem nó có thể được gỡ rối thành một vòng lặp đơn giản hay không. Các rối được thể hiện bằng cách sử dụng các ký tự -|để thể hiện các phân đoạn ngang và dọc, và +để đại diện cho các góc. Các vị trí mà chuỗi đi qua chính nó được biểu diễn như sau:

            |                           |   
         -------                     ---|---
            |                           |   
(Horizontal segment on top)   (Vertical segment on top)

Các đầu của chuỗi được kết nối với nhau; không có kết thúc lỏng lẻo.

Nếu chương trình của bạn quyết định rằng chuỗi không thể được gỡ rối thành một vòng lặp đơn giản, thì nó sẽ xuất ra từ KNOT. Nếu không, nó sẽ xuất ra từ NOT.

Đây là một thử thách , vì vậy câu trả lời hợp lệ ngắn nhất (tính bằng byte của mã nguồn) sẽ giành chiến thắng.

Hạn mức

Đầu vào ASCII sẽ bao gồm tối đa 25 dòng gồm 80 ký tự. Bạn có thể giả định rằng tất cả các dòng được đệm với khoảng trắng có cùng độ dài.

Ví dụ

Đầu vào:

+-------+    +-------+    
|       |    |       |    
|   +---|----+   +-------+
|   |   |        |   |   |
+-------|------------|---+
    |   |        |   |    
    +---+        +---+    

Đầu ra:

KNOT

Đầu vào:

+----------+         
|          |         
|    +--------------+
|    |     |        |
|    |   +-|----+   |
|    |   | |    |   |
|    +-----+    |   |
|        |      |   |
|        +------|---+
|               |    
+---------------+    

Đầu ra:

NOT

Người giới thiệu


36
+1 Câu hỏi tuyệt vời. Cố gắng đặt một tiền thưởng cho cái này để khuyến khích mọi người nhảy vào lý thuyết nút thắt đó.
Chấn thương kỹ thuật số

2
Chúng ta có thể giả sử đó là một nút thắt (có thể là nút thắt) hoặc nó có thể là một liên kết của> 1 thành phần được kết nối không?
msh210

@ msh210 Có, bạn có thể giả sử đó là một nút thắt duy nhất :-)
squossish ossifrage

Câu trả lời:


94

Python 3, 457 316 306 byte

E=enumerate
V={'+'}
Q=[[(-j,i,k)for i,u in E(open(0))for j,v in E(u)for k in[{v}&V,'join'][u[j:j+2]=='|-']]]
while Q:
 a,b,c,d,*e=A=tuple(x//2for y,x in sorted((y,x)for x,y in E(Q.pop())));e or exit('NOT')
 if{A}-V:V|={A};Q+=[[c,d,a,b]+e,A,A[2:]+A[:2]][a<c<b<d:][c<a<d<b:]
 if b==d:Q=[[a,c]+e]
exit('KNOT')

Huh?

Chương trình trước tiên chuyển đổi nút thành sơ đồ hình chữ nhật, có các hạn chế sau:

  1. Không có hai đoạn dọc hoặc ngang nằm trên cùng một dòng.
  2. Không có phân khúc dọc vượt qua một phân khúc ngang.

Ví dụ, trường hợp thử nghiệm đầu tiên được chuyển đổi sang sơ đồ hình chữ nhật sau:

+-----------+            
|           |            
|           | +-------+  
|           | |       |  
| +-------+ | |       |  
| |       | | |       |  
| |     +---+ |       |  
| |     | |   |       |  
| |     | +---+       |  
| |     |             |  
| |     |       +-------+
| |     |       |     | |
+-----+ |       |     | |
  |   | |       |     | |
  | +---+       |     | |
  | | |         |     | |
  | | +-------------+ | |
  | |           |   | | |
  | |           | +---+ |
  | |           | | |   |
  | |           | | +---+
  | |           | |      
  +-+           | |      
                | |      
                +-+      

mà chúng tôi đại diện duy nhất bằng chuỗi tọa độ y của các phân đoạn dọc, từ phải sang trái:

(5,10, 1,9, 8,10, 9,12, 5,12, 1,4, 0,3, 2,4, 3,7, 6,8, 7,11, 2,11, 0,6)

Sau đó, nó tìm kiếm sự đơn giản hóa của sơ đồ hình chữ nhật như được mô tả trong Ivan Dynnikov, Bài thuyết trình về các liên kết. Đơn giản hóa đơn điệu, 2004 . Dynnikov đã chứng minh rằng từ bất kỳ sơ đồ hình chữ nhật nào của unjack, có một chuỗi các động tác đơn giản hóa kết thúc ở sơ đồ tầm thường. Tóm lại, các động thái được phép bao gồm:

  1. Chu kỳ hoán vị các đoạn dọc (hoặc ngang);
  2. Hoán đổi các phân đoạn dọc (hoặc ngang) liên tiếp trong các ràng buộc cấu hình nhất định.
  3. Thay thế ba đỉnh liền kề nằm ở góc của sơ đồ bằng một đỉnh.

Xem giấy cho hình ảnh. Đây không phải là một định lý rõ ràng; nó không giữ nếu, giả sử, các động tác Reidemeister không làm tăng số lượng giao cắt được sử dụng thay thế. Nhưng đối với các loại đơn giản hóa cụ thể ở trên, hóa ra là đúng.

(Chúng tôi đơn giản hóa việc thực hiện bằng cách chỉ cho phép các phân đoạn dọc, nhưng cũng cho phép toàn bộ nút được chuyển sang ngang thay đổi theo chiều dọc.)

Bản giới thiệu

$ python3 knot.py <<EOF
+-------+    +-------+    
|       |    |       |    
|   +---|----+   +-------+
|   |   |        |   |   |
+-------|------------|---+
    |   |        |   |    
    +---+        +---+    
EOF
KNOT
$ python3 knot.py <<EOF
+----------+         
|          |         
|    +--------------+
|    |     |        |
|    |   +-|----+   |
|    |   | |    |   |
|    +-----+    |   |
|        |      |   |
|        +------|---+
|               |    
+---------------+    
EOF
NOT
$ python3 knot.py <<EOF  # the Culprit
        +-----+  
        |     |  
+-----------+ |  
|       |   | |  
|   +-+ | +---|-+
|   | | | | | | |
| +-|-------+ | |
| | | | | |   | |
+-|-+ | | +---+ |
  |   | |       |
  +---|---------+
      | |        
      +-+        
EOF
NOT
$ python3 knot.py <<EOF  # Ochiai unknot
    +-----+    
    |     |    
  +-|---------+
  | |     |   |
  | | +-+ |   |
  | | | | |   |
+-|-|---|-|-+ |
| | | | | | | |
| | | +---|---+
| | |   | | |  
+-------+ | |  
  | |     | |  
  | +-------+  
  |       |    
  +-------+    
EOF
NOT
$ python3 knot.py <<EOF  # Ochiai unknot plus trefoil
    +-----+ +-----+
    |     | |     |
  +-|---------+   |
  | |     | | |   |
  | | +-+ | +---+ |
  | | | | |   | | |
+-|-|---|-|-+ +---+
| | | | | | |   |  
| | | +---|-----+  
| | |   | | |      
+-------+ | |      
  | |     | |      
  | +-------+      
  |       |        
  +-------+        
EOF
KNOT
$ python3 knot.py <<EOF  # Thistlethwaite unknot
      +---------+        
      |         |        
    +---+ +---------+    
    | | | |     |   |    
    | +-------+ |   |    
    |   | |   | |   |    
    |   | | +---+   |    
    |   | | | |     |    
    |   | +-------+ |    
    |   |   | |   | |    
    |   +-------+ | |    
    |       | | | | |    
+-----------+ | | | |    
|   |         | | | |    
| +-----------+ | | |    
| | |           | | |    
| | +-------------+ |    
| |             |   |    
| |             +-----+  
| |                 | |  
| |                 +---+
| |                   | |
+---------------------+ |
  |                     |
  +---------------------+
EOF
NOT
$ python3 knot.py <<EOF  # (−3,5,7)-pretzel knot
      +-------------+
      |             |
    +-|-----+       |
    | |     |       |
  +-|-+   +-------+ |
  | |     | |     | |
+-|-+   +---+   +---+
| |     | |     | |  
| |   +---+   +---+  
| |   | |     | |    
| | +---+   +---+    
| | | |     | |      
| +---+   +---+      
|   |     | |        
|   |   +---+        
|   |   | |          
|   | +---+          
|   | | |            
|   +---+            
|     |              
+-----+              
EOF
KNOT
$ python3 knot.py <<EOF  # Gordian unknot
+-------------+                 +-------------+
|             |                 |             |
| +---------+ |                 | +---------+ |
| |         | |                 | |         | |
| | +-------------+         +-------------+ | |
| | |       | |   |         |   | |       | | |
| | | +---------+ |         | +---------+ | | |
| | | |     | | | |         | | | |     | | | |
| +-------+ | +-------+ +-------+ | +-------+ |
|   | |   | |   | |   | |   | |   | |   | |   |
+-------+ | +-------+ | | +-------+ | +-------+
    | | | |     | | | | | | | |     | | | |    
    | +-------+ | | | | | | | | +-------+ |    
    |   | |   | | | | | | | | | |   | |   |    
    +-------+ | | | | | | | | | | +-------+    
        | | | | | | | | | | | | | | | |        
        | +-----+ | | | | | | +-----+ |        
        |   | |   | | | | | |   | |   |        
        +---------+ | | | | +---------+        
            | |     | | | |     | |            
          +---------+ | | +---------+          
          | | |       | |       | | |          
          | | +-----------------+ | |          
          | |         | |         | |          
          | +---------------------+ |          
          |           | |           |          
          +-----------+ +-----------+          
EOF
NOT

Wow, điều này là tuyệt vời.
squossish ossifrage

3
Bạn có thể đăng một phiên bản không mã hóa của mã của bạn?
J. Antonio Perez

Ngoài ra, độ phức tạp thời gian của chương trình của bạn là gì?
J. Antonio Perez

3
@JorgePerez Tôi không có phiên bản không được phân tách riêng; cách tốt nhất để hiểu chương trình là đọc bài viết của Dynnikov mà tôi đã liên kết. Sự phức tạp là một cái gì đó theo cấp số nhân khủng khiếp; theo như tôi biết, liệu thuật toán thời gian đa thức có tồn tại hay không vẫn là một vấn đề mở.
Anders Kaseorg 7/12/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.