Decomporre una permutazione in cicli


15

Esiste un noto teorema secondo il quale qualsiasi permutazione può essere scomposta in una serie di cicli . Il tuo compito è quello di scrivere il programma più breve possibile per farlo.

Ingresso:

Due linee. Il primo contiene un numero N, il secondo contiene Ninteri distinti nell'intervallo [0,N-1]separato da spazi. Questi numeri interi rappresentano una permutazione di Nelementi.

Produzione:

Una riga per ogni ciclo nella permutazione. Ogni riga dovrebbe essere un elenco separato da spazi di numeri interi in ordine di ciclo.

I cicli possono essere emessi in qualsiasi ordine e ogni ciclo può essere emesso a partire da qualsiasi posizione.

Esempio 1:

8
2 3 4 5 6 7 0 1

Questo ingresso codifica la permutazione 0-> 2, 1-> 3, 2-> 4, 3-> 5, 4-> 6, 5-> 7, 6-> 0, 7-> 1. Questo si decompone in cicli come questo:

0 2 4 6
1 3 5 7

Un output ugualmente valido sarebbe

5 7 1 3
2 4 6 0

Esempio 2:

8
0 1 3 4 5 6 7 2

uscita valida:

0
1
4 5 6 7 2 3

@Keith Qual è il valore massimo di N?
fR0DDY,

3
3 caratteri in J:>C.
Eelvex

Diciamo N <1000.
Keith Randall,

Le permutazioni di solito vengono contate da 1, non da 0.
Dr. belisarius,

6
I matematici contano da 1, gli informatici contano da 0 :)
Keith Randall

Risposte:


4

C 145 134 personaggi

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


È legale chiamare funzioni variadiche dichiarate implicitamente? È legale omettere prima int?
6502

È legale fare qualsiasi cosa fintanto che il codice funziona. Mentre può dare avvisi, purché non dia errori, dovrebbe essere OK.
fR0DDY

Il punto è nel significato di "opere". Comunque ho aggiunto una risposta (139 caratteri) che usa questa regola (cioè dove "funziona" significa "c'è almeno un compilatore C auto-dichiarato in cui, a quanto pare, il codice macchina generato funziona")
6502

+1: Mi piace l' gets(&i)idea di sbarazzarmi di quella prima riga inutile, tuttavia questo chiaramente non funzionerebbe su sistemi a 16 bit se fossero passati più di 10 elementi. Ma ancora una volta se le regole "trovano almeno un programma che afferma di essere un compilatore C che crea un eseguibile in cui almeno in un caso sembra - almeno per me - dare una risposta valida", allora questo è un miglioramento: - )
6502

2

Python 131 caratteri

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 riga finale non è necessaria


1

Haskell, 131 caratteri

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
  • Modifica: (135 -> 131) è >=diventato >, ha eliminato due tailchiamate tramite pattern matching e pre-applicazione di a!!.

1

C (sorta di), 139 caratteri

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 nuova riga finale non è inclusa.

Ho detto "una specie di" perché AFAIK per esempio

  1. non è legale omettere la dichiarazione per le funzioni variadiche (ANSI C89: 3.3.2.2)
  2. intnon può essere omesso per la dichiarazione variabile (non ho trovato dove si dice che può essere omesso e la dichiarazione di tipo implicito è descritta solo per le funzioni. Le specifiche grammaticali nello standard sono sostanzialmente inutili in quanto accettano molto più delle dichiarazioni C valide, per esempio double double void volatile x;)
  3. è obbligatoria una nuova riga alla fine di un file sorgente non vuoto (ANSI C89: A.6.2)

ma il codice sopra compilato gcc -ocycles cycles.capparentemente funziona comunque.


Questo è un programma C valido, ma non è C99.
Chisciotte il

@Debanjan: No, non è ANSI C (nemmeno 89). Ad esempio lo standard dice (3.3.2.2) che se una funzione utilizza un numero variabile di argomenti non può essere dichiarata implicitamente nel sito di chiamata della funzione (in altre parole non è possibile chiamare scanfsenza #include <stdio.h>anche se i parametri sono corretti e non richiedono conversioni ):<<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 (tra 2 e 32)

Non sono abbastanza chiaro sul formato I / O, ma penso che C.farebbe, se il seguente output fosse accettato:

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

(Sembra meglio nel terminale J.)

Se deve essere una funzione denominata conforme alla mia migliore comprensione del formato I / O, sarebbero 32 caratteri, di cui 30 per la conversione del formato di output ...

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

In azione:

   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

Spiegazione:

J viene eseguito da destra a sinistra (praticamente). @è una "funzione" (non tecnicamente una funzione, ma abbastanza vicina) per combinare le funzioni.

  • i.&LF- trova il primo indice di LF, una variabile predefinita contenente il carattere ASCII numero 10, l'avanzamento di riga.
  • >:- trova il primo LFe incrementa l'indice di uno. In realtà non vogliamo il linefeed, vogliamo l'array che lo segue.
  • }.~ - Seleziona la parte dell'input che vogliamo.
  • ".- Poiché il formato di input è valido J ( * \ õ / * ), possiamo semplicemente usare il evalverbo (so che non è effettivamente chiamato eval.) Per trasformarlo in un array
  • C.- Pura magia. Non ho davvero idea di cosa faccia, ma sembra funzionare!
  • ":L:0- Rappresentazione. Trasforma l'output di C.in una sequenza inscatolata di stringhe
  • >- Unbox. L'output effettivo è in realtà un array di stringhe (ci sono spazi dietro il primo ai numeri dell'esempio).

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

Un po 'ungolfed, e suddiviso in una funzione (l'input deve essere un vettore, che è ciò che (vec (ripetutamente (leggi) leggi)) dall'alto produce):

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

(Caspita, ho appena notato che questa sfida ha più di 3 anni. Oh beh, mi sono divertito a farlo comunque!)

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.