3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

jqのむだづかいー階乗再帰篇

Last updated at Posted at 2022-09-20

JSON処理のコマンドラインツールであるjqは、JSONテキストを1行でちゃくっと解析、変換するときに使うものです。正統的なプログラミング言語ではないので、これでアルゴリズムの学習をすることはまずありません。

とは言え、jqにも変数定義などプログラミング言語らしき機能が備わっているので、「やればできんじゃねぇ」と野望を募らせてしまうこともあります。

今日のお題は、アルゴリズムの教本には必ず出てくる再帰です。ここでは階乗(factorial)を実装します。

Python

Pythonだったら、こう書くでしょう。

#!/usr/bin/env python

from sys import argv

def factorial(n):
    if n == 0 or n == 1:
        return 1
    else:
        return n * factorial(n-1)


if __name__ == '__main__':
    n = int(argv[1])
    print(factorial(n))

この再帰は、与えられたnから逆順に計算していきます。つまり、最初はn * factorial(n-1)、次にn-1 * factorial(n-2)と順に下がっていき、最後にn1のときに1! = 1を返します。教科書通りです。

n=20のときの実行結果は次の通りです。

$ ./factorial.py 20
2432902008176640000

jq

jqも同じようにコーディングするだけです。ただ、Pythonでは関数引数だったnは入力.で扱います。関数呼び出しをしなければならないので、関数で定義します。

def factorial:
    tonumber |
    if . == 0 or . == 1 then
        .
    else
        . * (. - 1| factorial)
    end;

elseブロックでは、n-1を関数に入力するのに、. - 1 | factorialとパイプを使わなければならないので、Pythonよりは読みにくくなっています。でも、構成は同じです。

関数定義は宣言のdefに続いて関数名、シグニチャを区切るコロン:で始まり、以下コードブロックです。関数末尾(ここではend)にはセミコロン;で終了を明示的に示します。

関数を用意したファイルをfactorial.jqとして、これを読み込むにはinclude "factorial";をフィルタに記述します。ファイル拡張子はjqであることが期待されており、インクルードするときにはこれを外します。ここも、セミコロンで終端します。

n=20のときの実行結果は次の通りです。

$ jq -n 'include "factorial"; 20 | factorial'
2432902008176640000

同じ結果が得られました。即値の20より前にincludeを書くのがポイントです。

おわりに

最初は半信半疑でしたが、再帰も、やればできるもんです。すごいですね、jq

参考

表紙

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?