"Nodo" o "NON"?


144

Scrivi un programma che elabora una rappresentazione di arte ASCII di una stringa aggrovigliata e decide se può essere districato in un semplice ciclo. Il groviglio viene rappresentato usando i caratteri -e |per rappresentare segmenti orizzontali e verticali e +per rappresentare gli angoli. I luoghi in cui la stringa passa su se stessa sono rappresentati come segue:

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

Le estremità della stringa sono collegate insieme; non ci sono estremità libere.

Se il tuo programma decide che la stringa non può essere districata in un semplice ciclo, dovrebbe generare la parola KNOT. Altrimenti, dovrebbe generare la parola NOT.

Questa è una sfida di , quindi vincerà la risposta valida più breve (misurata in byte del codice sorgente).

limiti

L'ingresso ASCII sarà composto da un massimo di 25 righe di 80 caratteri. Si può presumere che tutte le linee siano riempite con spazi della stessa lunghezza.

Esempi

Ingresso:

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

Produzione:

KNOT

Ingresso:

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

Produzione:

NOT

Riferimenti


36
+1 Ottima domanda. Sono tentato di mettere una taglia su questo per incoraggiare la gente a saltare in quella teoria del nodo.
Digital Trauma,

2
Possiamo supporre che sia un nodo (possibilmente il non-nodo) o può essere un collegamento di> 1 componenti collegati?
msh210,

@ msh210 Sì, puoi presumere che sia un singolo nodo :-)
ossifrage schizzinoso

Risposte:


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

Eh?

Il programma prima converte il nodo in uno schema rettangolare, che presenta le seguenti restrizioni:

  1. Non ci sono due segmenti verticali o orizzontali sulla stessa linea.
  2. Nessun segmento verticale attraversa un segmento orizzontale.

Ad esempio, il primo caso di test viene convertito nel seguente diagramma rettangolare:

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

che rappresentiamo in modo univoco dalla sequenza di coordinate y dei segmenti verticali, da destra a sinistra:

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

Quindi cerca le semplificazioni del diagramma rettangolare come descritto in Ivan Dynnikov, “Presentazioni di archi di collegamenti. Semplificazione monotonica ”, 2004 . Dynnikov ha dimostrato che da qualsiasi diagramma rettangolare del non-nodo, c'è una sequenza di mosse semplificanti che termina nel diagramma banale. In breve, le mosse consentite includono:

  1. Permutazione ciclica dei segmenti verticali (o orizzontali);
  2. Scambio di segmenti verticali (o orizzontali) consecutivi con determinati vincoli di configurazione.
  3. Sostituendo tre vertici adiacenti che giacciono nell'angolo stesso del diagramma con un vertice.

Vedi la carta per le immagini. Questo non è un teorema evidente; non vale se, per esempio, vengono usate mosse di Reidemeister che non aumentano il numero di incroci. Ma per i particolari tipi di semplificazioni di cui sopra, risulta essere vero.

(Semplifichiamo l'implementazione consentendo solo segmenti verticali, ma consentendo anche di trasporre l'intero nodo per scambiare orizzontale e verticale.)

dimostrazione

$ 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

Caspita, è eccellente.
ossifrage squeamish

3
Potresti pubblicare una versione non modificata del tuo codice?
J. Antonio Perez,

Inoltre, qual è la complessità temporale del tuo programma?
J. Antonio Perez,

3
@JorgePerez Non ho una versione ungolf separata; il modo migliore per capire il programma è leggere l'articolo di Dynnikov che ho collegato. La complessità è qualcosa di orribilmente esponenziale; per quanto ne so, l'esistenza di un algoritmo temporale polinomiale è ancora un problema aperto.
Anders Kaseorg,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.