Posted at

D言語で無駄に汎用的なズンドコキヨシを作る


始めに

今回急いで作成したため、ミスがあるかもしれません。

ご了承ください。


概要


  • 文字列だけではなくあらゆる型のズンドコキヨシに対応する。

  • D言語の特性を生かして汎用性を高めるためrangeで作成する

  • 契約プログラミングを使う

  • 出現確率を指定できるようにする。

  • 丸め誤差を避けるため比を使う(確率を使うと誤差の関係上合計値が1にならない可能性があるため)

  • testを行う


ソースコード

import std.stdio;

import std.algorithm.iteration;
import std.random;
import std.exception ;

struct fractions{
private ulong[] molecule;
private Random rnd;

this(ulong[] m)
body{
molecule=m.dup;
rnd=Random(unpredictableSeed);
}

private ulong sum_m(){
return sum(molecule);
}

ulong select(){
ulong d1=sum_m();

ulong temp=uniform(0,d1, rnd);

ulong sum_n=0;

foreach(i,e;molecule){
if(sum_n<=temp&&temp<sum_n+e){
return i;
}

sum_n+=e;
}

throw new Exception("内部バグです");

return -1;
}

@property ulong length(){
return molecule.length;
}
}

class zundoko(T){
private T[] data;
private fractions prob;

this(T[] d,fractions p)
in{
assert(d.length==p.length);
}
body{
data=d.dup;
prob=p;
}

@property T front() {
return data[prob.select()];
}

@property T[] front(ulong n) {
T[] A;
A.length=n;
foreach(i;0..n){
if(empty())
throw new Exception("要求された量front出来ませんでした");
A[i]=front;
}

return A;
}

void popFront() {
}

bool empty() {
return false;
}
}

T3 Run_func(T,T2,T3)(T v,T2[] ok,T3 ok_data){
while(!v.empty) {
if(v.front(ok.length)==ok)
return ok_data;
}
//ERROR
throw new Exception("マッチしませんでした");
}

unittest{
auto zundoko_data=new zundoko!(string)(["ズン","ドコ"],fractions([1,1]));
assert(zundoko_data.Run_func!(zundoko!string,string,string)(["ズン","ズン","ズン","ズン","ドコ"],"キ・ヨ・シ!")=="キ・ヨ・シ!");
zundoko_data=new zundoko!(string)(["ズン","ドコ"],fractions([3,2]));
assert(zundoko_data.Run_func!(zundoko!string,string,string)(["ズン","ズン","ズン","ズン","ドコ"],"キ・ヨ・シ!")=="キ・ヨ・シ!");
zundoko_data=new zundoko!(string)(["ズン","ドコ"],fractions([10,1]));
assert(zundoko_data.Run_func!(zundoko!string,string,string)(["ズン","ズン","ズン","ズン","ドコ"],"キ・ヨ・シ!")=="キ・ヨ・シ!");
}

void main()
{
auto zundoko_data=new zundoko!(string)(["ズン","ドコ"],fractions([4,1]));
writeln(zundoko_data.Run_func!(zundoko!string,string,string)(["ズン","ズン","ズン","ズン","ドコ"],"キ・ヨ・シ!"));
}


出力

キ・ヨ・シ!


しかし、このクラスだと動的に確率を変えたりすることは出来ません。

そういった意味ではまだ完全な汎用性には程遠いと思われます。

あと、出現確率の計算が間違っている可能性があります。


最後に

D言語は便利な機能が多いですね。