Una situación nudosa

34

Dada la notación Dowker de un nudo y sus signos de cruce, calcule su polinomio de paréntesis.

Aunque hay más definiciones técnicas, para este desafío es suficiente pensar en un nudo como algo hecho físicamente al unir los dos extremos de una cuerda. Como los nudos existen en tres dimensiones, cuando los dibujamos en papel, usamos diagramas de nudos , proyecciones bidimensionales en las que los cruces son exactamente de dos líneas, una encima y otra debajo.

ingrese la descripción de la imagen aquí

Aquí (b) y (c) hay diagramas diferentes del mismo nudo.

¿Cómo representamos un diagrama de nudos en papel? La mayoría de nosotros no somos Rembrandt, por lo que confiamos en la notación Dowker , que funciona de la siguiente manera:

Elija un punto de partida arbitrario en el nudo. Se mueven en una dirección arbitraria a lo largo del nudo y el número de los cruces que encuentre, a partir de 1, con la siguiente modificación: si se trata de un número par y actualmente vas más el cruce, niega que el número par. Finalmente, elija los números pares correspondientes a 1, 3, 5, etc.

Probemos un ejemplo:

ingrese la descripción de la imagen aquí

En este nudo, elegimos "1" como nuestro punto de partida y procedimos a movernos hacia arriba y hacia la derecha. Cada vez que pasamos sobre o debajo de otra pieza de la cuerda, asignamos el punto de cruce al siguiente número natural. Negamos los números pares correspondientes a los filamentos que cruzan un cruce, por ejemplo [3,-12]en el diagrama. Entonces, este diagrama estaría representado por [[1,6],[2,5],[3,-12],[-4,9],[7,8],[-10,11]]. Listado de los amigos de 1, 3, 5, 7, etc. nos da[6,-12,2,8,-4,-10] .

Hay algunas cosas a tener en cuenta aquí. Primero, la notación Dowker no es única para un nudo dado, ya que podemos elegir un punto de partida y dirección arbitrarios. Pero, dada la notación, uno puede determinar completamente la estructura del nudo (técnicamente, hasta el reflejo de sus componentes principales del nudo). Si bien no todas las anotaciones de Dowker pueden formar posibles nudos, en este problema puede suponer que la entrada representa un nudo real.

Para evitar la ambigüedad entre los reflejos de un nudo y hacer que el desafío sea más fácil de resolver, también se le dará una lista de signos de cruce como entrada.

ingrese la descripción de la imagen aquí

En un cruce positivo, la línea inferior va a la izquierda desde el punto de vista de la línea superior. En un cruce negativo va a la derecha. Tenga en cuenta que invertir la dirección de ir alrededor del nudo (es decir, invertir tanto la línea superior como la inferior ) no cambia los signos de cruce. En nuestro ejemplo, las señales de cruce son [-1,-1,-1,1,-1,1]. Se dan en el mismo orden que la notación Dowker, es decir, para cruces numerados 1, 3, 5, 7, etc.

En este desafío calcularemos el polinomio de corchete de un nudo. Es un objeto que es invariable en la mayoría de las transformaciones del diagrama de nudos, un concepto que lo hace sumamente útil en el análisis de la teoría de nudos. (Nuevamente, la mayoría de los teóricos de los nudos calculan el polinomio de soporte como un producto intermedio en su camino para calcular el polinomio de Jones, que es invariable en todas las transformaciones, pero no lo haremos). Entonces, ¿cómo funciona? El polinomio de soporte es un polinomio de Laurent, uno en el que la variable (tradicionalmente llamada ) puede elevarse a potencias negativas, así como positivas.UNA

Para un diagrama de nudos dado , las tres reglas para el polinomio, representadas como , son:rere

ingrese la descripción de la imagen aquí

  1. Un único lazo sin cruces tiene polinomio 1.

  2. rerere(-UNA2-UNA-2)

  3. reingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

En la imagen de arriba, el cruce delineado en el primer diagrama, que es de la forma ingrese la descripción de la imagen aquí, se puede transformar ingrese la descripción de la imagen aquícomo en la segunda figura (también conocido como suavizado positivo ), o ingrese la descripción de la imagen aquícomo en la tercera figura ( suavizado negativo ).

UNAUNA-1

ingrese la descripción de la imagen aquí

Confundido todavía? Hagamos un ejemplo, tratando de encontrar el polinomio de paréntesis de ingrese la descripción de la imagen aquí(Nota: se trata de dos nudos unidos entre sí. Este tipo de diagrama no será una entrada potencial en este desafío ya que las entradas solo serán nudos simples, pero puede aparecer como un resultado intermedio en el algoritmo).

