Edited at
D言語Day 9

小物づくりからはじめるD言語入門


まえがき

新しい言語を学び始めたきっかけ、覚えてますか?

この記事では「小物(さいころ)を作って満足する」という視点から,D言語の紹介記事のようなサムシングをこしらえてみました。


下準備

Home D Programming language

https://dlang.org/

大体なんでもあります。公式の入門記事(日本語訳版あり)もあります。

編集の際は文字コードがUTF-8であることを確認してください。文字コードが違った場合の動作の保証は致しかねます。

改行コードは気にしなくても大丈夫だと思います。


実際にさいころを作る


さいころ?

さっそくサイコロを作ってみます。

まずは数字を std.stdio の write() などで出力してみます。

import std.stdio;

void main(){
writeln(1);
writeln(1);
1.writeln();
}

$ rdmd dice.d

> 1
> 1
> 1

1面ピンじゃねぇか…!通るかっ…!こんなもん…!

一部に需要がありそうなサイコロですが、やっぱり変化が欲しいですね。


さいころのようなもの

一面ダイスのみではつまらないので六面ダイスも作りましょう。

std.random の uniform() で乱数(疑似)を生成しましょう。

import std.stdio

import std.random;

void main(){
auto rnd = Random();
uniform( 1, 6+1, rnd ).writeln();
}

$ rdmd dice.d

> 3
$ rdmd dice.d
> 3

こういうのでいいんだよ、こういうので…

…あれ、複数回実行しても結果が変わりませんでした。何か足りないのでしょうか?


よくあるさいころ

前回のコードでは シード値を与えていませんでした。

今回は 現在時刻をUnixTimeに直したものを シード値とするように変更してみます。

これで(ほぼ)毎回変わるサイコロになるはずです。

import std.stdio;

import std.random;
import std.datetime.systime;

void main(){
auto rnd = Random(Clock.currTime().toUnixTime());
// auto rnd = Random(unpredictableSeed()); // このコードもOK
uniform( 1, 6+1, rnd ).writeln();
}

$ rdmd dice.d

> 5
$ rdmd dice.d
> 4
$ rdmd dice.d
> 2

よかった、これで解決ですね。

…これなら普通にさいころをふれば良いのでは?


無限の可能性を持つさいころ

ここからがプログラミングの本番です。

プログラムで標準入力から数字を受け取り、任意の面数であるサイコロにします。

(引数で受けとる方法もありますが、競技プログラミングでも活かせそうなこちらの手法を使用します)

(2018/12/15 @tm_tn さんより頂いた情報で、std.datetime.systime を使わないコードに書き直しました,thanks!)

import std.stdio;

import std.random;
import std.conv, std.string;

void main(){
auto rnd = Random(unpredictableSeed());
auto n = readln().chomp().to!size_t();
uniform( 1, n+1, rnd ).writeln();
}

$ rdmd dice.d

> 10 (input)
> 6

これでコイントスも正二十面体ダイスも、一つのコードで完結します。素晴らしい!

一つ一つ真心を込めてさいころをふっているので、数字に温かみがあります。(ありません)


100万回ふれたさいころ

サイコロの個数分プログラムを動かすのは面倒に感じます。

せっかくなので、一度の入力でたくさんのサイコロを振れるようにします。

import std.stdio;

import std.random;
import std.conv, std.string;

void main(){
auto rnd = Random(unpredictableSeed());
auto list = readln().chomp().split("d");
size_t sum;

if ( list.length == 1 ){
sum = uniform( 1, list[0].to!size_t()+1, rnd );
} else if( list.length == 2 ) {

foreach( i ; 0..list[0].to!size_t() ){
sum += uniform( 1, list[1].to!size_t()+1, rnd );
}
}
sum.writeln();
}

$ rdmd dice.d

> 1000000d64 (input)
> 32510601

ここまでくると「パワーワード」ならぬ「パワーナンバー」ですね。

工夫の余地はまだまだありますが、コードが複雑になってきたので ここでお開きにします。


最後に

小物づくりから一つの記事をこしらえてみました、皆様の暇つぶしになれば幸いです。