LAMBDA 支持的简单 LET
对于 2022 年的问题,我使用了以下 LET:
=LET( matrix, A2:E6,
cC, COLUMNS( matrix ), cSeq, SEQUENCE( 1, cC ),
rC, ROWS( matrix ), rSeq, SEQUENCE( rC ),
eC, rC ^ cC, eSeq, SEQUENCE( eC,,0 ),
unblank, IF( ISBLANK(matrix), "°|°", matrix ),
m, UNIQUE( INDEX( unblank, MOD( INT( INT( SEQUENCE( eC, cC, 0 )/cC )/rC^SEQUENCE( 1, cC, cC-1, -1 ) ), rC ) + 1, cSeq ) ),
FILTER( m, BYROW( IFERROR( FIND( "°|°", m ), 0 ), LAMBDA(x, SUM( x ) ) ) = 0 ) )
其中用于在 A2:E6 中生成排列的矩阵:

此公式插入“°|°”代替空白,以避免将空白重铸为 0。它通过应用 UNIQUE 来消除重复项。
这是超级低效的,因为它会生成所有可能的排列,包括重复,然后将它们过滤掉。对于小规模矩阵,这没什么大不了的,但想象一下,一个 100 行乘 3 列的矩阵会生成 1'000'000 行,然后将它们过滤到一个小的子集。
但是,有一个小好处,请注意黄色单元格中的f,它被困在列的中间并且与它的同行不相邻。这个公式像冠军一样处理。它只是将其集成到有效排列的输出中。这在下面的有效公式中很重要。
由 LAMBDA 支持的高效通用 LET
至于一般的 LAMBDA 公式,我使用了:
SYMBOLPERMUTATIONS =
LAMBDA( matrix,
LET(
cC, COLUMNS( matrix ),
cSeq, SEQUENCE( 1, cC ),
symbolCounts, BYCOL( matrix, LAMBDA(x, SUM( --NOT( ISBLANK( x ) ) ) ) ),
rSeq, SEQUENCE( MAX( symbolCounts )-1 ),
permFactors, INDEX( SCAN( 1, INDEX( symbolCounts, , cC-cSeq+1), LAMBDA(a,b, a*b ) ),, cC-cSeq+1 ),
permMods, IFERROR( INDEX( permFactors,, IF( cSeq + 1 > cC, -1, cSeq+1 ) ), 1 ),
idx, INT( MOD( SEQUENCE( INDEX(permFactors, 1, 1),,0 ), permFactors )/permMods ) + 1,
answer, INDEX( matrix, idx, cSeq ),
er, OR( BYCOL( --ISBLANK(matrix), LAMBDA(x, SUM(--(INDEX(x,rSeq+1)<INDEX(x,rSeq))) ) ) ), // detect if there are stranded symbols
IF( SUM(symbolCounts)=0, "no symbols",
IF( er, "symbol columns must be contiguous",
answer ) ) )
)

这需要矩阵,就像上面一样(LET 版本如下所示)。它提供了完全相同的结果,但存在显着差异:
- 它是有效的。在此处显示的示例中,上面的简单公式
将生成
5^6 = 15625排列以达到
1440有效的排列。这只会生成需要的内容,不需要过滤。
- 但是,它根本无法处理那个搁浅的f。事实上,它会在f的位置生成一个 0,这不是拥有大量排列的用户甚至可能注意到的。
因此,存在错误检测和处理。变量er使用此 LAMBDA Helper 检测矩阵中是否有任何与上面的列不连续的滞留符号:
OR( BYCOL( --ISBLANK(matrix), LAMBDA(x, SUM(--(INDEX(x,rSeq+1)<INDEX(x,rSeq))) ) ) )
但这创造了一个新的挑战,也许是一个全新的问题。在搁浅f的情况下,任何人都可以想出一种方法来合并它吗?
另一个错误陷阱是检测列是否完全为空。
兰姆达魔术
LAMBDA 带来的魔力来自这一行,它使两个公式都可以扩展到任意数量的列,而无需对它们进行硬编码:
permFactors, INDEX( SCAN( 1, INDEX( symbolCounts, , cC-cSeq+1), LAMBDA(a,b, a*b ) ),, cC-cSeq+1 )
我从JvdV对这个问题的回答中得到了这个,该问题专门针对试图解决这个问题。Scott Craner和Bosco Yip已经证明,没有 LAMBDA 基本上是无法解决的,而 JvdV 展示了如何使用 LAMBDA 助手来完成SCAN。
LET 版本的有效公式
=LET( matrix, A2:F6,
cC, COLUMNS( matrix ),
cSeq, SEQUENCE( 1, cC ),
symbolCounts, BYCOL( matrix, LAMBDA(x, SUM( --NOT( ISBLANK( x ) ) ) ) ),
rSeq, SEQUENCE( MAX( symbolCounts )-1 ),
permFactors, INDEX( SCAN( 1, INDEX( symbolCounts, , cC-cSeq+1), LAMBDA(a,b, a*b ) ),, cC-cSeq+1 ),
permMods, IFERROR( INDEX( permFactors,, IF( cSeq + 1 > cC, -1, cSeq+1 ) ), 1 ),
idx, INT( MOD( SEQUENCE( INDEX(permFactors, 1, 1),,0 ), permFactors )/permMods ) + 1,
answer, INDEX( matrix, idx, cSeq ),
er, OR( BYCOL( --ISBLANK(matrix), LAMBDA(x, SUM(--(INDEX(x,rSeq+1)<INDEX(x,rSeq))) ) ) ),
IF( SUM(symbolCounts)=0, "no symbols",
IF( er, "symbol columns must be contiguous",
answer ) ) )