排列的组成–集团产品


12

给定两个不连续循环形式的排列,以不连续循环形式输出其乘积/组成。

Q·P =(1 5)(2 4)·(1 2 4 3)=(1 4 3 5)。

要查找组成,请将不相交的循环转换为两行符号的排列。循环的不连续部分中的每个数字都映射到同一部分中跟在其后的数字。它环绕。所以1 -> 55 -> 12 -> 44 -> 2。如果找不到数字3 -> 3,则会将其映射到自身。第一个不相交的周期也可以写成(1 5)(2 4)(3)。这些映射将转换为两行,如下所示(请注意,PQ的顺序相反):

哇,这张图片很大!

通过重新排列第二个(最左)排列的列,使其第一行与第一个(最右)排列的第二行相同,可以得到两个排列的乘积。然后可以将乘积写为修改后的第二排列的第二行上的第一排列的第一行。

在此处输入图片说明

维基百科文章


规则:

  • 输入将以列表形式或类似格式给出
  • 您可能不会采取类似(1 5)(2 4)as之类的[5, 4, 3, 2, 1]已经两行的形式(将索引映射为值)
  • 并非每个组中都必须有所有数字,所以您可能会有(1 5)·(1 2),导致(2 5 1)
  • 您的输出应该可以用作输入。
  • 您不需要使用空循环来支持输入(1 5)·()。取而代之的是(1 5)·(1)或等价的。
  • 由于循环回绕,因此顺序不重要,只要结果正确即可。
  • 您可以从零或一开始。没关系,因为结果相同。
  • 数字可以大于9
  • 您可能在输出中多次包含相同的数字。所以[[1],[1]]是不允许的。
  • 注意,该操作不是可交换的!我将Q放在P之前,因为这是Wikipedia所做的。您可以选择任何顺序,但要指定不同的顺序。
  • 最短的代码胜出
  • 允许内置,但是如果您使用内置的,请在不使用的情况下显示解决方案。

例子:

并未显示所有等效的输出可能性

Input
Output

[[1, 5], [2, 4]], [[1, 2, 4, 3]]
[[1, 4, 3, 5]] (or [[4, 3, 5, 1]] or ...)

[[1, 5]], [[1, 2]]
[[2, 5, 1]]

[[10, 2, 3]], [[2]]
[[3, 10, 2]]

[[1]], [[3]]
[[]] (or [[1]] or something equivalent)

[[10,2,3,15],[1,7],[5,6],[14,4,13,11,12]], [[5,6,7,9,14],[2,8,3,10],[1,11]]
[[12, 14, 6, 1], [8, 15, 10, 3, 2], [13, 11, 7, 9, 4]]

(arguments in reverse order from above gives a different answer)
[[5,6,7,9,14],[2,8,3,10],[1,11]], [[10,2,3,15],[1,7],[5,6],[14,4,13,11,12]]
[[9, 14, 4, 13, 1], [10, 8, 3, 15, 2], [7, 11, 12, 5]]

对我来说,这些是排列,而不是排列组。排列组是在此合成操作下封闭的一堆单个排列的集合。
格雷格·马丁

@GregMartin固定术语
mbomb007 '04

Answers:


2

J,7个字节

C.@C.@,

在线尝试!


您的输出应该可以用作输入。
mbomb007 '17

@ mbomb007输出可用作输入。每个循环列表必须是0索引的盒装数组。
英里

还是这是J的默认打印行为?我只想确保函数可以链接。
mbomb007

@ mbomb007是的,这只是它的视觉表示。它必须是0索引的,但我将其列为1索引,并在将它们存储到要传递给函数的变量之前将它们转换为0索引。然后,在将其输出之前,我将其从0索引转换回1索引。
英里

3

Mathematica,15个字节

##⊙Cycles@{}&

是弗吉尼亚,有一个内置的Mathematica ....在不相交的周期表示法已经支持的置换数据类型:这个纯函数作为输入的任何数量的参数的形式Cycles[{{1, 5}, {2, 4}}],并输出产品置换,再在Cycles[]形式。它使用与OP相反的排序约定,例如,

##⊙Cycles@{}&[Cycles[{{1, 2, 4, 3}}], Cycles[{{1, 5}, {2, 4}}]]

返回Cycles[{{1, 4, 3, 5}}]我上面使用的符号实际上应该是3字节的专用Unicode符号U + F3DE,可以在Mathematica中使用。请注意,Mathematica为此操作提供了一个命名内置函数PermutationProduct,但这要长三个字节。


