Ada で 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
```

# 今回用いた Ada の機能

[Ada Reference Manual, 2022 Edition](https://www.adaic.org/resources/add_content/standards/22rm/rm-final.pdf)
[Ada について話します #Ada - Qiita](https://qiita.com/mshioda/items/0356659738708d2c936c)
[Wikipedia に載っているコード例](https://ja.wikipedia.org/wiki/Ada#%E3%82%B3%E3%83%BC%E3%83%89%E4%BE%8B)も参考になる。

## プログラムの構造

関連する仕様書の部分：

* 6.1 Subprogram Declarations
* 6.3 Subprogram Bodies

Ada のプログラムは、以下の構造で書くことができる。

```ada
with 使用するパッケージ;

procedure プログラム名 is
   変数宣言
begin
   処理内容
end プログラム名;
```

プログラム名は、上下で合わせなければならない。
(下のプログラム名は省略することもできる)
ファイル名とも合わせることが推奨されるが、AtCoder の環境では

> Main.adb:3:11: warning: file name does not match unit name, should be "main.adb" [enabled by default]

となってしまい、合わせることはできなそうである。

インデントは、**空白3個**を用いるのが慣例のようである。

## 変数の宣言

関連する仕様書の部分：

* 3.1 Declarations
* 3.3.1 Object Declarations
* 3.5.2 Character Types
* 3.5.4 Integer Types
* 3.11 Declarative Parts

変数の宣言は、上記プログラムの構造の「変数宣言」の部分で、以下のように行うことができる。

```ada
変数名 : 型名;
```

変数名は、カンマで区切って複数宣言できる。
型名は、整数を表す `Integer`、文字を表す `Character` などが使用可能である。

このような変数宣言は、仕様書では `basic_declaration` の一種である `object_declaration` として定義されている。
`basic_declaration` は、「変数宣言」にあたる `declarative_part` に置ける要素の一種である。

## 数値・文字・文字列

関連する仕様書の部分：

* 2.1 Character Set
* 2.4.1 Decimal Literals
* 2.5 Character Literals
* 2.6 String Literals
* A.3.3 The Package Characters.Latin\_1

数値リテラル (十進数) は、`0`、`72` などのように数字を1個以上並べることで表現できる。

文字リテラルは、`' '` のように1文字を `''` で囲うことで表現できる。

文字列リテラルは、`" "` のように文字列を `""` で囲うことで表現できる。

なお、文字リテラルや文字列リテラルで用いることができる文字は `graphic_character` に限られ、改行文字 (`format_effector` に分類される) などは用いることができない。
改行文字 `Ada.Characters.Latin_1.LF` を含む制御文字は、パッケージ `Ada.Characters.Latin_1` で定義されている。

## 演算子

関連する仕様書の部分：

* 4.5.2 Relational Operators and Membership Tests
* 4.5.3 Binary Adding Operators

`a + b` で、数値 `a` と `b` を加算した和を求めることができる。

`a /= b` で、`a` と `b` が等しくないかを表す論理値を求めることができる。

## ループ

関連する仕様書の部分：

* 5.5 Loop Statements

以下のようにすることで、「条件」を満たす間「処理内容」を繰り返し実行することができる。

```ada
while 条件 loop
   処理内容
end loop;
```

## 標準入出力

関連する仕様書の部分：

* A.7 External Files and File Objects
* A.10.1 The Package Text_IO
* A.10.5 Operations on Columns, Lines, and Pages
* A.10.7 Input-Output of Characters and Strings
* A.10.8 Input-Output for Integer Types

`Ada.Text_IO` パッケージにより文字や文字列の入出力を、`Ada.Integer_Text_IO` パッケージにより数値の入出力を行うことができる。
`Ada.Integer_Text_IO` は、ジェネリック型 `Ada.Text_IO.Integer_IO` に型 `Integer` を指定したものである。

以下により、文字や文字列を標準出力に出力することができる。

```ada
Ada.Text_IO.Put(値);
```

以下により、改行を標準出力に出力することができる。
AtCoder の環境ではこれを用いなくても出力後 (プログラムの終了時？) 自動で改行が出力されるようだったが、仕様書ではプログラムの終了時の動作は定義しない、となっているので、明示的に出力を行ったほうがいいだろう。

```ada
Ada.Text_IO.New_Line;
```

以下により、標準入力から**改行文字を読み飛ばして**1文字読み込むことができる。

```ada
Ada.Text_IO.Get(読み込み先の変数);
```

以下により、標準入力から**改行文字を含む**1文字を読み込むことができる。

```ada
Ada.Text_IO.Get_Immediate(読み込み先の変数);
```

以下により、数値を余計な空白なしで標準出力に出力することができる。

```ada
Ada.Integer_Text_IO.Put(値, 0);
```

以下により、標準入力から数値を読み込むことができる。

```ada
Ada.Integer_Text_IO.Get(読み込み先の変数);
```

# 提出コード

```ada
with Ada.Text_IO, Ada.Integer_Text_IO, Ada.Characters.Latin_1;

procedure Main is
   A, B, C : Integer;
   S : Character;
begin
   Ada.Integer_Text_IO.Get(A);
   Ada.Integer_Text_IO.Get(B);
   Ada.Integer_Text_IO.Get(C);
   Ada.Integer_Text_IO.Put(A + B + C, 0);
   Ada.Text_IO.Put(" ");
   Ada.Text_IO.Get(S);
   while S /= Ada.Characters.Latin_1.LF loop
      Ada.Text_IO.Put(S);
      Ada.Text_IO.Get_Immediate(S);
   end loop;
   Ada.Text_IO.New_Line;
end Main;
```

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