Dessinez un chemin de permutation

20

Imaginez les diagrammes suivants comme des ensembles de tubes croisés verticaux.

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

Dans le diagramme le plus à gauche, les 1et 2glissent vers le bas de leurs barres obliques respectives, se croisent Xet sortent de part et d'autre de leur point de départ.

C'est la même idée dans le diagramme du milieu, mais le |signifie que les chemins ne se croisent pas, donc rien ne change.

Le diagramme le plus à droite montre un routage de tube plus complexe qui s'infiltre 1 2 3 4dans 3 1 4 2.

Objectif

Votre objectif dans ce défi de golf de code est de dessiner ces "diagrammes de routage de tubes" étant donné une permutation telle que 3 1 4 2. Le programme le plus court en octets gagnera.

Détails

  1. L'entrée provient de stdin comme toute permutation des nombres de 1 à n séparés par des espaces, où n est un entier positif. Vous pouvez supposer que toutes les entrées sont bien formées.
  2. La sortie du diagramme de routage passe à stdout.

    • La «suppression» des nombres de 1 à n dans le haut du diagramme devrait entraîner la permutation d'entrée en bas. (Le haut et le bas sont toujours des couches de barres obliques.)
    • Le diagramme n'a pas besoin d'être de petite taille optimale. Il peut y avoir autant de niveaux que nécessaire tant qu'il est correct.
    • Le diagramme ne doit contenir que les caractères \/ X|ainsi que les retours à la ligne (pas de chiffres).
    • |doit toujours être utilisé sur les intersections les plus externes, car l'utilisation Xn'aurait aucun sens.
    • Quelques espaces de début ou de fin sont corrects tant que le diagramme est correctement aligné.

Exemples

Une entrée de 3 1 4 2pourrait produire (comme ci-dessus)

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

Un apport de 1pourrait produire

 \
  |
 /
|
 \
  |
 /

Un apport de 3 2 1pourrait produire

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

Un apport de 2 1 3 4 6 5pourrait produire

\ / \ / \ /
 X   |   X
/ \ / \ / \
Loisirs de Calvin
la source
4
Grande question! Je ne peux pas croire que cela fait seulement deux semaines que vous vous êtes joints - vous semblez être partout.
xnor
@xnor: D Merci beaucoup. Mais vraiment j'ai passé trop de temps ici ...
Calvin's Hobbies
Un peut-il se Xconnecter directement à un comme |le fait un /? À un autre X?
xnor
1
@xnor Non , il doit toujours être en row of slashes, row of X's and |'s, row of slashes, row of X's and |'s, ... format.
Les loisirs de Calvin le
Peut nêtre supérieur à 10?
Julurous

Réponses:

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]

J'ai adopté une approche légèrement différente: je trouve les swaps nécessaires pour trier l'entrée, puis inverser verticalement pour obtenir les swaps nécessaires pour transformer la liste triée en entrée. En prime de cette approche, il peut prendre une liste arbitraire de nombres et donner le chemin de permutation pour transformer le type d'entrée en entrée.

Exemple:

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

Améliorations:

264 -> 261: Boucle externe commutée de pour à while.

261 -> 259: utilisé à la f%2place de (c^m), car en python, les opérateurs arithmétiques ont une priorité plus élevée que les opérateurs au niveau du bit.

259 -> 252: Boucle intérieure commutée de pour à while. Combiné iet cvariables.

252 -> 247: build modifié puis inversé pour simplement construire dans l'ordre inverse.

247 -> 243: Ajout de nouvelles lignes manuellement, au lieu d'utiliser la jointure.

243 -> 227: Adoption de la méthode de génération de lignes de barre oblique de grc (merci grc!) Et ajout de s.

227 -> 224: Déplacement de la génération de ligne de barre oblique avant la boucle while intérieure pour supprimer un %4et enregistrer un caractère en utilisant un découpage étendu.

224 -> 222: Supprimé m.

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

220 -> 219: | 1<n-1|-> |~i>-n|(espace de tête supprimé)

219 -> 218: initialisations combinées de oet set déplacé la tranche à la fin.

isaacg
la source
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

J'ai opté pour une approche assez basique, mais elle s'est avérée un peu plus longue que ce que j'espérais. Il considère la liste par paires et décide de permuter ou non chaque paire. Cette opération est répétée pour chaque ligne entrecroisée jusqu'à ce que la liste corresponde à l'entrée.

Exemple:

$ 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
la source
2

JavaScript HTML, 553 419

Merci à @izlin et @TomHart d'avoir signalé mes erreurs.

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

Testez ici: http://goo.gl/NRsXEj
entrez la description de l'image ici entrez la description de l'image ici

JeffSB
la source
Vous avez fait une petite erreur: la première ligne doit être les numéros triés et la dernière ligne doit être votre entrée comme dans les exemples ci-dessus.
izlin
Tu as raison. Merci. J'ai regardé la sortie de @ grc et j'ai pensé que les nombres étaient la position de départ. Oups.
JeffSB
Je me trompe peut-être, mais dans les deux photos que vous avez publiées, la dernière ligne n'est-elle pas redondante car rien ne change?
TMH
Oui, tu as raison. Je savais que c'était un consensus sur la façon dont je l'ai fait. Mais cela ne doit probablement pas l'être. J'y penserai. Merci pour le commentaire.
JeffSB
@izlin - Merci de l'avoir remarqué. J'ai corrigé cette erreur.
JeffSB
1

Javascript - 395

378 si je n'imprime pas les chiffres sur ma sortie, mais cela semble beaucoup mieux et améliore la lisibilité.
Testez-le ici . (avec version non golfée)

Version golfée :

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)

Explication

D'abord, je sous-entrave l'entrée, avec le numéro d'index et change la première ligne avec les résultats. Par exemple

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

Avec cette substitution, je peux utiliser un algorithme de tri à bulles pour trier 2,4,1,3 à 1,2,3,4 et le graphique sera le plus court possible que nous recherchons.
Si vous avez des idées sur la façon de réduire le code, commentez :)

Exemple

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
la source
(1) Je vois que vous utilisez la balise BR à trois endroits, et donc vous pourriez économiser un peu en mettant cela dans une variable. Vous pourriez aussi probablement utiliser \ n depuis votre sortie vers un PRE.
JeffSB
(2) J'ai essayé différentes façons de gérer le golf avec JavaScript et j'ai également une entrée et une sortie pratiques. Je pense que j'aime ma dernière méthode inspirée de votre invite et alerte ... J'utilise invite et alerte dans le code afin qu'il puisse être collé dans une console et qu'il fonctionne pour tout le monde. Mais j'ai aussi fait une page web avec un TEXTAREA et PRE pour le montrer fonctionnant. La page Web remplace l'invite et l'alerte pour utiliser TEXTAREA et PRE - c'est donc le même code et il y a moins de confusion - peut-être?
JeffSB
@JeffSB J'ai utilisé la <br>balise et la zone de texte uniquement sur jsfiddle, car cela semble beaucoup mieux. L'alerte n'a pas de police à espacement fixe, donc la sortie est mauvaise. Dans ma version golfée, j'utilise alert et \ n. Votre page Web est-elle publique?
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]

Il fonctionne en déplaçant chaque élément en place à partir de la gauche. Pour cette raison, il produira souvent une carte des chemins ridiculement grande (bien que toujours correcte).

Exemples:

3 1 4 2

\ / \ / 
 X   X  
/ \ / \ 
|  X  |
\ / \ / 
 X   X  
/ \ / \ 
|  X  |
\ / \ / 
 X   X  
/ \ / \ 
|  X  |
\ / \ / 
Οurous
la source