3

哈斯克尔157个 148字节

编辑:

  • -9个字节:确实可以打更多的球。删除了周围多余的括号p++q。交换参数的顺序gd以开始摆脱iteratep x,之后takeWhile不再与fst+ 捆绑在一起span。发了中iterate缀。

在我迟到的时候做这个……可能还会打高尔夫球。

它更简单,而且似乎是允许的,因此输出包括单元素循环。

q#p=g(p++q>>=id)$f q.f p
f p a=last$a:[y|c<-p,(x,y)<-zip(0:c)(c++c),x==a]
g(x:l)p|c<-x:fst(span(/=x)$p`iterate`p x)=c:g[x|x<-l,x`notElem`c]p
g[]p=[]

在线尝试!

怎么运行的:

  • #是主要功能。q#p接受两个数字列表,然后返回一个类似的列表。测试似乎在P之前有Q,所以我使用了相同的顺序。
  • f p将置换p从不相交的循环形式转换为函数,f q然后f p可以使用通常的组合运算符进行组合.
    • 列表理解遍历循环c,寻找a并找到其后继者。如果理解没有发现,a则仅返回。
    • zip(0:c)(c++c)c及其及其后继元素的成对列表。由于问题使我们“从一开始”,因此我们可以将其0用作虚拟值。与在第二个zip参数之前使用相比,tail在第一个参数之前添加该参数便宜。
  • g l p接受l元素列表和排列函数p,并返回接触元素的循环列表。
    • c是包含x列表第一个元素的循环,其他元素的c查找是通过从迭代p xx再次找到而找到的。递归查找剩余循环时,c首先使用列表推导删除所有的元素。

感谢您注意顺序在计算结果时很重要。我忘记添加示例或对此发表评论。这已得到纠正。
mbomb007 '04

1

Python,220个字节

a,b=eval(input())
p,o=a+b,[]
for i in range(1,1+max(map(max,p))):
 if not any(i in t for t in o):
  u,m=(i,),i
  while 1:
   for t in p[::-1]:
    if m in t:m=t[(t.index(m)+1)%len(t)]
   if m==i:o+=[u];break
   u+=(m,)
o

2
欢迎来到该网站。我看到很多方法可以缩短此时间。考虑查看python提示页面
Ad Hoc Garf Hunter

0

Python 3.8,187字节

q,p=eval(input())
g=lambda p,i:[*(c[c.index(i)-1]for c in p if i in c),i][0]
h=lambda*c:(x:=g(p,g(q,c[0])))in c and(*c[(m:=c.index(min(c))):],*c[:m])or h(x,*c)
exit({*map(h,sum(p|q,()))})

在线尝试!检查所有测试用例!

输入qp在该顺序中,每个是一组元组的,从STDIN
输出:乘以Q·P一组元组的乘积排列STDERR

说明

该函数g查找哪个数字映射到i置换中的数字p(aka g是的反置换p)。

g=lambda p,i:        
[                   # creates a list
  *(                # containing the following
    c[c.index(i)-1] #   the number before i in cycle c
    for c in p      #   for all cycles in permutation
    if i in c       #   if i is in that cycle
  )                 #
  ,i                # adds i to the end of that list
                    #   (in case i is not in any cycle)
][0]                # returns the first element of the list

该函数h接受一个数字,并返回Q·P包含该数字的循环。返回的循环将是一个元组,其格式设置为使得最小元素位于索引0。

h=lambda*c:                   # input: an incomplete cycle c, as a list
(x:=g(p,g(q,c[0])))           # finds the number x before the first number in c
in c                          # if x is also in c (aka the cycle is complete)
and                           # then returns the following:
(                             #   c as a tuple with min element at index 0
  *c[(m:=c.index(min(c))):],  #   (c, from the min element to the end)
  *c[:m]                      #   (c, from start to the min element)
)
or                            # else (cycle is incomplete) returns the following
h(x,*c)                       #   recursive result when after prepending x to c

通过应用h所有数字,我们可以得到中的所有周期Q·P。为了防止结果中出现重复的循环,我们只需将所有循环都放在一个集合中即可。之所以可行,h是因为返回的相似循环将被格式化为相同的元组(最小的元素位于索引0)。
我们只需要考虑出现在P或中的数字Q,因为所有其他数字都将映射到它们自己。

exit(              # returns through STDERR
  {                # create a set from the followings
    *map(h,        #   map function h to
      sum(p|q,())  #   all numbers in P or Q
    )
  }
)
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.