Dibuja un camino de permutación

20

Imagine los siguientes diagramas como conjuntos de tubos verticales entrecruzados.

1 2    1 2    1 2 3 4
\ /    \ /    \ / \ /
 X      |      |   |
/ \    / \    / \ / \
2 1    1 2   |   X   |
              \ / \ /
               X   X
              / \ / \
              3 1 4 2

En el diagrama de la izquierda, el 1y 2deslice hacia abajo sus barras diagonales respectivas, cruce en Xy salga en lados opuestos de donde comenzaron.

Es la misma idea en el diagrama del medio, pero |significa que los caminos no se cruzan, por lo que nada cambia.

El diagrama de la derecha muestra una ruta de tubo más compleja que permuta 1 2 3 4en 3 1 4 2.

Objetivo

Su objetivo en este desafío de golf de código es dibujar estos "diagramas de enrutamiento de tubos" dada una permutación como 3 1 4 2. El programa más corto en bytes ganará.

Detalles

  1. La entrada proviene de stdin como cualquier permutación de los números del 1 al n separados por espacios, donde n es un entero positivo. Puede suponer que todas las entradas están bien formadas.
  2. La salida del diagrama de enrutamiento va a stdout.

    • "Dejar caer" los números del 1 al n en orden en la parte superior del diagrama debería dar como resultado que la permutación de entrada salga en la parte inferior. (Arriba y abajo siempre son capas de barras).
    • El diagrama no necesita ser óptimamente pequeño. Puede ser tantos niveles como sea necesario siempre que sea correcto.
    • El diagrama solo debe contener los caracteres \/ X|y las nuevas líneas (sin números).
    • |siempre debe usarse en las intersecciones más externas ya que usarlo Xno tendría sentido.
    • Algunos espacios iniciales o finales están bien siempre que el diagrama esté alineado correctamente.

Ejemplos

Una entrada de 3 1 4 2podría producir (igual que arriba)

 \ / \ /
  |   | 
 / \ / \
|   X   |
 \ / \ /
  X   X 
 / \ / \

Una entrada de 1podría producir

 \
  |
 /
|
 \
  |
 /

Una entrada de 3 2 1podría producir

 \ / \
  X   |
 / \ /
|   X
 \ / \
  X   |
 / \ /

Una entrada de 2 1 3 4 6 5podría producir

\ / \ / \ /
 X   |   X
/ \ / \ / \
Pasatiempos de Calvin
fuente
44
Gran pregunta! No puedo creer que solo hayan pasado dos semanas en que te uniste, parece que estás en todas partes.
xnor
@xnor: D Muchas gracias. Pero realmente he estado pasando demasiado tiempo aquí ...
Calvin's Hobbies
¿Se puede Xconectar directamente a un |modo como lo /hace? A otro X?
xnor
1
@xnor No. Siempre debe estar en el row of slashes, row of X's and |'s, row of slashes, row of X's and |'s, ... formato.
Aficiones de Calvin
Puede nser mayor de 10?
Julurous

Respuestas:

4

Python 2, 218 219 220 222 224 227 243 247 252 259 261 264

l=map(int,raw_input().split())
f=n=len(l)
o=s=n*' \ /'
while f+n%2:
 f-=1;i=f+n&1;a=s[2*i:][:2*n]+'\n|   '[::2-i]
 while~i>-n:a+='|X'[l[i+1]<l[i]]+'   ';l[i:i+2]=sorted(l[i:i+2]);i+=2
 o=a+f%2*'|'+'\n'+o
print o[:-2*n]

Tomé un enfoque ligeramente diferente: encuentro los intercambios necesarios para ordenar la entrada, luego lo invierto verticalmente para obtener los intercambios necesarios para convertir la lista ordenada en la entrada. Como una ventaja adicional de este enfoque, puede tomar una lista arbitraria de números y proporcionar la ruta de permutación para convertir el tipo de entrada en la entrada.

Ejemplo:

$ python sort_path.py <<< '3 1 4 5 9 2 6 8 7'
 \ / \ / \ / \ / \
  |   |   |   |   |
 / \ / \ / \ / \ /
|   |   |   |   |   
 \ / \ / \ / \ / \
  |   |   |   |   |
 / \ / \ / \ / \ /
|   |   |   |   |   
 \ / \ / \ / \ / \
  |   |   |   |   |
 / \ / \ / \ / \ /
