Google Sheet で指定値以下の素数を全て求める

最終更新日

G Sheet で指定値以下の素数を全て求める

こんな式で指定値以下の素数を全て求めることができる。(Gスプレッドシート)指定値以下の素数をすべて求める – いきなり答える備忘録を参考にしました。改行と空白だけ少し変えたけど、式の意味は同じ。

= REDUCE (
  SEQUENCE ( [指定値] - 1, 1, 2),
  SEQUENCE (SQRT ([指定値]) -1, 1, 2),
  LAMBDA (
    a,
    b,
    FILTER (a, (a = b) + (MOD (a, b) > 0))
  )
)

上の式の [指定値] に、素数を求める範囲の上限を入力する。そうすると入力した指定値以下の素数が、この式を入力したセルの下にずらっと並ぶよ。

この式の意味が分からなかったので、具体的に考えてみた。理解できたので、以下にそれを解説するよ。参照元のサイトでも説明されてるんだけど、読むだけでは分からなかったので…😅

式の解釈 (1) 使われる 6 つの関数

まず、使用される 6 つの関数を理解しよう。僕の主観で、簡単な順に並べてみた。特に lambda()reduce() は難しいよねえ。ちょうど 1 年前の 2023 年始めにも lambda() についてブログを書いたね。

関数説明
SQRT正の数値の正の平方根を返します。
MODモジュロ演算の結果、すなわち除算の剰余を返します。
SEQUENCESEQUENCE 関数は、1、2、3、4 などの連続する数値の配列を返します。
FILTERソース範囲をフィルタ処理して、指定した条件を満たす行または列のみを返します。
LAMBDA一連の名前とそれらを使用する数式を含むカスタム関数を作成して返すことができます。数式を計算するために、名前で宣言されている個数の値を指定して、返された関数を呼び出します。
REDUCEこの関数は、LAMBDA 関数を各値に適用して、配列を累積結果に減らします。
Google Sheet の基本の関数で高度なことができる

式の解釈 (2) reduce() がすること

reduce() は 3 つの引数を取る: 初期値、配列、そして lambda()。第 1、2 引数には sequence() が入っていて、これは数列を返す。reduce() の初期値として配列を使うところが難しいよね。

今回はキリよく [指定値] = 20 で見てみよう。すると、reduce() の第 1、2 引数は、具体的には下記のようになる。開始値を 2 としてるので、第 1 引数の [指定値] - 1 行の配列の最後の値が [指定値] ぴったりになるし、第 2 引数では sqrt( [指定値] ) - 1 行の配列の最後の値が sqrt( [指定値] ) 以下の整数になる。

  1. {2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; 19; 20}
  2. {2; 3; 4}
reduce() の第 1、2 引数の中身。sequence() の第 1 引数は非整数でも良いんだね😯

この 2 つの配列が lambda() に渡される。reduce() の第 1 引数 (上記の長い方の配列) は lambda() では a と名前が付けられて、第 2 引数は b と名前が付けられてる。そして、この ab に対して、filter() 関数を適用していく。

式の解釈 (3-1) lambda()filter() がすること

filter() 関数がすることは、その第 1 引数 a に対して、条件に該当するものを抽出する操作だ。その条件は (a = b) + (mod (a, b) > 0) となってる。これがまた難しい。

上記の条件では、真理値 (TRUEFALSE) 同士の足し算をしてる。(a = b) という真理値と、(mod (a, b) > 0) という真理値の足し算。真理値の足し算は「どちらかが TRUE なら TRUE、両方とも FALSE なら FALSE」ということ。

具体的に処理を見ると、こんな感じ。まず a に対して、b = 2filter() を行う。つまり、filter (a, (a = 2) + (mod (a, 2) > 0)) をやる。抽出条件の前半 (a = 2) は簡単なので OK として、条件の後半 (mod (a, 2) > 0) は「a ÷ b が割り切れない」という意味だね。つまり、割り切れなければ TRUE、割り切れれば FALSE だ。それを踏まえて見てみよう。

aa = bmod (a, b) > 0Result
2TRUEFLASETRUE
3FALSETRUETRUE
4FALSEFLASEFLASE
5FALSETRUETRUE
6FALSEFLASEFLASE
7FALSETRUETRUE
8FALSEFLASEFLASE
9FALSETRUETRUE
10FALSEFLASEFLASE
11FALSETRUETRUE
12FALSEFLASEFLASE
13FALSETRUETRUE
14FALSEFLASEFLASE
15FALSETRUETRUE
16FALSEFLASEFLASE
17FALSETRUETRUE
18FALSEFLASEFLASE
19FALSETRUETRUE
20FALSEFLASEFLASE
真理値を全て評価した

filter() 関数は、条件に合うものだけを残し、合わないものを除く関数だということを思い出そう。すると、上の表の右列が ✅ TRUE のものだけが残されて、出力はこうなる。つまり、2 と 2 の倍数以外が残ったんだね。

{2; 3; 5; 7; 9; 11; 13; 15; 17; 19}

式の解釈 (3-2) 2 度目、3 度目の filter()

そして、ここで終わりじゃないね。reduce() は、その第 2 引数の配列のそれぞれの値について lambda() を繰り返し実行する。今 {2; 3; 4} の b = 2 が終わったところなので、次は b = 3 で同じことをする。

2 回めの filter() は、前回の filter() の出力を第 1 引数に取る (それが reduce() の動作だからね)。というわけで、b = 3 となる 2 回目の filter() で何が残り何が除かれるか、また真理値の表を作って見てみよう。

aa = bmod (a, b) > 0Result
2FALSETRUETRUE
3TRUEFALSETRUE
5FALSETRUETRUE
7FALSETRUETRUE
9FALSEFALSEFALSE
11FALSETRUETRUE
13FALSETRUETRUE
15FALSEFALSEFALSE
17FALSETRUETRUE
19FALSETRUETRUE
3 だけを残して、他の 3 の倍数が除去された

残ったのは、

{2; 3; 5; 7; 11; 13; 17; 19}

最後に b = 4 で同様に filter() をするけど、すでに最初の filter() で 2 以外の 2 の倍数は全て取り除いたから、b = 4filter() しても結果は変わらないね。

図解してみたけど… 伝わるだろうか?

理解してから、元の説明文を読んでみる

仕組みを理解した上で、改めて参照元の説明を読んでみて、僕はやっと意味が分かった。なるほど、これは端的な説明ですね…。ちなみに、ここで [指定値] はセル B3 に記入された 40 を使ってます。

まず「SEQUENCE(B3-1,1,2)」つまり 2 から指定値までの整数の集まりに a と名付けています。

また、「SEQUENCE(SQRT(B3)-1,1,2)」つまり 2 から指定値の平方根 (小数切り捨て) まで (結果として 2 から 6 まで) の整数の集まりに b と名付けています。

そして FILTER 関数により、a の中から「b と等しいか b の倍数でない値」を (まず b = 2 の場合について) 抽出し、次の抽出 (次の b = 3 の場合における抽出) における a として渡します。これが b = 6 まで繰り返され、結果的に最初の a の中の素数だけが残ります。ab という命名と、演算結果を順次引き渡して最後の結果だけ出力する部分が REDUCE / LAMBDA 関数の機能です。

なお、FILTER 関数の条件で OR 関数が使えないので + 演算子を用いる必要があります。

(Gスプレッドシート)指定値以下の素数をすべて求める – いきなり答える備忘録

コメントを残す

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

コメントする