以循环符号打印对称组Sn的“偶数”排列


9

任务

定义

考虑点{1,2,3,4,5}及其所有排列。我们可以通过一个简单的技巧找到这5个点的可能排列总数:成像用这些点填充5个插槽,第一个插槽将具有5个可能的数字,第二个插槽将具有5个可能的数字(因为已经使用一个填充了第一个插槽)第三三个,依此类推。因此,置换的总数为5 * 4 * 3 * 2 * 1;这将是5!排列或120个排列。我们可以将其视为对称组S5,然后对称组Sn将具有n! or (n*n-1*n-2...*1)置换。

“偶数”排列是偶数个偶数长度周期的排列。以循环表示法(例如(1 2 3)(4 5)置换)书写时最容易理解1->2->3->14->5->4并且具有1个3个长度的周期(1 2 3)和1个2个长度的周期(4 5)。当将排列归类为奇数或偶数时,我们忽略奇数长度的循环,并说此排列[ (1 2 3)(4 5)]为奇数,因为它具有偶数长度循环的奇数{1}。甚至示例:

  1. (1)(2 3)(4 5)=两个2长度循环| 偶数
  2. (1 2 3 4 5)=没有均匀的长度循环| 偶数 *请注意,如果不存在偶数长度循环,则排列是偶数。

奇怪的例子:

  1. (1 2)(3 4 5)= 1个2个长度周期| 奇数|
  2. (1)(2 3 4 5)= 1个4个长度的周期| 奇数|

由于在任何对称组中恰好一半的排列是偶数,因此我们可以将偶数组称为交替组N,因此S5 = 120 A5 = 60排列。

符号

至少为此,应使用循环符号来编写排列,其中每个循环使用不同的括号,并且每个循环以升序排列。例如(1 2 3 4 5)没有(3 4 5 1 2)。对于具有单个数字的循环,例如:(1)(2 3 4)(5)可以排除单个/固定点的含义(1)(2 3 4)(5) = (2 3 4)。但是标识(所有点都固定的点(1)(2)(3)(4)(5))应该写成()只是用来表示它。

挑战

我希望您以尽可能少的代码将任何正整数作为输入{1,2,3,4 ...}并显示交替组An的所有排列,其中n是输入/偶数Sn的排列 例如:

Input = 3
()
(1 2 3)
(1 3 2)

Input = 4
()
(1 2)(3 4)
(1 3)(2 4)
(1 4)(2 3)
(1 2 3)
(1 3 2)
(1 2 4)
(1 4 2)
(1 3 4)
(1 4 3)
(2 3 4)
(2 4 3)

就像在示例中一样,我希望消除一个长度的所有周期,并且对于标识:什么也不输出,(){不仅是括号,而且无论您使用什么来显示不同的排列},还是id可以接受的。

额外阅读

您可以在这里找到更多信息:

祝好运

因为这是代码高尔夫球员,所以谁可以在最短的字节中打印出交替组An的排列就赢了。


2
欢迎来到编程难题和Code Golf!通常,我们允许输出是灵活的,这样在以正确格式输出时遇到问题的语言就不会有不公平的劣势。是否允许例如输出[[1, 2], [3, 4]]而不是(1 2)(3 4)
阿德南

@Adnan是的,我应该澄清一下。只要分别显示不同的周期,您如何表示它就不会有问题。
哈里

““偶数”置换是偶数置换为偶数的置换。” 这看起来像一个循环定义。也许先引入循环符号,然后将该语句重写为“ ...偶数个偶数循环”?
Martin Ender

另外,如何将循环(2 3 1 4)按升序排列?您是说我们应该将最小的元素放在前面吗?
Martin Ender

@MartinEnder是最小的元素应该只要它不惹的顺序先走,这样(2 3 1 4)2->3->1->4->2可以将它写入(1 4 2 3)其最小元素第一
哈利

Answers:


5

Pyth,26个字节

t#Mf%+QlT2mcdf<>dTS<dTd.pS

          m            .pSQ   Map over permutations d of [1, …, Q]:
             f        d         Find all indices T in [1, …, Q] such that
               >dT                the last Q-T elements of d
              <   S<dT            is less than the sorted first T elements of d
           cd                   Chop d at those indices
   f                          Filter on results T such that
      Q                         the input number Q
     + lT                       plus the length of T
    %    2                      modulo 2
                                is truthy (1)
