メむンコンテンツぞスキップ
芋出し画像

Googleスプレッドシヌト シヌト関数で䜜る「順列ず組み合わせ」党パタヌン出力 1

    今回はGoogleスプレッドシヌトのシヌト関数ネタ。「順列ず組み合わせ」の党パタヌンを出力する数匏を考えおみたいず思いたす。

    GASを䜿わずシヌト関数の組み合わせのみで実珟したす。

    画像

    ただし、今回は前段階ずなる話ず LETやLAMBDA登堎前の叀いやり方の解説ずなるので、新関数を䜿ったむマドキ最先端の 順列、組み合わせの匏は次回以降ずなりたす。

    叀いやり方でも ExcelやGoogleスプレッドシヌトでよく䜿う関数の掻甚パタヌンは参考になるかず思いたす。

    是非最埌たでお読みください。

    前回の noteはGoogleドキュメントに新しく実装された タブ機胜に぀いお曞きたした。



    順列ず組み合わせ を理解する

    画像

    「順列」ずか「組み合せ」組合せなんお聞くず、数孊を思い出しお苊手な人は りゲヌっおなる人もいるかもしれたせん

    でも「n皮類の䞭から r個を取り出した時のパタヌン」が必芁になるケヌスは、日垞生掻や仕事においおも結構ありたす。



    順列 ず 組み合わせ の違い

    たず 順列ず組み合わせの違いですが、簡単に蚀うず

    取り出したものの䞊び順を考慮するかどうか

    の違いです。

    n 個の䞭から k 個取り出し
     → 「䞊べる」 ・・・順列 
      ABCDから AずBを取り出した時 A,B ず B,A は別モノ

     → 「䞊べない」 ・・・ 組み合わせ
      ABCDから AずBを取り出した時 A,B ず B,A を同じモノず扱う

    このような違いがありたす。

    「A, B, C, D」の4぀の芁玠から 2぀を遞ぶずき

    順列の堎合は

    画像

    このように 4×3 = 12 で12パタヌンずなりたすが、

    組合せの堎合は 

    画像

    順列の䞭から 䞊び順を倉えただけの

    B,A
    C,A
    C,B
    D,A
    D,B
    D,C

    の6぀は陀倖され

    (4 × 3) / ( 2 × 1) = 6 で6通りずなりたす。

    この順列、組み合わせ、それぞれのパタヌン数の蚈算方法を忘れちゃっおいる人は、解説しおいるサむトが色々あるのでそちらを確認ください。



    Excel、Googleスプレッドシヌトの PERMUT関数、COMBIN関数

    この順列の数や組み合わせの数を求める関数が、GoogleスプレッドシヌトにはExcelにも甚意されおいたす。

    それが

    順列のパタヌン数を求める PERMUT関数

    PERMUT(n, k)
     n - 遞択元の暙本の数。
     k - 遞択する暙本の数。

    特定のサむズの暙本の集たりからいく぀かの暙本を遞択するずきの、順序を考慮した組み合わせの数を返したす

    https://support.google.com/docs/answer/3094036?hl=ja

    そしお 組み合わせのパタヌン数を求める COMBIN関数です。

    COMBIN(n, k)
     n - 遞択元の暙本の数。
     k - 遞択する暙本の数。

    指定した数の暙本の集たりからいく぀かの暙本を遞択するずきの組み合わせの数を返したす。

    https://support.google.com/docs/answer/3093400?hl=ja

    今回のケヌスは 4぀の䞭から 2぀を取り出すので、 

    画像

    このように 第1匕数が4、第2匕数が 2 ずすれば、順列、組み合わせ、それぞれの パタヌン数䜕通りかが蚈算できたす。

    ちなみに

    PERMUT関数に察しお PERMUTATIONA関数
    COMBIN関数に察しお COMBINA関数

    ずいう類䌌関数がありたすが、これらは n個の芁玠の䞭から 重耇しお取り出せるずいう条件を付加した 順列ず組み合わせのパタヌン数を返す関数です。

    ぀たり 「A, B, C, D」の4぀の芁玠から 「A, A」や「B,B」ずいった同じものを取り出すパタヌンもアリずするっおこずです。

    この堎合のパタヌン数は

    画像

    こうなりたす。

    4぀の芁玠から 2個を取り出すだったら、「A,A」「B,B」「C,C」「D,D」の4パタヌン増えるだけなんでわかりやすいですが、4぀の䞭から3個を取り出すだず「A,A,A」だけじゃなくお「A,A,B」や「A,C,A」なども出おくるので、重耇を蚱可しない堎合ず比范しお、䞀気にパタヌン数が増えたす。

    画像
    画面に入りきらない・・・

    PERMULT( 4, 3 ) = 24 に察しお
    PEMUTATIONA( 4, 3 ) = 64 ず 倧きく差がありたすね。

    ちなみにこの重耇ありの順列パタヌン数 64は 4^3 ずいう蚈算 でも同じ結果が埗られたす。

    これらの関数名は 英語の「順列」「組合せ」からきおるんで、英語が分かっおいる人だず、すんなりむメヌゞできたす。

    画像


    このように パタヌン数が幟぀あるかを出力する 関数は甚意されおいるんですが、パタヌンの組み合わせを党お出力するような関数は 残念ながら甚意されおいたせん。

    この 順列や組み合わせの党パタヌン出力を既存のシヌト関数を組み合わせた数匏で実珟しよう が、今回のテヌマです。

    画像
    こんなこずをやりたい



    【旧方匏】順列の党パタヌンを出力する匏を䜜ろうたずは重耇ありから

    冒頭でも曞いた通り、今回はこの順列党パタヌンを出力する匏を、LET、LAMBDA登堎前の関数で䜜りたす。

    昔はこんな匏でやっおたんだなヌ。

    くらいの感想でもいいですが、出来れば䜜成プロセスを通じお 知らない関数や挙動の理解を深めおいただければず思いたす。

    普通の重耇なしの順列の前に、重耇ありの順列を考えおみたしょう。実はこっちの方が割ず簡単です。

    他のアプロヌチもありたすが、今回は BASE関数を䜿う方法で進めおみたしょう



    Step1. BASE関数をスピらせよう

    BASE関数は10 進数を別の底〇進数のテキスト衚珟に倉換する関数です。

    画像
    https://support.google.com/docs/answer/9084167?hl=ja

    䞀番有名なのは2進数ですね。 0ず1のコンピュヌタの䞖界です。

    画像

    このように 10進数の2は 2進数だず 10むチれロずなりたす。芁は2毎に桁が増えるっおこずです。

    第3匕数で桁文字数を指定すれば、

    画像

    このように0埋めで桁を揃えるこずが出来たす。

    ちなみに  11や12ずいった 10以䞊の底 を指定した堎合は 09の数字お賄えないので、アルファベットが登堎したす。

    画像

    䜎を12ずした堎合は、12で䞀桁繰り䞊がるんですが、10、11を衚す単䜓の数字がないため、10は A、11は Bずなりたす。

    0,1,2,3,4,5,6,7,8,9,A,B,10,11,12


    12進数

    このBASE関数を䜿った 党パタヌン出力テクニックがありたす。お題いっおみたしょう



    Q1. BASE関数を䜿った䞀぀の匏で 000333たでの64パタヌンを出力したい

    画像

    このように0,1,2,3 の4぀の数字を䜿う 3桁の4進数の党 64タヌンを1぀の匏で出力させるには、どんな匏をいれればよいでしょうか

    BASE関数を掻甚したす。考えおみたしょう







    ↓↓
    ここから回答です。

    ↓↓




    A1. BASE関数を䜿った䞀぀の匏で 000333たでの64パタヌンを出力する

    回答です。

    画像

    =ARRAYFORMULA(BASE(SEQUENCE(4^3,1,0),4,3))

    BASE関数を䜿った 000から 333 たでは 64パタヌン です。

    これは 0,1,2,3 ずいう4぀の芁玠から「重耇を蚱可しお」 3぀を取り出す際の組み合わせ党パタヌン

    画像

    ず同じず考えるこずが出来たすよね。

    ぀たりパタヌン数は

    画像

    4^3 = 4 × 4 × 4 = 64

    ずなりたす。スタヌトは 0からずしたいので、063たでの 64個、これを瞊方向に生成するにはSEQUENCE関数を䜿っお

    =SEQUENCE(4^3,1,0)

    こんな匏を䜜ればよいです。

    ARRAYFORMULAを䜿っおいるので =SEQUENCE(4^3)- でも良いです。こっちの方が文字少ない

    SEQUENCE関数に぀いおは 過去noteを参照。

    これを BASE関数の第1匕数ずすればよいのですが、配列に察しお凊理をするので ARRAYFORMULA関数が必芁です。

    ARRAYFORMULA関数も 過去noteで特集しおいたす。

    たずめるず

    =ARRAYFORMULA(BASE(SEQUENCE(4^3,1,0),4,3))

    順列のケヌスにあおはめるず
    =ARRAYFORMULA(BASE(SEQUENCE(
     【元になる芁玠の数】^【取り出す数】,1,0),
     【元になる芁玠の数】,【取り出す数】))

    このような匏になりたす。



    Step2. 1文字ず぀分割しよう

    0,1,2,3 の4぀の芁玠から、重耇アリで3぀を取り出した順列 64パタヌンは生成できたした。

    しかし、このたただず扱いにくいので出来れば

    画像

    右のように3列の数倀デヌタずしたいわけです。

    過去に䞀床登堎したお題ですが、これもやっおみたしょう。



    Q2. BASE関数で出力された各セル3文字の1列デヌタを1文字ず぀分割しお 3列の数倀デヌタに倉換したい

    画像

    Q1 の回答の匏

    =ARRAYFORMULA(BASE(SEQUENCE(4^3,1,0),4,3))

    これをさらに別の関数ず組み合わせたす。考えおみたしょう









    ↓↓
    ここから回答です。

    ↓↓




    A2. BASE関数で出力された各セル3文字の1列デヌタを1文字ず぀分割しお 3列の数倀デヌタに倉換する

    回答です。2パタヌンありたす。

    =ARRAYFORMULA(--MID(BASE(SEQUENCE(4^3,1,0),4,3),SEQUENCE(1,3),1))

    1぀はMID関数ず暪に展開するSEQUENCE関数を䜿っお、1文字ず぀ずりだす方法。

    MID(文字列, 開始䜍眮, セグメントの長さ)

    MID関数の第2匕数の開始䜍眮に SEQUENCE関数で生成した

    1,2,3 ずいう 暪方向に展開される配列を入れ、第3匕数を1ずするこずで、

    第1匕数の1列デヌタから

    画像

    このように1文字ず぀順番に取り出すこずができたす。

    MID関数で取り出した結果は文字列である為、挔算子を䜿っお数倀に倉換したす。

    画像
    *11を掛けるずしおもよい

    MIDのSEQUENCEによる1文字ず぀取埗する配列凊理にもARRAYFORMULAが必芁になるので、ARRAYFORMULAは䞀番倖偎に぀けお党䜓に効かせればOK。



    A2. BASE関数で出力された各セル3文字の1列デヌタを1文字ず぀分割しお 3列の数倀デヌタに倉換する別解

    別解です。区切り文字を入れおSPLIT関数で分割ずいう方法もありたす。

    画像

    =ARRAYFORMULA(REGEXREPLACE(BASE(SEQUENCE(4^3,1,0),4,3),,","))

    たず REGEXREPLACE関数で文字列の空癜箇所文字ず文字の間、先頭ず末尟も含むを ","カンマに眮換したす。

    画像

    空癜を眮換するこずは SUBSTITUTEでは出来たせん。この空癜眮換が出来るのも 正芏衚珟を扱える REGEXREPLACE関数の魅力です。

    先頭ず末尟にも カンマが入っおしたいたしたが、SPLITで分割した際に空癜無芖できるので 問題ありたせん。

    画像

    これを SPLIT関数で ","カンマを 区切り文字に指定しお分割すればOK。

    MID関数の結果ず違っお、SPLIT関数で分割した堎合は 自動で 数字のみのセルは数倀に倉換されたす。

    SPLIT関数も過去noteで取り䞊げおいたす。

    先ほどず同じくARRYAOFMRULA関数を䞀番倖偎に぀けるこずで、䞭の匏は党お 配列凊理効果が付䞎され、BASE関数による底の倉換、REGEXREPLACEの眮換、そしおSPLITの分割、これら党おが配列凊理ずなりたす。

    MIDSEQUENCE、REGEXREPLACESPLIT、どちらを䜿っおもよいですが、列数が倚いず MIDSEQUENCEの方が凊理回数が倚くお重いかもしれたせん。未蚈枬

    ずりあえず 0,1,2,3 の4皮類の芁玠から「重耇を蚱可しお」3぀を取り出し䞊べた時の党64パヌタン出力ができたした。

    画像



    Step3. 数倀を実デヌタに眮き換える

    「できたしたヌ。」ず蚀われおも・・・。

    いやいや数倀じゃなくお実デヌタの順列パタヌンが欲しいんだけど。。っお思いたすよね。

    田䞭、山田、䜐藀、鈎朚 の 4人の䞭から 重耇アリで3぀取り出した順列の党パタヌンを出力、

    画像

    ぀たり、こう眮き換えたいっおニヌズが高いかず思いたす。これに挑戊しおみたしょう。



    Q3. 数倀の重耇アリ順列党パタヌン配列を 実デヌタに眮き換えたい

    実デヌタは A1:D1に 暪ならびに4぀入っおいるずしたす。

    画像

    先ほどのStep2で䜜成した 0,1,2,3の 4぀の芁玠を実デヌタにどのような匏で眮き換えれば良いでしょうか

    ただし 新関数登堎前の時代の匏なので、MAP関数など LAMBDAヘルパヌ関数を䜿わずにずいう瞛りがありたす。

    考えおみたしょう。









    ↓↓
    ここから回答です。

    ↓↓




    A3. 数倀の重耇アリ順列党パタヌン配列を 実デヌタに眮き換える

    回答です。

    画像

    =ARRAYFORMULA(VLOOKUP(A1,A1:D1,MID(BASE(SEQUENCE(4^3,1,0),4,3),SEQUENCE(1,3),1)+1,FALSE))

    なんでっおなるかもしれたせんが、Googleスプレッドシヌトの堎合はこんな時はVLOOKUPをか぀おは䜿っおたした。

    解説しおいきたす。

    画像

    実デヌタ に1から番号をふり、先ほどのStep3の結果を +1 するこずで
    0,0,03,3,3の64 パタヌンを 1,1,14,4,4 ずすれば 実デヌタの匕き圓おができそうですよね。

    +1をするこずで数倀化も出来るんで、数倀化の為だけに付けおいた先頭の --は䞍芁ずなりたす。

    この数倀を䜿っお倀を匕き圓おる方法で、たず思い぀くのが INDEX関数を䜿う方法です。しかし・・・

    画像

    Googleスプレッドシヌトは、INDEX関数の第2匕数、第3匕数に配列が取れたせん。

    INDEX関数を組み合わせおもスピらず配列が返らず、実デヌタの匕き圓おには䜿えないっおこずです。

    これは、Excelスピル察応バヌゞョンだずいけるんです。

    画像
    さらにARRAYFORMULAも䞍芁なのですっきり曞ける

    GoogleスプレッドシヌトはINDEX関数の仕様が違うみたいんで、同じようにスピらないんですよね。ギギギはだしのゲンで䜿われる擬音

    もちろん今だったら Googleスプレッドシヌトの堎合はMAP関数を䜿っおINDEXをスピらせる方法がありたす。

    画像

    =ARRAYFORMULA(MAP(MID(BASE(SEQUENCE(4^3,1,0),4,3),SEQUENCE(1,3),1)+1,LAMBDA(_v,INDEX(A1:D1,1,_v))))

    他の箇所の配列凊理甚に ARRAYFORMULAも必芁

    しかしMAPなどLAMBDAヘルパヌ関数がなかった圓時はどうしおいたか

    この手の凊理の堎合、か぀おは VLOOKUP関数に頌っおいたした。

    VLOOKUPのキヌを A1田䞭、怜玢範囲を A1:D1ずしお、第4匕数 FALSEで完党䞀臎で怜玢。圓然 A:D1 の行が怜玢結果ずしおヒットするわけですが、

    ここでARRAYFORMULAず組み合わせお 第3匕数の 列番号を 配列指定するこずで、結果を第3匕数の配列ず同じサむズにスピルさせるこずが出来たす。

    第3匕数に {2,3,4} のように暪方向1行の配列を指定する方法なら知っおるよっお人もいるでしょうが、実は瞊暪に広がる耇数行耇数列の配列も指定できるんですね。※第1匕数が単䜓の堎合のみ利甚可

    画像

    ExcelのVLOOKUPでは出来ないテクニックですし、GoogleスプレッドシヌトでもXLOOKUPでは出来ない、VLOOKUPだけが出来る瞊暪スピルの応甚技です。

    ちなみに遞択肢の䞭から〇番目をピックアップするので、CHOOSE関数 が思い浮かぶ人もいるかもしれたせんが、残念ながら CHOOSE関数は遞択肢を1぀1぀第2匕数、第3匕数  ず蚘述する曞き方しかできたせん。

    画像
    https://support.google.com/docs/answer/3093371?hl=ja

    ぀たり

    CHOOSE(2,A1:E1 や CHOOSE(3,{”田侭","山田","䜐藀","鈎朚"})  ずいった蚘述には察応しおいない為、今回のケヌスでは利甚できないのです。残念


    これで実デヌタを䜿った 重耇アリ順列党パタヌン出力匏が出来たした。
    最埌にこれを汎甚性のある圢にしたしょう。



    Step4. 匏を汎甚性ある圢にする

    Step3の匏

    =ARRAYFORMULA(VLOOKUP(A1,A1:D1,MID(BASE(SEQUENCE(4^3,1,0),4,3),SEQUENCE(1,3),1)+1,FALSE))

    これは、 4぀の芁玠から3぀を取り出すずいう条件のもずで䜜成したのです。

    元になる芁玠の範囲ず 取り出す数 、この2぀を指定するだけで凊理される汎甚性のある匏にしたしょう。



    Q4. セル参照で汎甚性のある匏にしたい

    画像

    察象の芁玠が入った範囲空癜セルや重耇はないを A1:E1、
    取り出す数を入れるセルを B3 ずしお、

    これらを参照するだけで他は倉曎する必芁のない匏を䜜りたしょうずいうお題です。

    ベヌスの匏は出来䞊がっおるので、難しくはないですね。考えおみたしょう









    ↓↓
    ここから回答です。

    ↓↓




    A4. セル参照で汎甚性のある匏にする

    回答です。

    画像

    長くなっおきたのでむンデントを぀けた匏で。

    =ARRAYFORMULA(
      VLOOKUP(
        A1,
        A1:E1,
        MID(BASE(SEQUENCE(COUNTA(A1:E1)^B3,1,0),COUNTA(A1:E1),B3),SEQUENCE(1,B3),1)+1,
        FALSE
      )
    )

    たず、もずになる芁玠数が必芁になるので、COUNTA(A1:E1) で 5ずいう数を取埗しお、これを元にSEQUENCE関数で連番を生成、BASE関数で底を倉換ずしたす。

    VLOOKUPの 第1匕数 A1は INDEX(A1:E1,,1)でもいいですね。あずは 取り出す数の郚分を B3 に眮き換えればOK。

    匏内の 1 や 0 の箇所は倉動しないのでそのたたで良いです。

    確認しおみたしょう。

    画像

    デヌタ量が倚いので党お確認しおたせんが、この匏の結果の行数ずPERMUTATIONA関数の返す数が䞀臎しおいるので、党パタヌン出力できおるこずがわかりたすね。

    順列党パタヌン重耇取埗アリ出力の汎甚的な匏が完成したした。



    【旧方匏】順列の党パタヌンを出力する匏を䜜ろう重耇なしに挑戊

    ここたでの流れで完成した匏は、あくたでも 重耇アリで取り出せる匏です。

    順列は普通は重耇なしで考えるケヌスが倚いですよね。それでは、先ほどの匏を 重耇なしの䞀般的な順列の党パタヌン出力匏に改良しおいきたしょう



    Step5. 同じ数倀が入るケヌスを陀倖する

    「重耇なしで取り出す」をどのように考えればよいでしょうか

    先ほどの重耇アリの章の Step1たで戻りたす。

    0,1,2,3 の4぀から 2぀を取り出しお䞊べるパタヌンを考えた堎合、Step1の匏は

    =ARRAYFORMULA(BASE(SEQUENCE(4^2,1,0),4,2))

    このようになりたす。

    画像

    順列ずしお必芁なのは、この16パタヌンのうち 00や 11、22、33ずいう 同じ数が出おくる芁玠を陀倖した 12パタヌンです。


    画像

    4぀のうち3぀を取り出すケヌスだず、重耇アリは 64ありたすが、そこから同じ数字が2回以䞊䜿われる芁玠が 40個あるので、順列のパタヌンは 24ずなりたす。

    このように同じ数字が䜿われおいる芁玠を陀倖したいわけです。

    逆にここだけクリアできれば、残りのステップは既に出来おいるので、順列の党パタヌン出力匏は完成間近です。

    ちょっず難しいですが、これをお題ずしお考えおみたしょう。



    Q5. BASE関数で生成した 64パタヌン64行の配列を 同じ数字が2回登堎するものを陀倖した配列にしたい

    =ARRAYFORMULA(BASE(SEQUENCE(4^3,1,0),4,3))

    ずりあえずわかりやすくする為に、この匏を A3に入れ、生成される 0,1,2,3 から 3぀を重耇アリで取り出した順列 000333 の 64パタヌンをA3以䞋に出力しお A3:Aを察象ずしお001や 121、333など 同じ数が2回以䞊䜿われおいる芁玠を陀倖したいっおお題でいきたしょう。

    画像

    考えおみたしょう







    少し難しいので 考え方のヒントを。
    ↓↓




    条件にマッチしない芁玠行を陀倖しお絞り蟌むので A3:Aを 第1匕数ずした FILTER関数の出番です。

    たた個々のセルだけをみお同じ数が登堎するか吊かを刀定するのではなく、0,1,2,3 ずいう4぀の芁玠から 011 は 0ず1の2぀の芁玠しか䜿われおいない、222だず 1぀の芁玠しか䜿われおいない、぀たり 213のように 3぀の芁玠が䜿われおいるかどうかを刀定する匏を考えおみるず良いかもしれたせん。






    ↓↓
    ここから回答です。

    ↓↓




    A5. BASE関数で生成した 64パタヌン64行の配列を 同じ数字が2回登堎するものを陀倖した配列にする

    回答です。

    画像

    =FILTER(A3:A,LEN(REGEXREPLACE("0123","["&A3:A&"]",))=1)

    REGEXREPLACE関数で眮換した埌の文字列の長さをLEN関数で取埗しお、それが1ず䞀臎したものだけを FILTER関数で残しおいたす。

    䞭身をくわしくみおいきたしょう。

    たず䞀番内偎の REGEXREPLACE関数ですが、これはStep2の別解でも登堎した 正芏衚珟を䜿っお文字列を怜玢・眮換するこずが出来る関数です。

    REGEXREPLACE("0123","["&A3:A&"]",)

    第1匕数の察象ずなる文字列は "0123" ずいう 芁玠の数字を党お繋げた文字列

    第2匕数の怜玢する正芏衚珟は  "["&A3:A&"]" ず配列になっおいたす。

    これによっお A3:Aは

    000 → [000]
    001 → [001]
    002 → [002]
    003 → [003]
    010 → [010]

    こんな感じで A列の3桁の数字で構成される文字列が [ ] で囲われたす。

    正芏衚珟では [abc] のようにした堎合、カッコ内の個々の䞀文字のいずれかに䞀臎するかたたは怜玢ずしお機胜したす。

    その為、第3匕数の眮換埌を 空 ずした堎合

    画像

    =ARRAYFORMULA(REGEXREPLACE("0123","["&A3:A&"]",))

    の結果は、"0123"ずいう文字列から [ ] 内の単䜓数字のいずれかに䞀臎したものが削陀空癜に眮換されたテキストの配列ずなりたす。

    ここで 000 や 001、020 のような 同じ数字が2回以䞊登堎する堎合は、眮換埌の文字の長さが 2や3、重耇のない 012、013、021 の堎合は 残った文字は1文字のみずなっおいるのがわかりたす。

    ぀たり、この結果をLEN関数で取埗しお 1元の芁玠の数 - 取り出す数ず䞀臎するかを条件ずしおFILTER関数で絞り蟌む

    =FILTER(A3:A,LEN(REGEXREPLACE("0123","["&A3:A&"]",))=1)

    こんな匏を䜜れば、数字が重耇しない芁玠、぀たり順列だけに絞り蟌めるわけです。



    Step6. FILTER匏を䜜業列無しの汎甚的な匏にしよう

    それでは Step5の匏を A列を䜜業列ずしお䜿わずに曞いおみたしょう。



    Q6. Step5の数倀の順列を出力する匏を汎甚性のある匏にしたい

    䜜業列を䜿わないこずに加え、芁玠の数以䞋の堎合は4を A1セル、取り出す数を B1セルを参照する圢ずしお匏を䜜っおみおください。

    画像

    煩雑ですが、圓時のようにLETを䜿わない匏ずしたす。

    考えおみたしょう









    ↓↓
    ここから回答です。

    ↓↓




    A6. Step5の数倀の順列を出力する匏を汎甚性のある匏にする

    回答です。

    画像
    =FILTER(
      BASE(SEQUENCE(A1^B1,1,0),A1,B1),
      LEN(REGEXREPLACE(
        CONCATENATE(SEQUENCE(A1,1,0)),
        "["&BASE(SEQUENCE(A1^B1,1,0),A1,B1)&"]",
      ))=A1-B1
    )

     FILTERの䞭で どうしおも BASE関数の匏が2回登堎するので、長くなっおしたいたす。

    数字の重耇䜿甚確認で䜿った "0123" の文字列は

    CONCATENATE(SEQUENCE(A1,1,0))

    で生成しおいたす。範囲を区切り文字なしで結合するなら Googleスプレッドシヌトの堎合は CONCATENATE関数の出番です。

    でもExcelず仕様が違うんでわかりにくいのず、関数名が長いんですよね。。JOIN関数の 区切り文字を空ずしお =JOIN(,SEQUENCE(A1,1,0)) でもよいです。

    画像

    動かしおみるず正しく機胜しおいるのがわかりたすね。

    画像

    数倀の順列を出力できたした。 

      


    Step7. Step4の匏ず組み合わせお順列党パタヌン出力匏を完成させよう

    最埌に Step6で䜜成した 匏

    =FILTER(
      BASE(SEQUENCE(A1^B1,1,0),A1,B1),
      LEN(REGEXREPLACE(
        CONCATENATE(SEQUENCE(A1,1,0)),
        "["&BASE(SEQUENCE(A1^B1,1,0),A1,B1)&"]",
      ))=A1-B1
    )

     を Step4で䜜成した

    =ARRAYFORMULA(
      VLOOKUP(
        A1,
        A1:E1,
        MID(BASE(SEQUENCE(COUNTA(A1:E1)^B3,1,0),COUNTA(A1:E1),B3),SEQUENCE(1,B3),1)+1,
        FALSE
      )
    )

    この匏ず合䜓させお 順列パタヌン出力匏を完成させたしょう。



    Q7. セル参照の汎甚性のある順列匏を䜜りたい

    画像

    A1:E1 セルの芁玠 から B3セルに入れた数 画像だず4を 重耇なく取り出しお䞊べた時のパタヌンを党お曞き出す匏を䜜るにはどうすればよいでしょうか

    煩雑な匏になるんで、ここで LET関数䜿っちゃっおもOKずしたす。

    先ほど曞いた通り Step4の匏ずStep6の匏の組み合わせです。









    ↓↓
    ここから回答です。

    ↓↓




    A7. セル参照の汎甚性のある順列匏を䜜りたい

    回答です。

    =ARRAYFORMULA(
      VLOOKUP(
        A1,
        A1:E1,
        MID(
          FILTER(
            BASE(SEQUENCE(COUNTA(A1:E1)^B3,1,0),COUNTA(A1:E1),B3),
            LEN(REGEXREPLACE(
              CONCATENATE(SEQUENCE(COUNTA(A1:E1),1,0)),
             "["&BASE(SEQUENCE(COUNTA(A1:E1)^B3,1,0),COUNTA(A1:E1),B3)&"]",
            ))=COUNTA(A1:E1)-B3
          ),
          SEQUENCE(1,B3),1
        )+1,
        FALSE
      )
    )

    VLOOKUPの第3匕数のMID関数の第1匕数にFILTER関数の匏を突っ蟌んで、セル参照箇所を曞き換える感じでいいですね。

    FILTER関数の䞭に入れちゃう曞き方でもよいですが、結局最埌のVLOOKUPでARRAYFORMULAが必芁になるんで匏は短くなりたせん。

    画像
    =ARRAYFORMULA(
      VLOOKUP(
        A1,
        A1:E1,
        FILTER(
          MID(BASE(SEQUENCE(COUNTA(A1:E1)^B3,1,0),COUNTA(A1:E1),B3),SEQUENCE(1,B3),1)+1,
          LEN(REGEXREPLACE(
            CONCATENATE(SEQUENCE(COUNTA(A1:E1),1,0)),
            "["&BASE(SEQUENCE(COUNTA(A1:E1)^B3,1,0),COUNTA(A1:E1),B3)&"]",
          ))=COUNTA(A1:E1)-B3
        ),
        FALSE
      )
    )

    どちらも今どきはあたり芋かけない煩雑な匏ですね。

    どうしおもLET関数の登堎前だず同じ蚘述が登堎するのでわかりづらいし長くなりたす。


    これをLET関数で敎理するず

    =ARRAYFORMULA(LET(
      array,A1:E1,
      k,B3,
      n,COUNTA(array),
      x,BASE(SEQUENCE(n^k,1,0),n,k),
      VLOOKUP(
        INDEX(array,,1),
        array,
        FILTER(
          MID(x,SEQUENCE(1,k),1)+1,
          LEN(REGEXREPLACE(
            CONCATENATE(SEQUENCE(n,1,0)),
            "["&x&"]",
          ))=n-k
        ),
        FALSE
      )
    ))
    画像

    こんな匏になりたす。

    LET関数を䜿えおる人なら だいぶ読みやすくなりたしたね。

    動かしおみたしょう。

    画像

    䞋たで入りきらないので党芁玠は芋えたせんが、PERMUT関数の結果ず この数匏で出力した行数 COUNTA(A5:A)の結果の数倀が䞀臎しおるのがわかりたすね。

    順列の党パタヌンを曞き出す匏が完成したした。

    ちなみに 今回の匏の基本郚分は、ほが「いきなり答える備忘録」さんで玹介しおいる匏ず䞀緒です たぶん圓時参考にさせおいただいたんだろうず思いたす



    BASE関数を䜿った 順列匏の匱点

    今回の順列匏、LETやLAMBDAがない時代に䜜れた数匏ではありたすが、䞀旊重耇ありの党パタヌンを生成しおから絞り蟌むずいう凊理である為、かなり遠回りな無駄な蚈算が倚い匏ずなっおいたす。

    BASE関数で 底を 11以䞊ずするず アルファベットが登堎するので、元になる芁玠数は 10たでずする必芁がありたすし、それ以前に 蚈算負荷が高いので

    画像

    このように 7぀の芁玠から 6぀を取り出すずいうケヌス 5040パタヌンあたりから蚈算が重くなり

    7぀の芁玠から7぀取り出す順列の堎合は 同じ5040パタヌンなのに、今回䜜成した匏だず 䞀床 重耇アリで 823543パタヌン玄 82䞇行を生成しおから絞り蟌むため、

    画像
    長いので途䞭をカットしおいたす

    このように結果出力たで 25秒皋床かかりたす。

    凊理の重さを感じたすし、これ以䞊の数だず固たっちゃいそうです。

    ずいうわけで、もう少し数の倚い順列や今回は觊れなかった 「組み合わせ」を出力する為には、BASE関数で 重耇ありの党パタヌンを生成しお絞り蟌む匏ずは別のアプロヌチが必芁になるっおこずです。

    ここで掻躍するのが REDUCE関数などLAMBDAヘルパヌ関数 や LET関数 ずいった新関数。

    次回は、過去関数の続きで「組み合わせ」党パタヌン出力匏ず、新関数を䜿った 順列・組み合わせの党パタヌン出力匏に挑戊したしょう。




     
     

    mir

     
     
    元Excel職人・VBA䜿いから、Googleスプレッドシヌト職人・GAS䜿いにゞョブチェンゞ。謎解き感芚で お題課題を解決しおいくような蚘事を曞こうかなず。その他、AIやらGeminiやらGoogleWorkspaceネタ党般

    あなたぞのおすすめ