遞迴示例-指定數字以內的所有排列組合(Reduce)

熬肥妖發表於2024-06-27

指定數字以內的所有排列組合:

定義名稱版:

=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個數的所有組合就全部出來了。

好累~

相關文章