【ダメージ計算】Excel × LAMBDAで”イルーナ算”を効率化?

【ダメージ計算】Excel × LAMBDAで”イルーナ算”を効率化?

目次

  1. 前置き
  2. iruCalc関数
  3. 利用方法
  4. 技術的解説
  5. 最後に

前置き

突然ですがみなさんは装備を検討する際、ATKやMATK、ダメージについて装備プロパティをもとに計算するタイプですか?
それとも実際に装備して試行錯誤するタイプでしょうか?
どちらも良し悪しがありますが、私は基本的に前者です。
今回の記事は私のように計算する派の方に向けた記事になります。

さて、イルーナ戦記において各種計算をする際のポイントとして乗算、除算時の切り捨て処理が挙げられます。
概算する分には意識する必要がありませんが、誤差なく正確な値を求めるためにはこの処理は必須です。
これをタイトルに掲げている”イルーナ算”と呼ぶことにします。

実際に計算をするツールとしてはExcelをはじめとしたスプレッドシートを活用している方が多いかと思います。
まずは、Excelでダメージ計算をする具体例を挙げてみましょう。

以下は汎用装備(≠ 属性特化)でルナ人形への分身乱舞ダメージを計算したものです。
※ 説明の便宜上基礎ダメージの計算やクリティカル計算は割愛しています

=ROUNDDOWN(ROUNDDOWN(ROUNDDOWN(ROUNDDOWN(ROUNDDOWN(B3*(1+C3),0)*D3,0)*(1+E3),0)*(1+F3),0)*(1-G3),0)

ポイントはROUNDDOWN関数で、小数点以下の切り捨てを行います。
これで正確に値は計算できるのですが、お世辞にも見やすいとは言い難いです。
ROUNDDOWN関数を連発しているのもそうですが、括弧がネスト(入れ子)しており、
少し式を修正しようものなら閉じ括弧が迷子になってエラー地獄となる結末が容易に想像できます。

iruCalc関数

Excelは優秀な計算ツールとして機能しますが、イルーナ算を行うためには冗長な記述が必要です。
しかし、幸いにもExcelの新機能として実装されたLAMBDA関数により、VBAを使わずに独自の関数を容易に定義することが可能になりました。
これを利用してイルーナ算に特化したiruCalc関数を作成しました。
まずは使用例を示します。

=iruCalc(B3)(1+C3)(D3)(1+E3)(1+F3)(1-G3)()

計算結果が同じなのは勿論のこと、各値を括弧で連結する形となり実際の数式に近い見た目なっていることがわかると思います。

また、括弧内の第二引数にTRUEを指定することで除算にも対応します。

=iruCalc(10)(2,TRUE)(3)()

(10 ÷ 2 × 3 = 15)

尚、計算の終わりを示すため、終端の空括弧()は必須です。

利用方法

iruCalc関数の定義は以下の通りです。
後述手順に従い名前の定義を追加することによりブック内で利用可能になります。
※ LAMBDA関数に対応したExcel for Microsoft 365、もしくはExcel 2024以降のみ利用可能です
※ Google スプレッドシートはLAMBDA関数に対応していますが、ISOMITTEDヘルパー関数に非対応のため使用不可です
  (2024年10月現在)
※ デバッグ時セル内で自己参照するためにZコンビネータを用いていますが、本来、名前の定義をしてから関数を利用する場合は不要です

=LET(
    Z, LAMBDA(f, LET(g, LAMBDA(x, f(LAMBDA(v, LET(xx, x(x), xx(v))))), g(g))), 
    iruCalc, Z(LAMBDA(iruCalc, LAMBDA(x, 
        LAMBDA([y], [divFlg], 
            LET(
                divFlg, IF(ISOMITTED(divFlg), FALSE, divFlg), 
                IF(ISOMITTED(y), 
                    x,
                    IF(divFlg, 
                        iruCalc(ROUNDDOWN(x / y, 0)), 
                        iruCalc(ROUNDDOWN(x * y, 0))
                    )
                )
            )
        )
    ))), 
    iruCalc
)

使用する場合は画像の手順に従い名前の定義を追加してください。

技術的解説

本関数は関数(LAMBDA)を返す関数です。
更にいうと関数を返す関数を返す関数を… 関数です。
戻り値が関数のため、括弧で値を連結させることが可能です。
最終的には関数ではなく値を返したいので、引数が空の場合のみ内部の計算結果を返しています。

JavaScriptで示すと以下のような構造です。
※ インデントをExcel関数に寄せています
※ ROUNDDOWNはMath.floorで代用しています

const iruCalc = x =>
    (y, divFlg = false) =>
        y === void 0
            ? x
            : divFlg
                ? iruCalc(Math.floor(x / y))
                : iruCalc(Math.floor(x * y));

値をネストさせずに横並びにする構造はJavaScriptのPromiseチェーンから着想を得ました。

最後に

いかがでしたでしょうか。
この記事の内容が刺さる人は少数かと思いますが、最近のExcelは面白いことができます。
ただ単に計算するだけでも有用ですが、名前の定義を活用して基本的な計算式をコンポーネント化するなど
工夫を行うとより効率的に活用できるかもしれません。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です