0
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?

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

Welcome to AtCoder

PracticeA - Welcome to AtCoder

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

a
b c
s

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

sum s

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

今回用いる Zig の機能

Documentation - The Zig Programming Language

関数定義

Hello World
Functions

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

の形式で関数を定義できる。

return 値;

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

プログラムの実行開始時に実行される関数は

pub fn main() !void {
    処理内容
}

の形で定義できる。

Primitive Types

今回は以下の型を用いる。

意味
i32 32ビット符号つき整数
u32 32ビット符号なし整数
u8 8ビット符号なし整数

リテラル

Integer Literals
String Literals and Unicode Code Point Literals

整数のリテラルは、十進数 72 や十六進数 0x123 などを用いることができる。
文字列リテラルは、"hello" のように " で囲むことで表現できる。
文字 (文字コード) リテラルは、'a' のように ' で囲む。

条件分岐

if

if (条件式) {
    条件式が真の場合の処理
} else {
    条件式が偽の場合の処理
}
if (条件式) {
    条件式が真の場合の処理
}

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

ループ

while

while (true) {
    処理
}

の形式で、「処理」を無限に繰り返し実行できる。

break;

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

Zig では条件を指定してのループや配列の走査 (for) も使えるが、今回は使用しなかった。

定数と変数

Assignment

const 識別子 = 値;

の形式で、識別子に値を割り当てることができる。(すなわち、定数を定義できる)

var 識別子: 型 = 初期値;

の形式で、変数を定義できる。
変数には以下のように = を用いて値を代入できる。

識別子 = 値;

定数の定義では型を省略しやすいが、変数の定義では型を明示したほうがよさそうである。
たとえば、以下のように型を省略して整数の変数を定義しようとすると、以下のコンパイルエラーになった。

var value = 0;
error: variable of type 'comptime_int' must be const or comptime
    var value = 0;
        ^~~~~
note: to modify this variable at runtime, it must be given an explicit fixed-size number type

演算子

Operators

今回は、以下の演算子を用いた。

演算子 意味
a + b 加算
a - b 減算
a * b 乗算
a == b a と b の値が同じかを判定
a <= b a が b 以下かを判定
a and b 論理AND

特に、論理ANDはC言語では && だが、Zig では and である。

入出力

Hello World
String Literals and Unicode Code Point Literals
Anonymous List Literals
if
Error Union Type
@bitCast
@truncate
std.io
std.fs.File
std.io.Reader
std.io.Writer

入出力は、標準ライブラリを用いて行うことができる。
以下のようにして、標準ライブラリを std として読み込める。

const std = @import("std");

以下のようにすると、標準出力に出力する用の Writer オブジェクト stdout を取得できる。

const stdout = std.io.getStdOut().writer();

この Writerprint メソッドにより、データを出力できる。

try stdout.print(書式指定文字列, .{データリスト});

書式指定文字列では、{d} と書くとデータ(数値)を十進数で出力でき、{c} と書くとデータ(8ビットの数値)を文字として出力できる。

C言語の getchar() が返すように i32 (符号付き32ビット整数) に -1 (EOF) または1バイトを表す 0~255 の整数が格納されているとき、(EOF が入っている可能性は無視して) この1バイトを出力するのは以下のようにできる。

  1. @bitCast により、i32 のデータを同じバイト列で表される u32 (符号なし32ビット整数) に変換する
  2. @truncate により、整数の上位ビットを切り捨てて u8 に変換する
  3. 変換した値を出力する
const ch: i32 = 0x30;
try stdout.print("{c}", .{@truncate(u8, @bitCast(u32, ch))});

@bitCast および @truncate は、現在最新の 0.13.0 では引数を1個だけとり、変換先の型は変換結果を使う側が受け入れる型によって決まる。
しかし、AtCoder で用いられる 0.10.1 では引数を2個とり、変換先の型を明示する。

以下のようにすることで、標準入力から1バイト読み込み、数値として取得できる。

fn readChar() i32 {
    const stdin = std.io.getStdIn().reader();
    const c = stdin.readByte();
    if (c) |value| {
      return value;
    } else |_| {
      return -1;
    }
}

まず、std.io.getStdIn().reader() により読み込み用のオブジェクトを取得する。
次に、stdin.readByte() によりこのオブジェクトを用いて1バイト読み込む。
これは NoEofError!u8 という型のデータを返す。
この型は、エラーのデータと通常のデータが重ね合わせになっているので、if 文を用いて分離する。

提出コード

const std = @import("std");

fn readChar() i32 {
    const stdin = std.io.getStdIn().reader();
    const c = stdin.readByte();
    if (c) |value| {
      return value;
    } else |_| {
      return -1;
    }
}

fn readInt() i32 {
    var value: i32 = 0;
    while (true) {
        const c = readChar();
        if ('0' <= c and c <= '9') {
            value = value * 10 + c - '0';
        } else {
            return value;
        }
    }
}

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    const a = readInt();
    const b = readInt();
    const c = readInt();
    try stdout.print("{d} ", .{a + b + c});
    while (true) {
        const ch = readChar();
        try stdout.print("{c}", .{@truncate(u8, @bitCast(u32, ch))});
        if (ch == '\n') {
            break;
        }
    }
}

提出 #54529743 - AtCoder Beginners Selection

0
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
0
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?