Range
dlang
D言語
ズンドコキヨシ

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言語は便利な機能が多いですね。