|   X   |   |   X   
 \ / \ / \ / \ / \
  |   X   |   X   |
 / \ / \ / \ / \ /
|   |   X   X   |   
 \ / \ / \ / \ / \
  X   |   X   |   |
 / \ / \ / \ / \ /
|   |   |   |   X   
 \ / \ / \ / \ / \

Mejoras:

264 -> 261: bucle externo conmutado de for a while.

261 -> 259: se usa en f%2lugar de (c^m), porque en python los operadores aritméticos tienen mayor prioridad que los operadores bit a bit.

259 -> 252: bucle interno conmutado de por a mientras. Combinados iy cvariables.

252 -> 247: Se modificó la construcción y luego se invirtió para simplemente construir en orden inverso.

247 -> 243: se agregaron nuevas líneas manualmente, en lugar de usar join.

243 -> 227: Se adoptó el método de generación de líneas diagonales de grc (¡gracias grc!) Y se agregó s.

227 -> 224: Se movió la generación de línea de barra diagonal al bucle while interno anterior para eliminar ay %4guardar un carácter mediante el corte por división extendido.

224 -> 222: eliminado m.

222 -> 220: f%2+n%2->f+n&1

220 -> 219: | 1<n-1|-> |~i>-n|(espacio inicial eliminado)

219 -> 218: Inicializaciones combinadas de oy sy movieron el corte al final.

isaacg
fuente
9

Python, 290

def g(o,u=1):
 s=['|']*o
 for i in range(o,n-1,2):v=r[i+1]in a[:a.index(r[i])]*u;s+=['|X'[v]];r[i:i+2]=r[i:i+2][::1-2*v]
 print'  '*(1-o)+'   '.join(s+['|']*(o^n%2))*u+'\n'*u+(' / \\'*n)[2*o:][:n*2]
a=map(int,raw_input().split())
n=len(a)
r=range(1,n+1)
o=1
g(1,0)
g(0)
while r!=a:g(o);o^=1

Seguí un enfoque bastante básico, pero resultó un poco más de lo que esperaba. Considera la lista en pares y decide si intercambia o no cada par. Esto se repite para cada fila de intersección hasta que la lista coincida con la entrada.

Ejemplo:

$ python path.py
5 3 8 1 4 9 2 7 6
 \ / \ / \ / \ / \
  |   |   |   X   |
 / \ / \ / \ / \ /
|   X   X   X   X
 \ / \ / \ / \ / \
  X   X   X   X   |
 / \ / \ / \ / \ /
|   X   X   |   X
 \ / \ / \ / \ / \
  X   X   X   |   |
 / \ / \ / \ / \ /
|   |   |   X   |
 \ / \ / \ / \ / \
grc
fuente
2

HTML JavaScript, 553 419

Gracias a @izlin y @TomHart por señalar mis errores.

p=prompt();b=p.split(" "),l=b.length,d=l%2,o="",s=["","","\\/"],n="\n",a=[];for(i=0;i<l;i++){a[b[i]-1]=i+1;s[1]+=" "+s[2][i%2];s[0]+=" "+s[2][(i+1)%2];o+=" "+(i+1)}s[1]+=n,s[0]+=n;o+=n+s[1];f=1,g=2;do{var c="";for(var i=(f=f?0:1);i<l-1;i+=2)if(a[i]>a[i+1]){c+="  x ";g=2;t=a[i];a[i]=a[i+1];a[i+1]=t;}else c+="  | ";if(g==2){o+=(d?(f?"| "+c:c+"  |"):(f?"| "+c+"  |":c))+n;o+=(s[f]);}}while(--g);o+=" "+p;alert(o);

Prueba aquí: http://goo.gl/NRsXEj
ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

JeffSB
fuente
Cometiste un pequeño error: la primera línea debería ser los números ordenados y la última línea debería ser tu entrada como en los ejemplos anteriores.
izlin
Tienes razón. Gracias. Miré la salida de @ grc y pensé que los números eran la posición inicial. Ups
JeffSB
Podría estar mirando esto mal, pero en las dos imágenes que publicó, ¿no es redundante la última fila ya que nada cambia?
TMH
Sí, tiene usted razón. Sabía que esto era un consenso de cómo lo hice. Pero probablemente no tiene que ser así. Pensaré en esto. Gracias por el comentario.
JeffSB
@izlin - Gracias por notar esto. Arreglé este error.
JeffSB
1

