Décomposer une permutation en cycles

15

Il existe un théorème bien connu selon lequel toute permutation peut être décomposée en un ensemble de cycles . Votre travail consiste à écrire le programme le plus court possible pour le faire.

Contribution:

Deux lignes. Le premier contient un nombre N, le second contient Ndes entiers distincts dans la plage [0,N-1]séparée par des espaces. Ces entiers représentent une permutation d' Néléments.

Production:

Une ligne pour chaque cycle de la permutation. Chaque ligne doit être une liste d'entiers séparés par des espaces dans l'ordre des cycles.

Les cycles peuvent être émis dans n'importe quel ordre et chaque cycle peut être émis à partir de n'importe quelle position.

Exemple 1:

8
2 3 4 5 6 7 0 1

Cette entrée code la permutation 0-> 2, 1-> 3, 2-> 4, 3-> 5, 4-> 6, 5-> 7, 6-> 0, 7-> 1. Cela se décompose en cycles comme celui-ci:

0 2 4 6
1 3 5 7

Une sortie tout aussi valide serait

5 7 1 3
2 4 6 0

Exemple 2:

8
0 1 3 4 5 6 7 2

sortie valide:

0
1
4 5 6 7 2 3
Keith Randall
la source
@Keith Quelle est la valeur maximale de N?
fR0DDY
3
3 caractères en J:>C.
Eelvex
Disons N <1000.
Keith Randall
Les permutations sont généralement comptées à partir de 1, pas de 0.
Dr. belisarius
6
Les mathématiciens comptent à partir de 1, les informaticiens comptent à partir de 0 :)
Keith Randall

Réponses:

4

C 145 134 Caractères

N,A[999],i,j,f;main(){gets(&i);for(;~scanf("%d",A+N);)N++;for(;j<N;j++,f=f&&!puts(""))while(i=A[j]+1)f=printf("%d ",j),A[j]=-1,j=--i;}

http://www.ideone.com/BrWJT

fR0DDY
la source
Est-il légal d'appeler des fonctions variadiques implicitement déclarées? Est-il légal d'omettre d'abord int?
6502
Il est légal de faire quoi que ce soit tant que le code fonctionne. Bien qu'il puisse donner des avertissements, tant qu'il ne donne pas d'erreurs, il devrait être OK.
fR0DDY
L'essentiel est dans le sens de «œuvres». Quoi qu'il en soit, j'ai ajouté une réponse (139 caractères) qui utilise cette règle (c'est-à-dire où "fonctionne" signifie "il y a au moins un compilateur C auto-déclaré dans lequel, apparemment, le code machine généré fonctionne")
6502
+1: J'aime l' gets(&i)idée de me débarrasser de cette première ligne inutile, mais cela ne fonctionnerait clairement pas sur les systèmes 16 bits si plus de 10 éléments sont passés. Mais encore une fois, si les règles sont "trouver au moins un programme qui prétend être un compilateur C qui crée un exécutable où dans au moins un cas semble - au moins pour moi - donner une réponse valide" alors c'est une amélioration: - )
6502
2

Python 131 caractères

input();d=dict((i,int(x))for i,x in enumerate(raw_input().split()))
while d:
 x=list(d)[0]
 while x in d:print x,;x=d.pop(x)
 print

la nouvelle ligne de fin n'est pas nécessaire

6502
la source
1

Haskell, 131 caractères

n%l|all(>n)l=(n:l>>=(++" ").show)++"\n"|1<3=""
c(_:a)=a>>=(\n->n%(takeWhile(/=n)$iterate(a!!)$a!!n))
main=interact$c.map read.words
  • Edit: (135 -> 131) >=est devenu >, éliminé deux tailappels grâce à la correspondance de modèles et à la pré-application de a!!.
MtnViewMark
la source
1

C (en quelque sorte), 139 caractères

n,j,t,a[999];main(){scanf("%*i");for(;scanf("%i",a+n)>0;)n++;while(n--)if(a[j=n]+1){for(;t=a[j]+1;a[j]=-1,j=t)printf("%i ",--t);puts("");}}

La nouvelle ligne finale n'est pas incluse.

