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

整数 $a$, $b$, $c$ は 1 以上 1,000 以下でる。

# 今回用いる V の言語仕様

:::note info
V のドキュメントには [HTML 版](https://docs.vlang.io/introduction.html)もあるが、これは執筆時点で

* ソースコードなど、なぜか**コピーできない部分がある**
* 記述する文字列そのままではなく、**特殊な表示**をされる演算子がある

という**不親切設計**になっている。
このため、GitHub に載っている [V Documentation](https://github.com/vlang/v/blob/master/doc/docs.md) を参照することを推奨する。
:::

## 関数定義

[Hello World](https://github.com/vlang/v/blob/master/doc/docs.md#hello-world)
[Functions](https://github.com/vlang/v/blob/master/doc/docs.md#functions)

```
fn 関数名(引数) 返り値の型 {
	関数の処理内容
}
```

の形式で、関数を定義できる。
「返り値の型」は、返り値を返さない関数では省略できる。

```
return 値
```

により、関数から値を返すことができる。

以下のように `main` 関数を定義すると、プログラムの実行開始時に実行してくれる。

```
fn main() {
	処理内容
}
```

`main` 関数を作らず、トップレベルで直接処理内容を書いてもよい。

## 変数とリテラル

[Variables](https://github.com/vlang/v/blob/master/doc/docs.md#variables)
[V Types](https://github.com/vlang/v/blob/master/doc/docs.md#v-types)

```
変数名 := 値
```

の形式で、値を変更できない変数を定義できる。

```
mut 変数名 := 初期値
```

の形式で、値を変更できる変数を定義できる。

これらの変数定義において、変数の型は(初期)値の型になる。

`型(値)` の形式で、「値」を「型」に変換できる。

整数リテラルは、`72` のような形式の十進数や、`0x72` のような形式の十六進数などを用いることが出来る。型は `int` (32ビット符号付き整数) である。

文字列リテラルは、`'hoge'` のように `'` で囲む。型は `string` である。

文字リテラルは、`` `a` `` のように `` ` `` で囲む。型は `rune` (32ビット符号なし整数) である。

## 演算子

[Appendix II: Operators](https://github.com/vlang/v/blob/master/doc/docs.md#appendix-ii-operators)

詳細は省略するが、だいたいC言語に近い演算子を用いることができる。

## フロー制御

[If](https://github.com/vlang/v/blob/master/doc/docs.md#if)
[For loop](https://github.com/vlang/v/blob/master/doc/docs.md#for-loop)

```
if 条件式 {
	条件式が真の場合に実行する処理
} else {
	条件式が偽の場合に実行する処理
}
```

の形式で、条件分岐ができる。

```
if 条件式 {
	条件式が真の場合に実行する処理
}
```

だけでも使える。

```
for {
	処理内容
}
```

で、「処理内容」を無限に繰り返し実行できる。
繰り返す条件や範囲を指定することもできるが、今回は使用しないので省略する。

```
break
```

により、ループから抜けることができる。

## 出力

[Builtin functions](https://github.com/vlang/v/blob/master/doc/docs.md#builtin-functions)
[Strings](https://github.com/vlang/v/blob/master/doc/docs.md#strings)

```
print(値)
```

(`print` 関数) により、「値」を標準出力に出力できる。

```
println(値)
```

(`println` 関数) により、「値」と改行文字を標準出力に出力できる。

文字コードを `u8` 型に変換し、さらに `ascii_str` 関数を用いることで、文字コードに対応する文字を取得できる。
これを `print` 関数や `println` 関数に渡すことで、文字を出力できる。

```
ch := 0x21
print(u8(ch).ascii_str())
```

## 入力

[Calling C from V](https://github.com/vlang/v/blob/master/doc/docs.md#calling-c-from-v)

V の組み込み関数に入力を読み込むものは無いが、V ではC言語の関数を呼び出すことができる。
関数名の先頭に `C.` をつけ、引数や戻り値の型を含めて宣言することで、そのC言語の関数を使えるようになる。
たとえば、以下のように宣言して `getchar` 関数を使用できる。

```
fn C.getchar() int
```

# 提出コード

```
fn C.getchar() int

fn read_int() int {
	mut value := 0
	for {
		c := C.getchar()
		if int(`0`) <= c && c <= int(`9`) {
			value = value * 10 + c - int(`0`)
		} else {
			break
		}
	}
	return value
}

fn main() {
	a := read_int()
	b := read_int()
	c := read_int()
	print(a + b + c)
	print(' ')
	for {
		ch := C.getchar()
		print(u8(ch).ascii_str())
		if ch == int(`\n`) {
			break
		}
	}
	println('')
}
```

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