「ノット」または「ノット」?


144

もつれた文字列のASCIIアート表現を処理し、それを単純なループに解くことができるかどうかを決定するプログラムを作成します。もつれは、文字-を使用し|て表され、水平および垂直セグメント+を表し、角を表します。文字列がそれ自体を通過する場所は、次のように表されます。

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

ストリングの両端は互いに接続されています。ゆるい終わりはありません。

プログラムが文字列を単純なループに解くことができないと判断した場合、wordを出力する必要がありますKNOT。それ以外の場合は、wordを出力する必要がありますNOT

これは挑戦なので、最短の有効な回答(ソースコードのバイト数で測定)が勝ちます。

制限

ASCII入力は、最大25行の80文字で構成されます。すべての行に同じ長さのスペースが埋め込まれていると想定できます。

入力:

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

出力:

KNOT

入力:

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

出力:

NOT

参照資料


36
+1すばらしい質問。この結び目理論に飛び込むように人々を奨励するために、これに賞金をかけようとしました。
デジタル外傷14

2
結び目(おそらく結び目ではない)であると仮定できますか、それとも1つ以上の接続されたコンポーネントのリンクであると仮定できますか?
msh210

@ msh210はい、あなたはそれが単一の結び目であると仮定することができます:
squeamish ossifrage

回答:


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つの垂直または水平セグメントはありません。
  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)

次に、Ivan Dynnikovの「リンクのアーク表現」で説明されているように、長方形図の簡略化を検索します。単調単純化」、2004年。Dynnikovは、結び目のない長方形の図から、単純な図で終わる一連の単純化された動きがあることを証明しました。簡単に言えば、許可される移動には次のものが含まれます。

  1. 垂直(または水平)セグメントを周期的に並べ替えます。
  2. 特定の構成の制約の下で、連続する垂直(または水平)セグメントを交換します。
  3. ダイアグラムの隅にある3つの隣接する頂点を1つの頂点に置き換えます。

写真については論文をご覧ください。これは明らかな定理ではありません。例えば、交差の数を増加させないReidemeisterの動きが代わりに使用される場合、それは保持されません。しかし、上記の特定の種類の単純化については、真実であることがわかりました。

(垂直セグメントのみを並べ替えることで実装を簡素化しますが、ノット全体を転置して水平と垂直を入れ替えることもできます。)

デモ

$ 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

うわー、これは素晴らしいです。
squeamish ossifrage

3
コードの未使用バージョンを投稿できますか?
J.アントニオペレス

また、プログラムの時間の複雑さは何ですか?
J.アントニオペレス

3
@JorgePerez個別のバージョンはありません。プログラムを理解する最良の方法は、リンクしたDynnikovの論文を読むことです。複雑さは恐ろしく指数関数的なものです。私の知る限り、多項式時間アルゴリズムが存在するかどうかは未解決の問題です。
アンデルスカセオルグ16
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.