感想文ランダム生成 ソース (旧版)

ついでにコードも載せとく。

mc.h

  • ツリー状のデータで文字のつながりを表現。
  • 次に来る可能性のある文字を「子供」と呼ぶ
  • 末っ子へのポインタと、直上の兄/姉へのポインタがあれば家系図を表現できる
class MCDat
{
  public:
  int val; //文字の番号
  int hist; //発生頻度
  int chist; //Σ子供の発生頻度
  class MCDat *child; //末っ子へのポインタ
  class MCDat *next;  //直上の兄/姉へのポインタ

  MCDat(int c0);
  
  class MCDat *find_child(int c0); //文字c0 の子供へのポインタ。ないならNULL
  class MCDat *add_child(int c0);  //文字c0 の子供を末っ子に追加
  class MCDat *random_child();     //記録された頻度を元に子供を選ぶ
};

mc.cc

#include <stdlib.h>
#include "mc.h"

MCDat::MCDat(int c0)
{
    val = c0;
    hist = 0;
    chist = 0;
    child = NULL;
    next = NULL;
}

MCDat *MCDat::find_child(int c0)
{
    MCDat *p = child;

    while(p!=NULL)
    {
	if (p->val == c0) break;
	p = p->next;
    }
    return p;
}

MCDat *MCDat::add_child(int c0)
{
    MCDat *p = find_child(c0);
    if (!p)
    {
	p=new MCDat(c0);
	p->next = child;
	child = p;
    }
    chist++;
    p->hist++;
    return p;
}

MCDat *MCDat::random_child()
{
    MCDat *p;
    double r0 = rand()*1.0/RAND_MAX;
    int r = (int)(r0 * chist);

    for (p=child;p!=NULL;p=p->next)
    {
	r -= p->hist;
	if (r<=0) break;
    }
    return p;
}

四文字前まで参考にするコード、サンプル読み込みフェーズ

    MCDat *p1, *p2, *p3, *p4, *root;
    root = new MCDat(0);
    p1=p2=p3=p4 = NULL;

    while(1)
    {
	unsigned char *c = buf;
	fgets((char *)buf,10000, fp);
	if(feof(fp))break;

	while(1)
	{
	    int c0 = getwchar(&c);
	    if (c0 == -1) break;

	    if(p4) p4->add_child(c0);      //ツリー第五世代
	    if(p3) p4 = p3->add_child(c0); //ツリー第四世代
	    if(p2) p3 = p2->add_child(c0); //ツリー第三世代
	    if(p1) p2 = p1->add_child(c0); //ツリー第二世代
            p1 = root->add_child(c0);      //ツリー第一世代

	    if (c0 == kidxs("。") ||
		c0 == kidxs(".") ||
		c0 == kidxs("?") )
	    {
		//Terminate chain
		p1=p2=p3=p4=NULL;
	    }
	}//buf
    }

表示フェーズ

    for(i=0;i<100;i++)
    {
	double r=1.0*rand()/RAND_MAX;
	int ri = (int)(tophist_sum*r);
	int c0 = 0;
        while(c0<kmax)
	{
	    ri -= tophist[c0];
	    if (ri<=0)break;
	    c0++;
	}
	prtkidx(c0);
        p1 = root->find_child(c0);
	p2 = p3 = p4 = NULL;

	while(1)
	{
	    MCDat *p;
	    if (p4) 
		p = p4->random_child();
	    else if (p3) 
		p = p3->random_child();
	    else if (p2) 
		p = p2->random_child();
	    else if (p1)
		p = p1->random_child();
	    else
		break;
	    if (!p) break;
	    c0 = p->val;
            prtkidx(c0);

	    if (p3) p4 = p3->find_child(c0);
	    if (p2) p3 = p2->find_child(c0);
	    if (p1) p2 = p1->find_child(c0);
	    p1 = root->find_child(c0);
	}	
	putchar(10);
    }