順列をサイクルに分解する


15

順列はサイクルのセットに分解できるというよく知られた定理があります。あなたの仕事は、できる限り短いプログラムを書くことです。

入力:

2行。最初は数値を含みN、2番目はN範囲内の異なる整数を含みます[0,N-1]スペースで区切られれます。これらの整数は、N要素の順列を表します。

出力:

順列の各サイクルに1行。各行は、スペースで区切られた整数のサイクル順のリストである必要があります。

サイクルは任意の順序で出力でき、各サイクルは任意の位置から出力できます。

例1:

8
2 3 4 5 6 7 0 1

この入力は、順列0-> 2、1-> 3、2-> 4、3-> 5、4-> 6、5-> 7、6-> 0、7-> 1をエンコードします。これは、次のようなサイクルに分解されます。

0 2 4 6
1 3 5 7

同様に有効な出力は

5 7 1 3
2 4 6 0

例2:

8
0 1 3 4 5 6 7 2

有効な出力:

0
1
4 5 6 7 2 3

@Keith Nの最大値は?
fR0DDY

3
Jに3文字:>C.
Eelvex

N <1000としましょう。
キースランドール

順列は、通常は1からカウントアップされている、いない0
ベリサリウス博士は

6
数学者は1から数え、コンピューター科学者は0から数えます:)
キースランドール

回答:


4

C 145 134文字

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


暗黙的に宣言された変数関数を呼び出すことは合法ですか?最初に省略することは合法intですか?
6502

コードが機能する限り、何でもできます。警告を出すこともありますが、エラーを出さない限り、問題ありません。
fR0DDY

まさにポイントは「作品」の意味です。とにかく、このルールを使用する回答(139文字)を追加しました(つまり、「動作する」とは、「生成されたマシンコードが動作する自己宣言Cコンパイラが少なくとも1つある」という意味です)
6502

+1:gets(&i)役に立たない最初の行を削除するというアイデアが好きですが、10個を超える要素が渡された場合、これは明らかに16ビットシステムでは機能しません。しかし、ルールが「少なくとも1つのケースで-少なくとも私には有効な応答を提供するように見える実行可能ファイルを作成するCコンパイラであると主張するプログラムを少なくとも見つける」場合、これは改善です:- )
6502

2

Python 131文字

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

最後の改行は必要ありません


1

Haskell、131文字

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
  • 編集:(135-> 131)に>=なり>tailパターンマッチングとの事前適用を通じて2つの呼び出しが削除されましたa!!

1

C(並べ替え)、139文字

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

最後の改行は含まれていません。

私は「ソート」と言った

  1. 可変引数関数の宣言を省略することは違法です(ANSI C89:3.3.2.2)
  2. int 変数宣言では省略できません(省略できると言われている場所は見つかりませんでしたし、暗黙的な型宣言は関数についてのみ説明されています。標準の文法仕様は、有効なC宣言よりも多くを受け入れるため、基本的には役に立ちません double double void volatile x;
  3. 空でないソースファイルの最後の改行は必須です(ANSI C89:A.6.2)

しかし、gcc -ocycles cycles.cとにかくコンパイルされた上記のコードはどうやら動作します。


これは有効なCプログラムですが、これはC99ではありません。
キクソティック

@Debanjan:いいえ、それはANSI Cではありません(89さえも)。例えば、標準関数は、引数の可変数を使用している場合、それはつまり、あなたが呼び出すことはできません(関数呼び出しサイトで暗黙的に宣言することができないこと(3.3.2.2)と言うscanfことなく、#include <stdio.h>パラメータが正しいとの変換を必要としない場合でも、 ):<<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〜32)

私はI / O形式については明確ではありませんがC.、次の出力が受け入れられれば、そうなると思います。

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

(Jターミナルではより見栄えがよくなります。)

I / O形式の私の最高の理解に準拠した名前付き関数である必要がある場合、それは32文字であり、そのうち30文字は出力形式変換用です...

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

動作中:

   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

説明:

Jは右から左へ(実際に)実行されます。@関数を結合するための「関数」(技術的には関数ではありませんが、十分に近い関数です)。

  • i.&LF-の最初のインデックス、LFASCII文字番号10を含む定義済み変数、改行を見つけます。
  • >:-最初のを見つけて、そのLFインデックスを1つ増やします。実際には改行が必要ではなく、それに続く配列が必要です。
  • }.~ -入力したい部分を選択します。
  • ".-入力形式は有効なJ(* \õ/ *)であるため、eval動詞(実際には呼び出されないことがわかっていevalます)を使用して配列に変換できます
  • C.-純粋な魔法。私はこれが何をするのか本当に分かりませんが、うまくいくようです!
  • ":L:0-表現。の出力C.を文字列のボックス化されたシーケンスに変換します
  • >-箱を開けます。実際の出力は、実際には文字列配列です(例の最初の数字から数字の後ろにスペースがあります)。

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

やや無制限で、関数に分割されます(入力はベクトルでなければなりません。これは(vec(repeatedly(read)read))が生成するものです):

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

(すごい、このチャレンジは3歳以上だということに気付いた。まあ、とにかく楽しんでいた!)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.