Bir permütasyonu döngülere ayrıştırın


15

Herhangi bir permütasyonun bir dizi döngüye ayrılabileceği iyi bilinen bir teorem vardır . İşiniz mümkün olan en kısa programı yazmaktır.

Giriş:

İki çizgi. Birincisi bir sayı N, ikincisi boşluklarla ayrılmış Naralıkta farklı tamsayılar içerir [0,N-1]. Bu tamsayılar Nelementlerin permütasyonunu temsil eder .

Çıktı:

Permütasyondaki her döngü için bir satır. Her satır, döngü sırasında boşlukla ayrılmış bir tam sayı listesi olmalıdır.

Döngüler herhangi bir sırayla çıkarılabilir ve her bir döngü herhangi bir konumdan başlayarak çıkarılabilir.

Örnek 1:

8
2 3 4 5 6 7 0 1

Bu giriş 0-> 2, 1-> 3, 2-> 4, 3-> 5, 4-> 6, 5-> 7, 6-> 0, 7-> 1 permütasyonunu kodlar. Bu, aşağıdaki gibi döngüler halinde ayrışır:

0 2 4 6
1 3 5 7

Aynı derecede geçerli bir çıktı

5 7 1 3
2 4 6 0

Örnek 2:

8
0 1 3 4 5 6 7 2

geçerli çıktı:

0
1
4 5 6 7 2 3

@Keith N'nin maksimum değeri nedir?
17.03.2017

3
J'de 3 karakter:>C.
Eelvex

N <1000 diyelim.
Keith Randall

Permütasyonlar genellikle 0 değil, 1'den sayılır.
Dr.Belisarius

6
Matematikçiler 1'den sayılır, bilgisayar bilimcileri 0'dan sayılır :)
Keith Randall

Yanıtlar:


4

C 145134 Karakterler

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


Örtülü olarak bildirilen varyasyon işlevleri çağırmak yasal mı? Önce atlamak yasal mı int?
6502

Kod çalıştığı sürece herhangi bir şey yapmak yasaldır. Uyarı verebilse de, hata vermediği sürece Tamam olmalıdır.
fR0DDY

Asıl mesele "eserler" anlamındadır. Her neyse, bu kuralı kullanan bir cevap (139 karakter) ekledim (yani, "çalışır" anlamına gelir "görünüşte, oluşturulan makine kodunun çalıştığı en az bir kendi kendini beyan eden C derleyicisi var")
6502

+1: gets(&i)Bu işe yaramaz ilk satırdan kurtulma fikrini seviyorum , ancak 10'dan fazla eleman geçirilirse bu 16 bit sistemlerde açıkça işe yaramaz. Ancak bir kez daha kurallar "en azından bir durumda - en azından benim için - geçerli bir yanıt vermek gibi görünen bir yürütülebilir dosya oluşturan bir C derleyicisi olduğunu iddia eden bir program bulmak" ise, o zaman bu bir gelişme: - )
6502

2

Python 131 karakter

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

son satırsonuna gerek yok


1

Haskell, 131 karakter

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
  • Düzenleme: (135 -> 131) >=oldu >, taildesen eşleştirme ve ön uygulama olsa iki çağrı ortadan kaldırıldı a!!.

1

C (bir çeşit), 139 karakter

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

Son satırsonu dahil edilmemiştir.

"Bir çeşit" dedim çünkü AFAIK

  1. varyasyon fonksiyonları için beyanı atlamak yasal değildir (ANSI C89: 3.3.2.2)
  2. int Değişken bildirimi için atlanamaz (atlandığı ve örtük tip bildiriminin yalnızca işlevler için açıklandığı yerde bulamadım. Standarttaki gramer belirtimi, geçerli C bildirimlerinden çok daha fazlasını kabul ettiği için temelde işe yaramaz, örneğin double double void volatile x; )
  3. boş olmayan bir kaynak dosyanın sonundaki yeni satır zorunludur (ANSI C89: A.6.2)

ancak gcc -ocycles cycles.cgörünüşe göre derlenmiş yukarıdaki kod zaten çalışıyor.


Bu geçerli bir C programı, ancak bu C99 değil.
Quixotic

@Debanjan: Hayır ANSI C değil (89 bile değil). Örneğin standart (3.3.2.2) bir işlev başka bir deyişle (o zaman işlev çağrısı sitesinde örtük ilan edilemez bağımsız değişken bir dizi kullanıyorsa sen arayamayacağımı diyor scanfolmadan #include <stdio.h>parametreler doğru ve yapılacak olsa bile gerektirmeyen dönüşümleri ):<<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 (2 ile 32 arasında)

I / o biçiminde tam olarak açık değilim, ancak C.aşağıdaki çıktı kabul edilirse yapacağını düşünüyorum :

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

(J terminalinde daha iyi görünüyor.)

I / o biçimini en iyi anladığımla uyumlu bir adlandırılmış işlev olması gerekiyorsa, bu 32 karakterden oluşur ve bunların 30'u çıktı biçimi dönüşümü içindir ...

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

Eylemde:

   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

Açıklama:

J sağdan sola (pratik olarak) yürütülür. @işlevleri birleştirmek için bir 'işlev' (teknik olarak bir işlev değil, ancak yeterince yakın).

  • i.&LF- LFASCII karakter sayısı 10'u içeren önceden tanımlanmış bir değişken olan ilk dizini , satır feed'ini bulun .
  • >:- ilkini bulun ve LFdizinini bir artırın. Aslında satır beslemesini istemiyoruz, onu izleyen diziyi istiyoruz.
  • }.~ - Girişin istediğimiz bölümünü seçer.
  • ".- Giriş formatı J ( * \ õ / * ) geçerli olduğundan , evalfiili evalbir diziye dönüştürmek için kullanabiliriz (aslında çağrılmadığını biliyorum .)
  • C.- Saf büyü. Bunun ne yaptığına dair hiçbir fikrim yok, ama işe yarıyor gibi görünüyor!
  • ":L:0- Temsil. Çıktısını C.kutulu bir dizgi dizisine dönüştürür
  • >- Kutuyu kaldır. Gerçek çıktı aslında bir dize dizisidir (örneğin ilkinden sayılarına kadar boşluklar vardır).

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

Biraz çözülmemiş ve bir fonksiyona bölünmüş (giriş bir vektör olmalıdır, bu da yukarıdan (vec (tekrar tekrar (okuma))) üretir):

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

(Vay be, bu zorluğun 3 yaşın üzerinde olduğunu fark ettim. Ah, yine de bunu yaparken eğlendim!)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.