Primero usamos la regla 3

ingrese la descripción de la imagen aquí

Usamos la regla 3 nuevamente en los dos nuevos nudos

ingrese la descripción de la imagen aquí

Sustituimos estos 4 nuevos nudos en la primera ecuación.

ingrese la descripción de la imagen aquí

Aplicando las reglas 1 y 2 a estos 4 díganos

ingrese la descripción de la imagen aquí

Entonces, esto nos dice

ingrese la descripción de la imagen aquí

¡Felicidades por completar tu breve introducción a la teoría de los nudos!

Entrada

Dos listas:

  • Notación Dowker, por ej [6,-12,2,8,-4,-10]. La numeración de los cruces debe comenzar desde 1. Los números impares correspondientes [1,3,5,7,...]están implícitos y no se deben proporcionar como entrada.

  • Señales ( 1/ -1o si prefiere 0/ 1o false/ trueo '+'/ '-') para los cruces correspondientes a la notación de Dowker, por ejemplo [-1,-1,-1,1,-1,1].

En lugar de un par de listas, podría tener una lista de pares, p. Ej. [[6,-1],[-12,-1],...

Salida

UNA-2+5 5+UNA-UNA3[[1,-2],[5,0],[1,1],[-1,3]]

-k...kknorte[0,1,0,5,1,0,-1]UNA0 0

Reglas

Este es un desafío de . No se puede usar ninguna de las lagunas estándar, y no se pueden usar las bibliotecas que tienen herramientas para calcular las anotaciones de Dowker o los polinomios de soporte. (Todavía se puede usar un lenguaje que contenga estas bibliotecas, pero no las bibliotecas / paquetes).

Pruebas

// 4-tuples of [dowker_notation, crossing_signs, expected_result, description]
[
 [[],[],[[1,0]],"unknot"],
 [[2],[1],[[-1,3]],"unknot with a half-twist (positive crossing)"],
 [[2],[-1],[[-1,-3]],"unknot with a half-twist (negative crossing)"],
 [[2,4],[1,1],[[1,6]],"unknot with two half-twists (positive crossings)"],
 [[4,6,2],[1,1,1],[[1,-7],[-1,-3],[-1,5]],"right-handed trefoil knot, 3_1"],
 [[4,6,2,8],[-1,1,-1,1],[[1,-8],[-1,-4],[1,0],[-1,4],[1,8]],"figure-eight knot, 4_1"],
 [[6,8,10,2,4],[-1,-1,-1,-1,-1],[[-1,-7],[-1,1],[1,5],[-1,9],[1,13]],"pentafoil knot, 5_1"],
 [[6,8,10,4,2],[-1,-1,-1,-1,-1],[[-1,-11],[1,-7],[-2,-3],[1,1],[-1,5],[1,9]],"three-twist knot, 5_2"],
 [[4,8,10,2,12,6],[1,1,-1,1,-1,-1],[[-1,-12],[2,-8],[-2,-4],[3,0],[-2,4],[2,8],[-1,12]],"6_3"],
 [[4,6,2,10,12,8],[-1,-1,-1,-1,-1,-1],[[1,-10],[2,-2],[-2,2],[1,6],[-2,10],[1,14]],"granny knot (sum of two identical trefoils)"],
 [[4,6,2,-10,-12,-8],[1,1,1,1,1,1],[[1,-14],[-2,-10],[1,-6],[-2,-2],[2,2],[1,10]],"square knot (sum of two mirrored trefoils)"],
 [[6,-12,2,8,-4,-10],[-1,-1,-1,1,-1,1],[[1,-2],[1,6],[-1,10]],"example knot"]
]

Recursos externos

No es necesario para el desafío, pero si estás interesado:


puestos de pruebas: 1 , 2

gracias @ChasBrown y @ H.Pwiz por detectar un error en mi definición de notación Dowker

Don mil
fuente
Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
Mego
1
@ngn: ¡Mucho mejor! Supuse que eso era lo que quería decir, pero es un poco trabalenguas expresarlo correctamente. :)
Chas Brown

Respuestas:

10

K (NGN / K) , 196 193 bytes

