jq で Welcome to AtCoder を解いてみた

[Qiita Engineer Festa 2024（キータ・エンジニア・フェスタ 2024） - Qiita](https://qiita.com/official-campaigns/engineer-festa/2024)
において、約1ヶ月で38記事という大量の記事の投稿を要求されることがわかった。
そこで、あまりコストをかけずに記事数を稼ぐ方法を考えた結果、「Welcome to AtCoder を様々な言語で解く」ことを思いついた。
単に解くだけでなく、使用する言語仕様の解説を入れれば、記事として一応成立するだろう。

# Welcome to AtCoder

[PracticeA - Welcome to AtCoder](https://atcoder.jp/contests/abs/tasks/practice_1)

Welcome to AtCoder では、以下の形式で整数 $a$, $b$, $c$ および文字列 $s$ が入力として与えられる。

```text
a
b c
s
```

この入力をもとに、与えられた整数の和 $sum = a + b + c$ および文字列 $s$ を、以下の形式で出力することが求められる。

```text
sum s
```

# 今回用いる jq の機能

[jq 1.6 Manual](https://jqlang.github.io/jq/manual/v1.6/)

## コマンドラインオプション

[ルール - AtCoder Beginners Selection](https://atcoder.jp/contests/abs/rules)
を参照すると、AtCoder における jq はコマンドラインオプション `-MrRs` を指定して実行されることがわかる。
これらのオプションは、それぞれ以下の意味である。

|オプション|意味|
|:-:|---|
|`-M`|出力に色をつけない|
|`-r`|文字列を出力する際、JSON形式でクォートせずそのまま出力する|
|`-R`|入力をJSONとしてパースせず、文字列として解釈する|
|`-s`|フィルタを入力の行ごとに実行せず、全体に対して一度実行する|

すなわち、

* 入力全体を一度に処理する
* 余計な加工はせず、入力を文字列として受け取り、文字列はそのまま出力する

という設定になっていることがわかる。
また、「`-r` と同様の動作をするが、結果の出力後に改行を出力しない」オプション `-j` が存在することから、逆に AtCoder で使われているオプション `-r` は結果の出力後に自動で改行を出力すると推測できる。

## フィルタ

jq では、入力を「フィルタ」で処理することにより加工し、出力を生成する。
一つまたは複数のフィルタを受け取り、それを用いた新たなフィルタを構築する構文もある。

### 要素の取り出し `.[添字]`

[`.[添字]`](https://jqlang.github.io/jq/manual/v1.6/#array-index) は、配列を入力として受け取り、「添字」で指定する要素を出力するフィルタである。

### 部分列の取り出し `.[開始点:終了点]`

[`.[開始点:終了点]`](https://jqlang.github.io/jq/manual/v1.6/#array-string-slice) は、配列を入力として受け取り、添字が「開始点」以上「終了点」未満の部分を切り出した配列を出力するフィルタである。
また、文字列を入力として受け取り、同様に部分文字列を出力することもできる。

### 文字列の数値への変換 `tonumber`

[`tonumber`](https://jqlang.github.io/jq/manual/v1.6/#tonumber) は、文字列を入力として受け取り、それが表す数値を出力するフィルタである。
数値が入力された場合は、それをそのまま出力する。

### 文字列の分割 `split(正規表現; フラグ)`

[`split(正規表現; フラグ)`](https://jqlang.github.io/jq/manual/v1.6/#split-2) は、文字列を入力として受け取り、それを「正規表現」にマッチする場所で区切った結果の (文字列を要素とする) 配列を出力するフィルタである。

### 配列の文字列化 `join(文字列)`

[`join(文字列)`](https://jqlang.github.io/jq/manual/v1.6/#join) は、配列を入力として受け取り、その要素を「文字列」を区切りとして結合した文字列を出力するフィルタである。

### 加算 `左辺 + 右辺`

[`左辺 + 右辺`](https://jqlang.github.io/jq/manual/v1.6/#addition) は、以下の動作をするフィルタである。

1. 全体の入力を「左辺」のフィルタと「右辺」のフィルタそれぞれで入力として処理する
2. 「左辺」のフィルタの出力に「右辺」のフィルタの出力を「加算」した結果を全体の出力とする

「加算」とは、数値なら足し算、文字列なら結合、などである。

### パイプ `左辺 | 右辺`

[`左辺 | 右辺`](https://jqlang.github.io/jq/manual/v1.6/#pipe) は、以下の動作をするフィルタである。

1. 全体の入力を「左辺」のフィルタの入力として処理する
2. その出力を「右辺」のフィルタの入力として処理する
3. その出力を全体の出力とする

### 列の結合 `左辺 , 右辺`

[`左辺 , 右辺`](https://jqlang.github.io/jq/manual/v1.6/#comma) は、以下の動作をするフィルタである。

1. 全体の入力を「左辺」のフィルタと「右辺」のフィルタそれぞれで入力として処理する
2. 「左辺」のフィルタの出力(列)の次に「右辺」のフィルタの出力(列)を結合した列を全体の出力とする

### 配列化 `[フィルタ]`

[`[フィルタ]`](https://jqlang.github.io/jq/manual/v1.6/#array-construction) は、以下の動作をするフィルタである。

1. 全体の入力を「フィルタ」で入力として処理する
2. その出力(列)を要素とする1個の配列を全体の出力とする

すなわち、**複数の値**からなるデータを、それらを複数の**要素**として格納した配列という**1個の値**からなるデータに変換する。
たとえば、前述の `左辺 , 右辺` と組み合わせて `[左辺 , 右辺]` とすることで、「左辺」の出力と「右辺」の出力を要素としてもつ配列を生成できる。

### 配列の各要素の処理 `map(フィルタ)`

[`map(フィルタ)`](https://jqlang.github.io/jq/manual/v1.6/#map-map_values) は、配列を入力として受け取り、その配列の各要素を「フィルタ」の入力として処理した結果 (出力) を同じ順で格納した配列を出力とするフィルタである。

# 提出コード

```
split("[ \n]"; "") | [(.[0:3] | map(tonumber) | .[0] + .[1] + .[2]), .[3] ] | join(" ")
```

[提出 #54742931 - AtCoder Beginners Selection](https://atcoder.jp/contests/abs/submissions/54742931)