I have been reading these forums for a while now and thought I would
give something back to the community. I finished a *very* simple markov
chain name generator in C++. I have no website or any where to post this
code so I hope you guys don't mind. I present this to you as public domain,
no warranties, and there are probably mistakes so you can edit as you wish.
//CWordFrequency.h
#ifndef CWORDFREQUENCY_H_
#define CWORDFREQUENCY_H_
class CWordFrequency
{
private:
int countBeginning;
int countEnd;
int countWithin;
public:
CWordFrequency();
~CWordFrequency();
void incrementCountBeginning();
void incrementCountEnd();
void incrementCountWithin();
int returnCountBeginning();
int returnCountEnd();
int returnCountWithin();
};
#endif
//CWordFrequency.cpp
#include "CWordFrequency.h"
CWordFrequency::CWordFrequency() : countBeginning(0), countEnd(0),
countWithin(0)
{
}
CWordFrequency::~CWordFrequency()
{
}
void CWordFrequency::incrementCountBeginning()
{
++countBeginning;
}
void CWordFrequency::incrementCountEnd()
{
++countEnd;
}
void CWordFrequency::incrementCountWithin()
{
++countWithin;
}
int CWordFrequency::returnCountBeginning()
{
return countBeginning;
}
int CWordFrequency::returnCountEnd()
{
return countEnd;
}
int CWordFrequency::returnCountWithin()
{
return countWithin;
}
//CRandomName.h
#include <fstream>
#include <map>
#include <string>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <algorithm>
#include "CWordFrequency.h"
#ifndef CRANDOMNAME_H_
#define CRANDOMNAME_H_
class CRandomName
{
private:
std::string errorMessage;
std::ifstream *fileStreamIn;
std::ofstream *fileStreamOut;
std::map<char, std::map<char, CWordFrequency> > baseMap;
std::map<char, CWordFrequency> sequenceFrequencyMap;
CWordFrequency tempFrequency;
public:
CRandomName();
~CRandomName();
void inputFile(std::ifstream &streamHandle);
void processFile();
void outputList(std::ofstream &streamHandle);
std::string outputName(double minLength, double maxLength);
};
#endif
//CRandomName.cpp
#include <iostream>
#include "CRandomName.h"
CRandomName::CRandomName()
{
}
CRandomName::~CRandomName()
{
}
void CRandomName::inputFile(std::ifstream &streamHandle)
{
fileStreamIn = &streamHandle;
}
void CRandomName::processFile()
{
std::string word;
char base;
char sequence;
int wordPosition;
while(!fileStreamIn->eof())
{
std::map<char, std::map<char, CWordFrequency> >::iterator itr;
*fileStreamIn >> word;
for (wordPosition = 0 ; (wordPosition + 1) < word.length();
wordPosition++)
{
base = word[wordPosition];
sequence = word[wordPosition + 1];
CWordFrequency &wf = baseMap[base][sequence];
if (wordPosition > 0 && (wordPosition + 1) < (word.length() -
1)) {wf.incrementCountWithin();}
else if (wordPosition == 0) {wf.incrementCountBeginning();}
else if ((wordPosition + 1) == word.length() - 1)
{wf.incrementCountEnd();}
}
}
}
void CRandomName::outputList(std::ofstream &streamHandle)
{
fileStreamOut = &streamHandle;
std::map<char, std::map<char, CWordFrequency> >::iterator itr;
std::map<char, CWordFrequency>::iterator itr2;
for (itr = baseMap.begin() ;itr != baseMap.end(); itr++)
{
sequenceFrequencyMap = itr->second;
for (itr2 = sequenceFrequencyMap.begin() ;itr2 !=
sequenceFrequencyMap.end(); itr2++)
{
tempFrequency = itr2->second;
*fileStreamOut << itr->first << " " << itr2->first << " " <<
tempFrequency.returnCountBeginning() << " " <<
tempFrequency.returnCountWithin() << " " << tempFrequency.returnCountEnd()
<< std::endl;
}
}
}
std::string CRandomName::outputName(double minLength, double maxLength)
{
std::string name;
std::vector<char> freqVector;
double range = static_cast<double>((maxLength - minLength) + 1);
int rangeLength = static_cast<int>(minLength + (range * ((double)rand()
/ (double)(RAND_MAX+1))));
char a = static_cast<char> (65 + (7 * rand() / ( RAND_MAX + 1.0 ))); //
I made this only go to //'G' because I
haven't finished compileing my list of names
name += a;
for(int counter = 1; counter < rangeLength; )
{
int cdc = 0;
if(baseMap.find(a) != baseMap.end())
{
for (char b = 'A'; b <= ('Z'); b++)
{
if(baseMap[a].find(b) != baseMap[a].end())
{
if(counter == 1)
{
for(int cc = 0; cc <
(baseMap[a][b].returnCountBeginning()); cc++)
{
freqVector.push_back(b);
cdc++;
}
}
else if((counter + 1) > (rangeLength - 1))
{
for(int cc = 0; cc < baseMap[a][b].returnCountEnd();
cc++)
{
freqVector.push_back(b);
cdc++;
}
}
else
{
for(int cc = 0; cc < baseMap[a][b].returnCountWithin();
cc++)
{
freqVector.push_back(b);
cdc++;
}
}
}
}
}
std::random_shuffle(freqVector.begin(), freqVector.end());
std::random_shuffle(freqVector.begin(), freqVector.end());
std::random_shuffle(freqVector.begin(), freqVector.end());
int c = (int)(((cdc) * rand() / ( RAND_MAX + 1.0 )));
name += freqVector.at(c);
a = freqVector.at(c);
counter++;
}
return name;
}
Have you seen the stuff about Markov chains on RL dev dot org and Hajo's
site?
--
ABCGi - ab...@yahoo.com
RL LINKS:
http://codemonkey.sunsite.dk/projects/beyond/beyondrelatedlinks_20041117.html
> Hello,
>
> I have been reading these forums for a while now and thought I would
> give something back to the community. I finished a *very* simple markov
> chain name generator in C++. I have no website or any where to post this
> code so I hope you guys don't mind. I present this to you as public domain,
> no warranties, and there are probably mistakes so you can edit as you wish.
>
> //CWordFrequency.h
>
> #ifndef CWORDFREQUENCY_H_
> #define CWORDFREQUENCY_H_
>
> class CWordFrequency
> {
> //...
>
> public:
> CWordFrequency();
> ~CWordFrequency();
Just a nit: Without a fairly good reason not to, and comments supporting
it in the code, best practice is to make destructors virtual.
Thanks for the contribution.
G
--
Change account to gw when responding by mail.
I couldn't find any markov information on hajo's site, but I remember
seeing it on rldev.org. Maybe I'll clean up the code and submit it to these
sites.
I recall a big thread over a year ago discussing Markov's and all that,
just wondering if you'd seen that and the fruits of it's threadiness on
various sites.
My recollection of where they were may be hazy...