J'ai dit "en quelque sorte" parce que l'AFAIK par exemple

  1. il n'est pas légal d'omettre la déclaration des fonctions variadiques (ANSI C89: 3.3.2.2)
  2. intne peut pas être omis pour la déclaration de variable (je n'ai pas trouvé où il est dit qu'il peut être omis et la déclaration de type implicite n'est décrite que pour les fonctions. La spécification de grammaire dans la norme est fondamentalement inutile car accepte beaucoup plus que les déclarations C valides, par exemple double double void volatile x;)
  3. une nouvelle ligne à la fin d'un fichier source non vide est obligatoire (ANSI C89: A.6.2)

mais le code ci-dessus compilé avec gcc -ocycles cycles.cfonctionne apparemment de toute façon.

6502
la source
Ceci est un programme C valide, mais ce n'est pas C99.
Quixotic
@Debanjan: Non ce n'est pas ANSI C (pas même 89). Par exemple, la norme dit (3.3.2.2) que si une fonction utilise un nombre variable d'arguments, elle ne peut pas être déclarée implicitement sur le site d'appel de la fonction (en d'autres termes, vous ne pouvez pas appeler scanfsans #include <stdio.h>même si les paramètres sont corrects et ne nécessitent pas de conversions ):<<If the function is defined with a type that includes a prototype, and the types of the arguments after promotion are not compatible with the types of the parameters, or if the prototype ends with an ellipsis ( ", ..." ), the behavior is undefined.>>
6502
1

J (entre 2 et 32)

Je ne suis pas tout à fait clair sur le format d'E / S, mais je pense que ce C.serait le cas si la sortie suivante était acceptée:

   C. 0 1 3 4 5 6 7 2
┌─┬─┬───────────┐
│0│1│7 2 3 4 5 6│
└─┴─┴───────────┘

(Il semble mieux dans le terminal J.)

S'il doit s'agir d'une fonction nommée conforme à ma meilleure compréhension du format d'E / S, ce serait 32 caractères, dont 30 pour la conversion du format de sortie ...

g=:>@(":L:0)@(C.@".@}.~>:@i.&LF)

En action:

   g=:>@(":L:0)@(C.@".@}.~>:@i.&LF)
   g
>@(":L:0)@(C.@".@}.~ >:@i.&(10{a.))
   t
8
0 1 3 4 5 6 7 2
   g t
0          
1          
7 2 3 4 5 6

Explication:

J est exécuté de droite à gauche (pratiquement). @est une «fonction» (pas techniquement une fonction, mais c'est assez proche) pour combiner des fonctions.

  • i.&LF- trouver le premier index de LF, une variable prédéfinie contenant le caractère ASCII numéro 10, le saut de ligne.
  • >:- trouver le premier LF, et incrémenter son index de un. Nous ne voulons pas réellement le saut de ligne, nous voulons le tableau qui le suit.
  • }.~ - Sélectionne la partie de l'entrée que nous voulons.
  • ".- Puisque le format d'entrée est valide J ( * \ õ / * ), nous pouvons simplement utiliser le evalverbe (je sais qu'il n'est pas réellement appelé eval.) Pour le transformer en un tableau
  • C.- Magie pure. Je n'ai vraiment aucune idée de ce que cela fait, mais cela semble fonctionner!
  • ":L:0- Représentation. Transforme la sortie de C.en une séquence encadrée de chaînes
  • >- Déballer. La sortie réelle est en fait un tableau de chaînes (il y a des espaces derrière le premier pour les numéros de l'exemple).
ɐɔıʇǝɥʇuʎs
la source
0

Clojure, 145

(let[v(vec(repeatedly(read)read))](loop[a(set v)b 0](cond(a(v b))(do(print" "b)(recur(disj a(v b))(v b)))(seq a)(do(prn)(recur a(first a)))1"")))

Quelque peu non golfé et divisé en une fonction (l'entrée doit être un vecteur, ce que produit (vec (lecture répétée)) d'en haut):

(defn p [v]
  (loop [a (set v) b 0]
    (cond
     (a (v b)) (do (print" "b) (recur (disj a (v b)) (v b)))
     (seq a) (do (prn) (recur a (first a)))
     1 "")))

(Wow, je viens de remarquer que ce défi a plus de 3 ans. Oh bien, amusez-vous quand même!)

YosemiteMark
la source