[英]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.