将置换分解为周期


15

有一个众所周知的定理,任何置换都可以分解为一组循环。您的工作是编写最短的程序。

输入:

两行。第一个包含数字N,第二个包含以空格分隔N的范围内的不同整数[0,N-1]。这些整数表示N元素的排列。

输出:

排列中每个循环一行。每行应是按循环顺序用空格分隔的整数列表。

循环可以以任何顺序输出,并且每个循环可以从任意位置开始输出。

范例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 2011年

3
J中的3个字符:>C.
Eelvex

假设N <1000。
基思·兰德尔

置换通常是从1向上计数,而不是0。
博士贝利萨留

6
数学家从1开始计数,计算机科学家从0开始计数:)
Keith Randall

Answers:


4

C 145134个字符

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 2011年

重点是“作品”的含义。无论如何,我已经添加了使用此规则的答案(139个字符)(即“工作”的意思是“至少有一个自声明的C编译器,显然其中生成的机器代码可以工作”)
6502

+1:我喜欢gets(&i)摆脱无用的第一行的想法,但是,如果传递了10个以上的元素,这显然在16位系统上将不起作用。但是再一次,如果规则是“至少找到一个声称是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通过模式匹配和的预应用消除了两个调用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("");}}

最后的换行符不包括在内。

我说“排序”是因为AFAIK

  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。
Quixotic

@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-找到的第一个索引LF,即包含ASCII字符编号10的预定义变量,换行符。
  • >:-找到第一个LF,然后将其索引增加一个。我们实际上并不需要换行,而是需要跟随它的数组。
  • }.~ -选择所需的输入部分。
  • ".-由于输入格式为有效的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年了。哦,好吧,还是很开心!)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.