Javascript - 395

378 si no imprimo los números en mi salida, pero se ve mucho mejor y mejora la legibilidad.
Pruébalo aquí . (con versión sin

golf ) Versión con golf:

a=prompt(),n=a.split(" "),l=n.length,k=[],s="",i=1;for(j=0;j<l;j++){k[n[j]-1]=j+1;s+=" "+(j+1)}s+="\n";while(i++){for(j=0;j<l;j++)s+=i%2?j%2?" \\":" /":j%2?" /":" \\";for(z=0,y=0;z<l-1;z++)if(k[z]>k[z+1])y=1;if(y==0&&i!=2)break;s+="\n";for(m=i%2;m<l;m+=2){s+=i%2&&m==1?"|":"";if(k[m]>k[m+1]){[k[m],k[m+1]]=[k[m+1],k[m]];s+=i%2?"   X":"  X "}else{s+=i%2?"   |":"  | "}}s+="\n"}s+="\n "+a;alert(s)

Explicación

Primero sustituyo la entrada, con el número de índice y cambio la primera línea con los resultados. Por ejemplo

3 1 4 2
v v v v substitude with
1 2 3 4

so the first line will become:
1 2 3 4
v v v v
2 4 1 3

sorting 1,2,3,4 to 3,1,4,2 is equivalent to 2,4,1,3 to 1,2,3,4

Con esta sustitución puedo usar un algoritmo de clasificación de burbujas para clasificar 2,4,1,3 a 1,2,3,4 y el gráfico será el más corto posible que estamos buscando.
Si tienes alguna idea de cómo puedo hacer que el código sea más pequeño, solo comenta :)

Ejemplo

input: 3 4 2 1 7 5 6
output:
 1 2 3 4 5 6 7
 \ / \ / \ / \
  X   |   |   | 
 / \ / \ / \ /
|   X   |   X
 \ / \ / \ / \
  X   X   X   | 
 / \ / \ / \ /
|   X   |   |
 \ / \ / \ / \
 3 4 2 1 7 5 6

izlin
fuente
(1) Veo que usa la etiqueta BR en tres lugares, por lo que podría ahorrar un poco al poner esto en una variable. También es probable que pueda usar \ n desde su salida a un PRE.
JeffSB
(2) He estado probando diferentes formas de lidiar con JavaScript de golf y también teniendo una entrada y salida conveniente. Creo que me gusta mi último método inspirado en su aviso y alerta ... Uso el aviso y la alerta en el código para que pueda pegarse en una consola y funcione para cualquier persona. Pero también hice una página web con TEXTAREA y PRE para mostrar que funciona. La página web anula el aviso y la alerta para usar TEXTAREA y PRE, por lo que es el mismo código y hay menos confusión, ¿tal vez?
JeffSB
@JeffSB Usé la <br>etiqueta y textarea solo en jsfiddle, porque se ve mucho mejor. La alerta no tiene una fuente monoespaciada, por lo que la salida se ve mal. En mi versión de golf utilizo alerta y \ n. ¿Tu página web es pública?
izlin
1

Cobra - 334 344 356 360

class P
    def main
        a,o,n=CobraCore.commandLineArgs[1:],['/','\\'],0
        c,l=a.count,a.sorted
        while (n+=1)%2or l<>a
            p,d='',(~n%4+4)//3
            for i in n%2*(c+1-c%2),p,o=p+o[1]+' ',[o.pop]+o
            for i in 1+d:c-n%2*c:2
                z=if(l[:i]<>a[:i],1,0)
                l.swap(i-z,i)
                p+=' ['|X'[z]]  '
            print[['','| '][d]+[p,p+'|'][d^c%2],p][n%2][:c*2]

Funciona moviendo cada elemento a su lugar comenzando desde la izquierda. Debido a esto, a menudo generará un mapa de ruta ridículamente grande (aunque todavía correcto).

Ejemplos:

3 1 4 2

\ / \ / 
 X   X  
/ \ / \ 
|  X  |
\ / \ / 
 X   X  
/ \ / \ 
|  X  |
\ / \ / 
 X   X  
/ \ / \ 
|  X  |
\ / \ / 
Οurous
fuente