[英]How do I generate a table of permutations from a list with cyclical redundancy eliminated?
[英]How to list all permutations without repetition?
当前帖子是此链接帖子的后续问题:
将一副 7 张假设的交易卡洗牌,并在 Google 表格中列出他们可以进来的订单
惊喜。 我的问题孩子实际上是为真女神转生 3 排列 - 为一个视频游戏。 我认为把它放在交易卡的术语中对外行来说更有意义。 对不起。
好的。 我弄乱了一个包含 7 个独特怪物的数据集(在视频游戏早期很容易获得的初始集)。 它们不能在我的派对中复制,但可以组合成不同的。 一开始,视频游戏中只有 8 个可用于怪物的插槽。
该项目的重点是构建“融合链”的所有排列,试图将这些怪物排列成独特的顺序,以便稍后在该链中组合。
它从 A+B 开始,然后清理该列表以从初始配对中消除任何 B+A 场景(融合 A+B 或 B+A 会产生相同的结果)。 然后,融合只是将 C、D、E、F、G 和 H(当前已损坏)添加到先前融合的结果,直到不再存在可能的融合(我的队伍中只有一个怪物)。
问题是这样的:排列单元格中的查询或其他函数在尝试列出一次排序 8 个怪物的排列时抛出错误“结果数组太大”——甚至在融合发生之前。 我已将问题隔离到这个公式(有点长):
=iferror(if(counta($A$2:$A$13)>=2,arrayformula(query(query(split(flatten(flatten(flatten(flatten(flatten(flatten(
filter($F$2:$F,$F$2:$F<>"")&if(counta($A$2:$A$13)>=3,","&transpose(
filter($A$2:$A$13,$A$2:$A$13<>"")),""))&if(counta($A$2:$A$13)>=4,","&transpose(
filter($A$2:$A$13,$A$2:$A$13<>"")),""))&if(counta($A$2:$A$13)>=5,","&transpose(
filter($A$2:$A$13,$A$2:$A$13<>"")),""))&if(counta($A$2:$A$13)>=6,","&transpose(
filter($A$2:$A$13,$A$2:$A$13<>"")),""))&if(counta($A$2:$A$13)>=7,","&transpose(
filter($A$2:$A$13,$A$2:$A$13<>"")),""))&if(counta($A$2:$A$13)>=8,","&transpose(
filter($A$2:$A$13,$A$2:$A$13<>"")),"")),","),
"where Col1 <> Col2"&
if(counta($A$2:$A$13)>=3," and Col1 <> Col3 and Col2 <> Col3"&
if(counta($A$2:$A$13)>=4," and Col1 <> Col4 and Col2 <> Col4 and Col3 <> Col4"&
if(counta($A$2:$A$13)>=5," and Col1 <> Col5 and Col2 <> Col5 and Col3 <> Col5 and Col4 <> Col5"&
if(counta($A$2:$A$13)>=6," and Col1 <> Col6 and Col2 <> Col6 and Col3 <> Col6 and Col4 <> Col6 and Col5 <> Col6"&
if(counta($A$2:$A$13)>=7," and Col1 <> Col7 and Col2 <> Col7 and Col3 <> Col7 and Col4 <> Col7 and Col5 <> Col7 and Col6 <> Col7"&
if(counta($A$2:$A$13)>=8," and Col1 <> Col8 and Col2 <> Col8 and Col3 <> Col8 and Col4 <> Col8 and Col5 <> Col8 and Col6 <> Col8 and Col7 <> Col8",),),),),),),0),"where Col1 <>''",0)),"not enough data"),)
该公式查看的第一个范围是以前稳定的形式(F 列):
唯一的初始化对 |
---|
小精灵,式神 |
儿玉,小精灵 |
花婆,小精灵 |
Datsue-Ba,Pixie |
天使,小精灵 |
Fomorian,小精灵 |
儿玉式神 |
花坡,式神 |
达江场式神 |
天使,式神 |
佛摩人,式神 |
花宝,儿玉 |
达江场,儿玉 |
天使,儿玉 |
佛摩里安,儿玉 |
达采霸,华坡 |
天使,华宝 |
Fomorian,华坡 |
天使,达江霸 |
达江坝,佛摩里安 |
天使,佛摩人 |
它是由我制作的一种“更清洁”的公式提供的,但这不是问题。
我正在测试的整体输入是这样的(在 A 列中),也是初始对的更清晰公式的输入:
可用的 |
---|
小精灵 |
式神 |
儿玉 |
华坡 |
达江坝 |
天使 |
福莫里安 |
高精灵 |
而预期的 output... 真的很大。 这是获得想法的第一行示例(托管在原始工作表的 H2 中):
一个 | 乙 | C | D | 乙 | F | G | H |
---|---|---|---|---|---|---|---|
小精灵 | 式神 | 儿玉 | 华坡 | 达江坝 | 天使 | 福莫里安 | 高精灵 |
小精灵 | 式神 | 儿玉 | 华坡 | 达江坝 | 福莫里安 | 天使 | 高精灵 |
小精灵 | 式神 | 儿玉 | 华坡 | 天使 | 达江坝 | 福莫里安 | 高精灵 |
小精灵 | 式神 | 儿玉 | 华坡 | 天使 | 福莫里安 | 达江坝 | 高精灵 |
小精灵 | 式神 | 儿玉 | 华坡 | 福莫里安 | 达江坝 | 天使 | 高精灵 |
小精灵 | 式神 | 儿玉 | 华坡 | 福莫里安 | 天使 | 达江坝 | 高精灵 |
小精灵 | 式神 | 儿玉 | 达江坝 | 华坡 | 天使 | 福莫里安 | 高精灵 |
等等... |
我目前不知道如何解决这个问题。 我想在我的表格中放置至少 8 个起始怪物以供分析,如果不是完整的 12 个以供游戏结束。
可能有一种比我现有的方式更好、更紧凑的方式来生成这些排列。 我可能想启动 Excel 在我的超级系统上尝试这个,然后看看它在哪里断线。 然而,我想要更有效的公式来解决我在 Google 表格中的“数组太大”问题。 这是我工作得最好的地方,也是我有许多其他项目的地方。
PS:感谢 Erik 对完整工作表的帮助,并教我一些使用 LAMBDA 和命名函数的新技术。 它有助于最终解决我的问题。 Stack 的政策限制我共享完整的电子表格是有充分理由的(担心不良行为者等等)。 因此,我对这篇文章进行了编辑,以使其更好地包含在内。 再次,为混乱感到抱歉。
Stack 是一项免费的、由志愿者运营的服务,旨在提供“小帮助”(例如,一些共享知识、对现有公式或几乎正确的代码行的调整等)。 它的设计初衷不是让人们可以免费获得定制的、复杂的、耗时的解决方案。
也就是说,由于最近推出的新功能,我选择采用它,主要是为了展示其中一些新功能的一些好处。
我提供这个解决方案没有解释,因为解释比写公式要花更长的时间。
我已将以下公式放在链接电子表格中新工作表(“Erik 帮助”)的单元格 A1 中:
=ArrayFormula(IFERROR(TO_TEXT(VLOOKUP(SPLIT(REGEXREPLACE({LAMBDA(x,FILTER(x,NOT(REGEXMATCH(x&"","8|9|0")),x>=12,BYROW(1*(MID(x&LEFT("abc",5-LEN(x)),SEQUENCE(1,4),1)<MID(x&LEFT("abc",5-LEN(x)),SEQUENCE(1,4,2),1)),LAMBDA(row,SUM(row)))=4))(SEQUENCE(34567));REGEXREPLACE("1234567",SEQUENCE(7)&"","")*1;1234567}&"","(.)","$1~"),"~",1,1),{SEQUENCE(7),'chains-original':A2,A8},2,FALSE))))
注意新函数 LAMBDA 和 BYROW 的使用。
为了未来访问者的利益,如果链接的电子表格失效,这是公式中与电子表格无关的部分,将生成数字 1-7 的所有唯一组合,即 2 到 7 个数字的组合和在任何单个结果中不重复任何数字:
=ArrayFormula(SPLIT(REGEXREPLACE({LAMBDA(x,FILTER(x,NOT(REGEXMATCH(x&"","8|9|0")),x>=12,BYROW(1*(MID(x&LEFT("abc",5-LEN(x)),SEQUENCE(1,4),1)<MID(x&LEFT("abc",5-LEN(x)),SEQUENCE(1,4,2),1)),LAMBDA(row,SUM(row)))=4))(SEQUENCE(34567));REGEXREPLACE("1234567",SEQUENCE(7)&"","")*1;1234567}&"","(.)","$1~"),"~",1,1))
如果其他人对此公式的特定元素有具体问题,请在下面的评论中提出该问题,我将尽我所能在合理范围内回答。 但是,我建议首先使用公式(本段上方与电子表格无关的公式)并对其进行剖析以进行理解。 经验永远是最好的老师。
有不同的算法来实现这一点。 请参阅计算中的排列:
直接且最简单的方法是创建一个数字序列,其中BASE
等于可供选择的项目数。 例如,如果有 7 个项目可供选择,请创建如下序列:
BASE 7(=数组公式(BASE(SEQUENCE(25),7,7))) |
---|
0000001 |
0000002 |
0000003 |
0000004 |
0000005 |
0000006 |
0000010 |
0000011 |
0000012 |
0000013 |
0000014 |
0000015 |
0000016 |
0000020 |
0000021 |
0000022 |
0000023 |
0000024 |
0000025 |
0000026 |
0000030 |
0000031 |
0000032 |
0000033 |
0000034 |
…… |
注意每个 position 有 7 个变量(0 到 6),有 7 个位置。 一旦我们得到了PERMUTATIONA(7,7)
的所有数字,只需删除所有重复的数字就很简单了,其中每个 position 中的所有数字都是唯一的,即每个数字的COUNTUNIQUE
= 7(例如:0124536)。 这是一个实现:
=ARRAYFORMULA(LAMBDA(n,QUERY(BYROW(SPLIT(REGEXREPLACE(TO_TEXT(BASE(SEQUENCE(PERMUTATIONA(n,n)-1),n,n)),"\B","."),"."),LAMBDA(r, IF(COUNTUNIQUE(r)<>n,"👀",JOIN(,r)))),"where not Col1='👀' ",0))(5))
不幸的是,谷歌任意限制执行时间少于几秒钟。 因此,此公式无法获得超过n=5
的所有排列。
列表中的下一个是使用阶乘(Lehmer 的代码)来获取排列。 请参阅此处的排列。 请注意数字序列与排列之间的直接关系。
十进制 | 因数 | 排列 |
---|---|---|
0 | 0:0:0! | (0,1,2) |
1 | 0:1:0! | (0,2,1) |
2 | 1:0:0! | (1,0,2) |
3 | 1:1:0! | (1,2,0) |
4 | 2:0:0! | (2,0,1) |
5 | 2:1:0! | (2,1,0) |
表格来自https://wikipedia.org/wiki/Factorial_number_system在 CC-BY-SA 3.0 下获得许可
我实现了这个算法,并且在n=5
处再次达到了 Google 的限制。 (此处未显示代码)。
接下来,我们有Lexicographic ordering 。 算法如下:
以下算法在给定排列之后按字典顺序生成下一个排列。 它就地改变了给定的排列。
找到满足 a[k] < a[k + 1] 的最大索引 k。 如果不存在这样的索引,则排列是最后一个排列。 找到大于 k 的最大索引 l,使得 a[k] < a[l]。 将 a[k] 的值与 a[l] 的值交换。 反转从 a[k + 1] 到最后一个元素 a[n] 的序列。
例如,给定序列 [1, 2, 3, 4](按升序排列),并且给定索引是从零开始的,步骤如下:
索引 k = 2,因为 3 被放置在满足仍然小于 a[k + 1] 即 4 的最大索引条件的索引处。索引 l = 3,因为 4 是序列中唯一的值大于 3 以满足条件 a[k] < a[l]。 a[2] 和 a[3] 的值被交换以形成新的序列 [1, 2, 4, 3]。 从 k-index a[2] 到最后一个元素的顺序是相反的。 因为只有一个值位于该索引(3)之后,所以在这种情况下序列保持不变。 因此,初始 state 的词典后继被置换:[1,2,4,3]。
引自https://en.wikipedia.org/wiki/Permutation根据 CC-BY-SA 3.0 许可
感谢 Google 对递归和命名函数的最新支持,我实现了这一点,并且能够在单个公式中获得多达n=6
(720 项),但我仍然达到了 Google 的递归限制,即n=7
(5040 项) . 话虽如此,仍然可以在没有数组公式的情况下一一获得所有 5k 排列(甚至可能n=8
(40320 项),具体取决于您的设备可以处理的内容)。
1.小精灵 | 2.式神 | 3.儿玉 | 4.花婆 | 5.达江坝 | 6.天使 | 7.佛摩里安 |
---|---|---|---|---|---|---|
1.小精灵 | 2.式神 | 3.儿玉 | 4.花婆 | 5.达江坝 | 7.佛摩里安 | 6.天使 |
1.小精灵 | 2.式神 | 3.儿玉 | 4.花婆 | 6.天使 | 5.达江坝 | 7.佛摩里安 |
1.小精灵 | 2.式神 | 3.儿玉 | 4.花婆 | 6.天使 | 7.佛摩里安 | 5.达江坝 |
1.小精灵 | 2.式神 | 3.儿玉 | 4.花婆 | 7.佛摩里安 | 5.达江坝 | 6.天使 |
1.小精灵 | 2.式神 | 3.儿玉 | 4.花婆 | 7.佛摩里安 | 6.天使 | 5.达江坝 |
1.小精灵 | 2.式神 | 3.儿玉 | 5.达江坝 | 4.花婆 | 6.天使 | 7.佛摩里安 |
1.小精灵 | 2.式神 | 3.儿玉 | 5.达江坝 | 4.花婆 | 7.佛摩里安 | 6.天使 |
1.小精灵 | 2.式神 | 3.儿玉 | 5.达江坝 | 6.天使 | 4.花婆 | 7.佛摩里安 |
1.小精灵 | 2.式神 | 3.儿玉 | 5.达江坝 | 6.天使 | 7.佛摩里安 | 4.花婆 |
1.小精灵 | 2.式神 | 3.儿玉 | 5.达江坝 | 7.佛摩里安 | 4.花婆 | 6.天使 |
1.小精灵 | 2.式神 | 3.儿玉 | 5.达江坝 | 7.佛摩里安 | 6.天使 | 4.花婆 |
1.小精灵 | 2.式神 | 3.儿玉 | 6.天使 | 4.花婆 | 5.达江坝 | 7.佛摩里安 |
1.小精灵 | 2.式神 | 3.儿玉 | 6.天使 | 4.花婆 | 7.佛摩里安 | 5.达江坝 |
1.小精灵 | 2.式神 | 3.儿玉 | 6.天使 | 5.达江坝 | 4.花婆 | 7.佛摩里安 |
1.小精灵 | 2.式神 | 3.儿玉 | 6.天使 | 5.达江坝 | 7.佛摩里安 | 4.花婆 |
1.小精灵 | 2.式神 | 3.儿玉 | 6.天使 | 7.佛摩里安 | 4.花婆 | 5.达江坝 |
1.小精灵 | 2.式神 | 3.儿玉 | 6.天使 | 7.佛摩里安 | 5.达江坝 | 4.花婆 |
1.小精灵 | 2.式神 | 3.儿玉 | 7.佛摩里安 | 4.花婆 | 5.达江坝 | 6.天使 |
1.小精灵 | 2.式神 | 3.儿玉 | 7.佛摩里安 | 4.花婆 | 6.天使 | 5.达江坝 |
1.小精灵 | 2.式神 | 3.儿玉 | 7.佛摩里安 | 5.达江坝 | 4.花婆 | 6.天使 |
1.小精灵 | 2.式神 | 3.儿玉 | 7.佛摩里安 | 5.达江坝 | 6.天使 | 4.花婆 |
1.小精灵 | 2.式神 | 3.儿玉 | 7.佛摩里安 | 6.天使 | 4.花婆 | 5.达江坝 |
1.小精灵 | 2.式神 | 3.儿玉 | 7.佛摩里安 | 6.天使 | 5.达江坝 | 4.花婆 |
显示n=7
的前几个排列。 要使公式起作用,请务必注意列表中必须存在固有的升序。 我在1.Pixie
、 2.Shikigami
... 等中添加了前缀: 1.
、 2.
等,以强制执行升序。 可以在公式本身中进行排序,但未实现。
A1:G1
:
1.小精灵 | 2.式神 | 3.儿玉 | 4.花婆 | 5.达江坝 | 6.天使 | 7.佛摩里安 |
---|
A2
:
=GET_NEXT_LEX(A1:G1)
根据需要向下拖动填充或自动填充(40k 或 5k 行)。
创建这些函数
GET_NEXT_LEX(arr)
:=ARRAYFORMULA(
TRANSPOSE(
LAMBDA(arr,
LAMBDA(k,
LAMBDA(sarr,k,{SPLICE(sarr,k+1,2^999);REVERSE(SPLICE(sarr,1,k+1))})
(SWAP(arr,k,XMATCH(TRUE,INDEX(arr,k)<SPLICE(arr,1,k+1),,-1)+k),k)
)(XMATCH(TRUE,POP(arr)<SHIFT(arr),,-1))
)(TRANSPOSE(arr))
)
)
功能类似于javascript或python
SPLICE(arr,i,j)
=FILTER(arr,LAMBDA(seq,(seq<i)+(seq>=j))(SEQUENCE(ROWS(arr))))
REVERSE(arr)
=POP(REDUCE(,arr,LAMBDA(a,c,{c;a})))
SWAP(arr,i,j)
=SORT(arr,LAMBDA(keys,SWITCH(keys,i,j,j,i,keys))(SEQUENCE(ROWS(arr))),1)
POP(arr)
=ARRAY_CONSTRAIN(arr,ROWS(arr)-1,1)
SHIFT(arr)
=FILTER(arr,{0;SEQUENCE(ROWS(arr)-1)})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.