"КНОТ" чи "НЕ"?


144

Напишіть програму, яка обробляє зображення зображень ASCII заплутаного рядка і вирішує, чи можна його переплутати в просту петлю. Клубок представлений за допомогою символів -і |для зображення горизонтальних і вертикальних сегментів, а також +для подання кутів. Місця, де рядок переходить над собою, представлені так:

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

Кінці струни з'єднані між собою; немає вільних кінців.

Якщо ваша програма вирішить, що рядок не можна розплутати в простий цикл, вона повинна вивести слово KNOT. В іншому випадку воно повинно вивести слово NOT.

Це виклик з , тому найкоротший вірний відповідь (вимірюється в байтах вихідного коду) виграє.

Обмеження

Вхід ASCII буде містити до 25 рядків з 80 символів. Ви можете припустити, що всі рядки прокладені пробілами однакової довжини.

Приклади

Вхід:

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

Вихід:

KNOT

Вхід:

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

Вихід:

NOT

Список літератури


36
+1 Відмінне запитання. Спокусився наділити це щедротою, щоб заохотити людей стрибнути в цю теорію вузлів.
Цифрова травма

2
Чи можемо ми припустити, що це вузол (можливо, unknot) або це може бути посиланням> 1 підключених компонентів?
msh210

@ Msh210 Так, ви можете припустити , що це єдиний вузол :-)
гидливо грифа

Відповіді:


94

Python 3, 457 316 306 байт

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')

Так?

Програма спочатку перетворює вузол у прямокутну діаграму, яка має такі обмеження:

  1. На одній лінії не лежать два вертикальні чи горизонтальні відрізки.
  2. Жоден вертикальний відрізок не перетинає горизонтальний відрізок.

Наприклад, перший тестовий випадок перетворюється на таку прямокутну діаграму:

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

яку ми однозначно представляємо послідовністю y координат вертикальних відрізків справа наліво:

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

Потім він шукає спрощення прямокутної діаграми, як описано в Івані Диннікову, «Дугові презентації посилань. Монотонне спрощення », 2004 . Дінніков довів, що з будь-якої прямокутної діаграми розв'язки існує послідовність спрощення ходів, яка закінчується на тривіальній діаграмі. Якщо коротко, дозволені рухи включають:

  1. Циклічно переймаючи вертикальні (або горизонтальні) сегменти;
  2. Зміна послідовних вертикальних (або горизонтальних) сегментів за певних обмежень конфігурації.
  3. Заміна трьох суміжних вершин, які лежать в самому куті діаграми, однією вершиною.

Дивіться папір для малюнків. Це не очевидна теорема; це не дотримується, якщо, скажімо, використовуються рухи Reidemeister, які не збільшують кількість перетинів. Але для конкретних видів спрощень вище, це виявляється правдою.

(Ми спрощуємо реалізацію лише permuting вертикальними сегментами, але також дозволяємо транспонувати весь вузол для обміну горизонтальними з вертикальними.)

Демо

$ 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

Ого, це чудово.
писклива косточка

3
Чи можете ви опублікувати невмілену версію коду?
Дж. Антоніо Перес

Крім того, яка часова складність вашої програми?
Дж. Антоніо Перес

3
@JorgePerez У мене немає окремої версії, що не використовується для гольфу; найкращий спосіб зрозуміти програму - прочитати папір Діннікова, яку я пов’язав. Складність - це щось жахливо експоненціальне; наскільки я знаю, чи існує алгоритм поліноміального часу - це все ще відкрита проблема.
Андерс Касеорг
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.