{!N::2*n:#x;{+/d,'x,'d:&:'-2!(|/n)-n:#:'x}(+/1-2*s){j::+,/y;,/(&0|2*x;(-1+#?{x[j]&:x@|j;x}/!N){-(d,x)+x,d:&4}/,1;&0|-2*x)}'(N!{(x,'|1+x;x+/:!2)}'((2*!n),'-1+x|-x)@'0 1=/:x>0)@'/:+~(y<0)=s:!n#2}

Pruébalo en línea!

ngn
fuente
12

Brain-Flak , 1316 bytes

(({})<({()<(({}<>))><>}){(({})[()()]<{([{}]({})<>({}<>))}{}(([({}<>)]<<>({}<>)<>((({})<<>{({}<>)<>}<>>))>)){({}<>)<>}<>{}(({}<{}(({}<{({}<>)<>}>))>))<>{({}<>)<>}>)}<>>){(({}){}()<({}<>)>)<>{}(({}){}<>)<>}<>{}{}(()){(<({}<({}<>)>)>)<>((){[()](<(({})<>){({}[({})]<>({}<>))}{}({}<>({}<{}<>{({}<>)<>}>)[()])<>({}({})[()])(([()]{()(<({}[({})]())>)}{})<{(<{}{}>)}{}><>{()((<({}()[({}<>)])<>>))}{}<{}{}>)((){[()]<({}()<({}<({}<<>({()<({}<>)<>>}<>){({}[()]<(({})<({()<({}<>)<>>})<>>)<>{({}[()]<<>({}<>)>)}{}>)}<>>)<>>)>)((){[()](<{}(({})<<>(({})<(<<>({}<<>({}<(()()){({}[()]<([{}]()<>)<>({}<<>{({}({})<>[({}<>)])}{}{}>){({}<>)<>}<>>)}{}>{})>)>)<>{}{({}<>)<>}<>([({}<>)]<((()))>)(())<>({}<>)<>{}({}[()]){<>({}<<>(()()){({}[()]<({}<<>{({}<>)<>}>){({}[({})]<>({}<>))}{}(({})<<>({}<>)<>([{}])>)>)}{}{}>)<>({}<(({})())>[()]<>)}{}({}<<>{}([{}]()<{({}<>)<>}>){({}({})<>[({}<>)])}{}{}>){({}<>)<>}<>{}{}{}>{})>)>)}{}){(<{}(({})<<>(({}{})<<>(<({}<>)>)<>{}{({}<>)<>}<>>(({}){}){})>)>)}>}{}){(<{}([{}]<({}<<>([{}]()<>)<>({}<<>{({}({})<>[({}<>)])}{}{}>){({}<>)<>}<>>({})({}){})>)>)}{}>)}{}){{}(([{}]){}<>{}{}<<>({}<>{}){([{}]({}()()<{}({}<>)(())<>>))}{}{}{}>{})(())<>{{}({}<>)(())<>}(<>)<>}{}}{}{}<>{}{}({}<{{}({}<>)(())<>}<>{{}{((<(())>))}{}}{}{{}({}<>)(())<>}>)<>{{}({}<(<()>)<>([]){{}({}<>)(())<>([])}{}>)<>{{}({}<>)<>}{}{}({}<>)<>}<>

Pruébalo en línea!

Me arrepiento de nada. La entrada es una lista aplanada de pares.

# Part 1: extract edges
(({})<

({()<(({}<>))><>}){

(({})[()()]<

{([{}]({})<>({}<>))}{}(([({}<>)]<<>({}<>)<>((({})<<>{({}<>)<>}<>>))>)){({}<>)<>}

<>{}(({}<{}(({}<{({}<>)<>}>))>))<>{({}<>)<>}

>)}

<>>){(({}){}()<({}<>)>)<>{}(({}){}<>)<>}<>

{}{}(())

# Part 2: Compute bracket polynomial
{

  # Move degree/sign to other stack
  (<({}<({}<>)>)>)<>

  # If current shape has crossings:
  ((){[()](<

    # Consider first currently listed edge in set
    # Find the other edge leaving same crossing
    (({})<>){({}[({})]<>({}<>))}{}

    # Move to top of other stack
    # Also check for twist
    ({}<>({}<{}<>{({}<>)<>}>)[()])

    # Check for twist in current edge
    <>({}({})[()])

    (

      # Remove current edge if twist
      ([()]{()(<({}[({})]())>)}{})<{(<{}{}>)}{}>

      # Remove matching edge if twist
      <>{()((<({}()[({}<>)])<>>))}{}<{}{}>

    # Push 1 minus number of twists from current vertex.
    )

    # If number of twists is not 1:
    ((){[()]<

      # While testing whether number of twists is 2:
      ({}()<

        # Keep sign/degree on third stack:
        ({}<({}<

          # Duplicate current configuration
          <>({()<({}<>)<>>}<>){({}[()]<(({})<({()<({}<>)<>>})<>>)<>{({}[()]<<>({}<>)>)}{}>)}

        # Push sign and degree on separate stacks
        <>>)<>>)

      # If number of twists is not 2: (i.e., no twists)
      >)((){[()](<{}

        # Make first copy of sign/degree
        (({})<<>(({})<

          # Make second copy of sign/degree
          (<<>({}<<>({}<

            # Do twice:
            (()()){({}[()]<

              # Prepare search for vertex leading into crossing on other side
              ([{}]()<>)

              # While keeping destination on third stack:
              <>({}<

                # Search for matching edge
                <>{({}({})<>[({}<>)])}{}

              # Replace old destination
              {}>)

              # Move back to original stack
              {({}<>)<>}<>

            >)}{}

          # Add orientation to degree
          >{})>)>)

          # Move duplicate to left stack
          <>{}{({}<>)<>}<>

          # Create "fake" edges from current crossing as termination conditions
          ([({}<>)]<((()))>)(())<>

          # Create representation of "top" new edge
          ({}<>)<>{}({}[()])

          # While didn't reach initial crossing again:
          {

            # Keep destination of new edge on third stack
            <>({}<<>

              # Do twice:
              (()()){({}[()]<

                # Search for crossing
                ({}<<>{({}<>)<>}>){({}[({})]<>({}<>))}{}

                # Reverse orientation of crossing
                (({})<<>({}<>)<>([{}])>)

              >)}{}

              # Remove extraneous search term
              {}

            # Push new destination for edge
            >)

            # Set up next edge
            <>({}<(({})())>[()]<>)

          }

          # Get destination of last edge to link up
          {}({}<

            # Find edge headed toward original crossing
            <>{}([{}]()<{({}<>)<>}>){({}({})<>[({}<>)])}

          # Replace destination
          {}{}>)

          # Move everything to left stack
          {({}<>)<>}

          # Clean up temporary data
          <>{}{}{}

        # Push new sign/degree of negatively smoothed knot
        >{})>)

      # Else (two twists)
      # i.e., crossing is the twist in unknot with one half-twist
      >)}{}){(<{}

        # Copy sign and degree+orientation
        (({})<<>(({}{})<

          # Move sign to left stack
          <>(<({}<>)>)

          # Move copy of configuration to left stack
          <>{}{({}<>)<>}

        # Add an additional 4*orientation to degree
        <>>(({}){}){})>)

      >)}

    # Else (one twist)
    >}{}){(<

      # Invert sign and get degree
      {}([{}]<({}<

        # Search term for other edge leading to this crossing
        <>([{}]()<>)

        # With destination on third stack:
        <>({}<

          # Find matching edge
          <>{({}({})<>[({}<>)])}{}

        # Replace destination
        {}>)

        # Move stuff back to left stack
        {({}<>)<>}<>

      # Add 3*orientation to degree
      >({})({}){})>)

    >)}{}

  # Else (no crossings)
  >)}{}){{}

    # If this came from the 2-twist case, undo splitting.
    # If this came from an initial empty input, use implicit zeros to not join anything
    # New sign = sign - 2 * next entry sign
    (([{}]){}<>{}{}<

      # New degree = average of both degrees
      <>({}<>{})

      # Find coefficient corresponding to degree
      {([{}]({}()()<{}({}<>)(())<>>))}{}{}

    # Add sign to coefficient
    {}>{})

    # Move rest of polynomial back to right stack
    (())<>{{}({}<>)(())<>}

    # Set up next configuration
    (<>)<>

  }{}

}{}{}<>{}

# Step 3: Put polynomial in correct form

# Keeping constant term:
{}({}<

  # Move to other stack to get access to terms of highest absolute degree
  {{}({}<>)(())<>}<>

  # Remove outer zeros
  {{}{((<(())>))}{}}

  # Move back to right stack to get access to lower order terms
  {}{{}({}<>)(())<>}

>)<>

# While terms remain:
{

  # Move term with positive coefficient
  {}({}<(<()>)<>([]){{}({}<>)(())<>([])}{}>)<>{{}({}<>)<>}{}

  # Move term with negative coefficient
  {}({}<>)<>

}<>
Nitrodon
fuente
Whoaaaaaa. ¡¡¡¡Fantástico!!!! +1
Don Thousand
Siento que necesito repartir otra recompensa
Don Thousand el