"NÓ" ou "NÃO"?


144

Escreva um programa que processe uma representação artística ASCII de uma sequência emaranhada e decida se ela pode ou não ser emaranhada em um loop simples. O emaranhado é representado usando os caracteres -e |para representar segmentos horizontais e verticais e +para representar cantos. Os locais onde a sequência passa sobre si são representados da seguinte maneira:

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

As extremidades da cadeia são conectadas juntas; Não há pontas soltas.

Se o seu programa decidir que a sequência não pode ser desemaranhada em um loop simples, ela deve gerar a palavra KNOT. Caso contrário, ele deve gerar a palavra NOT.

Este é um desafio de , portanto a resposta mais curta e válida (medida em bytes do código-fonte) vencerá.

Limites

A entrada ASCII consistirá em até 25 linhas de 80 caracteres. Você pode assumir que todas as linhas são preenchidas com espaços do mesmo comprimento.

Exemplos

Entrada:

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

Resultado:

KNOT

Entrada:

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

Resultado:

NOT

Referências


36
+1 ótima pergunta. Tentou dar uma recompensa a essa para incentivar as pessoas a entrar nessa teoria dos nós.
Digital Trauma

2
Podemos assumir que é um nó (possivelmente o nó) ou pode ser um link de> 1 componentes conectados?
Msh210 03/03

@ msh210 Sim, você pode assumir que é um único nó :-)
ossifrage escrúpulos

Respostas:


94

Python 3, 457 316 306 bytes

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

Hã?

O programa primeiro converte o nó em um diagrama retangular, com as seguintes restrições:

  1. Não existem dois segmentos verticais ou horizontais na mesma linha.
  2. Nenhum segmento vertical cruza um segmento horizontal.

Por exemplo, o primeiro caso de teste é convertido no seguinte diagrama retangular:

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

que representamos exclusivamente pela sequência de coordenadas y dos segmentos verticais, da direita para a esquerda:

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

Em seguida, procura simplificações do diagrama retangular, como descrito em Ivan Dynnikov, “Apresentações em arco de links. Simplificação monotônica ”, 2004 . Dynnikov provou que, a partir de qualquer diagrama retangular do nó, existe uma sequência de movimentos simplificadores que termina no diagrama trivial. Resumidamente, os movimentos permitidos incluem:

  1. Permutando ciclicamente os segmentos verticais (ou horizontais);
  2. Trocar segmentos verticais (ou horizontais) consecutivos sob certas restrições de configuração.
  3. Substituindo três vértices adjacentes que ficam no canto do diagrama por um vértice.

Veja o jornal para fotos. Este não é um teorema óbvio; não é válido se, digamos, movimentos de Reidemeister que não aumentam o número de cruzamentos forem usados. Mas para os tipos específicos de simplificações acima, isso é verdade.

(Simplificamos a implementação permitindo apenas segmentos verticais, mas também permitindo que todo o nó seja transposto para trocar horizontal com vertical.)

Demo

$ 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

Uau, isso é excelente.
ossifrage melindroso

3
Você poderia postar uma versão não destruída do seu código?
J. Antonio Perez

Além disso, qual é a complexidade de tempo do seu programa?
J. Antonio Perez

3
@JorgePerez Eu não tenho uma versão ungolfed separada; a melhor maneira de entender o programa é ler o artigo de Dynnikov que eu vinculei. A complexidade é algo terrivelmente exponencial; até onde eu sei, se existe um algoritmo de tempo polinomial ainda é um problema em aberto.
Anders Kaseorg 07/12/16
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.