递归示例-指定数字以内的所有排列组合(Reduce)

指定数字以内的所有排列组合:

定义名称版:

=pmtt(指定数字)
    pmtt=LAMBDA(x,IF(x=1,1,VSTACK(pmtt(x-1),REDUCE(SEQUENCE(x),SEQUENCE(,x-1)^0*x,LAMBDA(a,b,TOCOL(a&SEQUENCE(,b)))))))

不定义名称版:

=LET(fx,LAMBDA(npmtt,x,IF(x=1,1,VSTACK(npmtt(npmtt,x-1),REDUCE(SEQUENCE(x),SEQUENCE(,x-1)^0*x,LAMBDA(a,b,TOCOL(a&SEQUENCE(,b))))))),fx(fx,指定数字))

这个指定数不能太小,1的话,就只有1。

看一下2的结果:

没几个是吧?那就3:

看看这增长的架势,再大点的数就不截图了,且,最大就只能到7。

嗯,才7,返回的值有87万多,一个工作表才一百多万行……

好吧,言归正传,这公式要怎么理解,郑重点,加条分割线吧,顺带居中一下。

***********************************************************************

这公式分成两个部分,递归部分就是一个堆叠,前一个值的结果和当前值的结果堆叠在一起,这没啥好说的,重点是Reduce部分(本文是不是不该归类为递归?)

假设x为2,Reduce部分的公式就可以写成:

=REDUCE(SEQUENCE(2),SEQUENCE(,2-1)^0*2,LAMBDA(a,b,TOCOL(a&SEQUENCE(,b))))

公式返回的结果就是11、12、21、22。

初始值是纵向矩阵1和2,数组就是一个2,然后Reduce的功能就是为迪卡尔积运算而生的,Lambda里使用&连接就可以了,需要注意的是连接的对象不是简单的a&b,而是a连接以b为列数的一行,这里就是横向的1和2。

在这公式里,数组参数的写法明显很累赘,这其实是为递归而设置的具有统一性的一个公式,x为2的时候感觉上去还没啥,再来看当x为3的时候。

好吧,接下来的内容已经没办法在一个平面内正常展示了,只能通过脑电波“搬砖”,就比如a&SEQUENCE(,b),b本身就是一个横向数组,要怎么横向?想说所以才用ToCol?不,ToCol的功能绝不是简单的转成一列,不然把ToCol部分去掉试试,结果就不对了。

那么,一步一步来吧。

第一步运算(这个步子有点大哈):

纵向的1、2、3和横向的1、2、3连接,结果就是11-33的9个值。

ToCol的目的是把这9个值转成一列,然后,这一列就摇身一变,变成了第二步运算的a:

接下来就是新的a和SEQUENCE(,b)的连接。

然后,3个数的所有组合就全部出来了。 

好累~

用Reduce实在太BT了,可以用Base吗?

数值是没问题,但其他呢?用了Reduce,参数由Sequence换成引用,那就随便什么都可以组合了,Base的话……不管了,下篇先写个Base的解法吧。

posted @ 2024-06-27 18:29  熬肥妖  阅读(19)  评论(0编辑  收藏  举报