t#M                           In each result, remove 0- and 1-cycles.

在线尝试

此解决方案基于单行表示法的排列与周期表示法的排列之间的整齐双射。当然,存在明显的双射,其中两个符号表示相同的排列:

[8,4,6,3,10,1,5,9,2,7] =(1 8 9 2 4 3 6)(5 10 7)

但这会花费太多代码。取而代之的是,简单地将单行符号切成小块,然后将所有小于其所有前任数字的数字称为这些块循环,并根据它们建立新的排列。

[8,4,6,3,10,1,5,9,2,7]↦(8)(4 6)(3 10)(1 5 9 2 7)

要逆转这种双射,我们可以采用周期形式的任何置换,旋转每个周期以使其最小的数字为第一,对周期进行排序以使其最小的数字以降序显示,并消除所有括号。


OP要求标识置换不带一个周期。我确实认为,如果不是这样,那会更好。
英里

1
哈利似乎对我的果冻答案还好,甚至连打印了1个周期id。也许他可以鸣叫?
林恩

我也不太确定其措辞方式,也没有注意到您的(Lynn's)解决方案也是如此。
英里

我的理解是,您无法使用空字符串表示身份置换,因此我对答案进行了修改,以保留所有1个周期(也方便地节省了6个字节)。
尼尔

1
我对问题进行了更清晰的编辑,我希望像回答第二部分所做的那样消除“一个周期”。顺便说一句。
哈利

6

Mathematica,84 49 31字节

GroupElements@*AlternatingGroup

两个功能的组成。以{Cycles[{}], Cycles[{{a, b}}], Cycles[{{c, d}, {e, f}}], ...}表示形式的输出(), (a b), (c d)(e f), ...


3

J,53字节

[:(<@((>:@|.~]i.<./)&.>@#~1<#@>)@C.@#~1=C.!.2)!A.&i.]

由于J将零填充的锯齿状数组零填充,所以每个置换中的循环都表示为方框数组。

如果输出是宽松的,则使用41个字节

[:((1+]|.~]i.<./)&.>@C.@#~1=C.!.2)!A.&i.]

其中每个排列可能包含一个周期和零个周期。

用法

   f =: [:(<@((>:@|.~]i.<./)&.>@#~1<#@>)@C.@#~1=C.!.2)!A.&i.]
   f 3
┌┬───────┬───────┐
││┌─────┐│┌─────┐│
│││1 2 3│││1 3 2││
││└─────┘│└─────┘│
└┴───────┴───────┘
   f 4
┌┬───────┬───────┬─────────┬───────┬───────┬───────┬───────┬─────────┬───────┬───────┬─────────┐
││┌─────┐│┌─────┐│┌───┬───┐│┌─────┐│┌─────┐│┌─────┐│┌─────┐│┌───┬───┐│┌─────┐│┌─────┐│┌───┬───┐│
│││2 3 4│││2 4 3│││1 2│3 4│││1 2 3│││1 2 4│││1 3 2│││1 3 4│││1 3│2 4│││1 4 2│││1 4 3│││2 3│1 4││
││└─────┘│└─────┘│└───┴───┘│└─────┘│└─────┘│└─────┘│└─────┘│└───┴───┘│└─────┘│└─────┘│└───┴───┘│
└┴───────┴───────┴─────────┴───────┴───────┴───────┴───────┴─────────┴───────┴───────┴─────────┘

对于其他实现,

   f =: [:((1+]|.~]i.<./)&.>@C.@#~1=C.!.2)!A.&i.]
   f 3
┌─────┬─┬─┐
│1    │2│3│
├─────┼─┼─┤
│1 2 3│ │ │
├─────┼─┼─┤
│1 3 2│ │ │
└─────┴─┴─┘

这实际上很漂亮...做得很好。
哈里

2

果冻34 28 字节

L€’SḂ
ṙLR$Ṃµ€Ṣ
Œ!ŒṖ€;/Ç€ÑÐḟQ

在这里尝试

说明

Jelly程序中的每一行都定义一个函数。底部的是“ main”。

  • 第一行定义了一个测试循环乘积是否为奇数的函数。

    L€      Length of each
      ’     Add 1 to each length 
       S    Take the sum
        Ḃ   Modulo 2
    
  • 第二行将的置换分区归一[1…n]化为循环乘积,如下所示:

         µ€    For each list X in the partition:
    ṙLR$          Rotate X by each element in [1…length(X)].
        Ṃ         Get the lexicographically smallest element.
                  Thus, find the rotation so that the smallest element is in front.
           Ṣ   Sort the cycles in the partition.
    

    这将(4 3)(2 5 1)变成(1 2 5)(3 4)

这是主程序。它n从命令行获取一个参数,并且:

Œ!              Compute all permutations of [1…n].
  ŒṖ€           Compute all partitions of each permutation.
     ;/         Put them in one big list.
       ǀ       Normalize each of them into a cycle product.
         ÑÐḟ    Reject elements satisfying the top function,
                i.e. keep only even cycle products.
            Q   Remove duplicates.

我尝试使用5作为输入来运行它,却没有任何输出。该脚本仅适用于A3和A4组吗?它是否可以提供任何组?我之前从未见过Jelly,因此任何解释都将有所帮助。
哈里

不,我在挑战赛中只加了3和4,到目前为止,您赢了,但是我真的只是想了解更多。
哈里

Jelly实际上有一个内置的分区,我忘了!值得庆幸的是,一位朋友提醒了我。因此,现在它更加高效(处理n = 5,是的!)并且更短。
林恩

OP编辑了该问题,以阐明必须删除1个循环。
Anders Kaseorg '16

2

的JavaScript(火狐30-57),220个 218 212 211字节

f=(a,p)=>a[2]?[for(i of a)for(j of f(a.filter(m=>m!=i),p,p^=1))[i,...j]]:[[a[p],a[p^1]]]

不幸的是88个字节仅足以产生交替分组作为排列的列表a,所以它然后费用我的附加132个 130 124个 123字节到输出转换为所需的格式:

n=>f([...Array(n).keys()],0).map(a=>a.map((e,i)=>{if(e>i){for(s+='('+-~i;e>i;[a[e],e]=[,a[e]])s+=','+-~e;s+=')'}},s='')&&s)

我已经成功地修剪我ES6版降至222个 216 215字节:

n=>(g=(a,p,t=[])=>a[2]?a.map(e=>g(a.filter(m=>m!=e),p,[...t,e],p^=1)):[...t,a[p],a[p^1]].map((e,i,a)=>{if(e>i){for(s+='('+-~i;e>i;[a[e],e]=[,a[e]])s+=','+-~e;s+=')'}},s='')&&r.push(s))([...Array(n).keys(r=[])],0)&&r

我不介意这种格式是否不是完美的循环表示法,只要:每个排列及其周期都显示为单独(例如[1 2 3] [4 5]和<< 123> <45 >>都可以接受) ),并省略了一个长度的循环。也许这可以缩短您的答案
哈里

@Harry我永远不会显示(1,2,3)(4,5)-这是一个奇怪的排列!当前,我将显示例如(1,2,3)(4)(5)-不仅删除长度为1的循环会花掉我6个字节,然后以身份循环为空结果会导致我花4个字节来修复。
尼尔

如果您的意思是什么都没有印出来,那么我会接受我所说的as for the identity outputs of nothing ... are accepatble。而且,如果输出“原始数据”,它会以(1,2,3)(4)(5)的形式还是其他形式显示?
哈利

@Harry现在不包括长度为1的循环,包括用于身份的空白条目,并且仍设法保存一个字节!
尼尔

@Harry Raw数据将[1, 2, 0, 3, 4]用于该特定示例,因此离您想要的位置不远。
尼尔

1

GAP,32字节

感谢@ChristianSievers将数量减少了一半。

f:=n->List(AlternatingGroup(n));

提示符下的用法:

gap> f(4);
[ (), (1,3,2), (1,2,3), (1,4,3), (2,4,3), (1,3)(2,4), (1,2,4), (1,4)(2,3), (2,3,4), (1,3,4), (1,2)(3,4), (1,4,2) ]

格式非常好,我认为GAP是回答此问题的很好选择。
哈里

您的答案没有显示一个排列的结束位置,下一个排列的开始位置。假设该函数不需要将这些值作为副作用打印,而可以将这些值作为解释器要打印的列表返回,我会这样做f:=n->List(AlternatingGroup(n));
Christian Sievers,2016年
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.