Random sentence generator

Thanks to the participants in the C++ shame corner

This recursive text generator opens a file and prints out a random line, character by character, until a <> bracket instructs it to start or stop reading another filename.

So give it a text file “my awesome list.txt” and it chooses one line. If the line has a <token>, it will look for a file named “token” and open THAT list before returning.

With a sturdy PRNG, this is an excellent (simple) list picker for random names, restaurants, decisions, fortune telling, boilerplate text, nonsense, artistic filler and inspiration, encounters, loot etc. :+1: :+1: :+1:

The format is so clean and intuitive, any given list like this (I just searched that up) will work just fine with no processing on your end.

Windows command line only. :drudgesiren:

Try it yourself! I also copied the code below if you prefer to stay on-site and scoff.

code dump
//A multi-file variant on the classic Zelenski RSG (Random Sentence Generator),
//chooses a random line from a file and recursively replaces <bracketed filenames>.

#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include "random.h"
//Thanks to: https://github.com/effolkronium/random
#include "argh.h"
//Thanks to: https://github.com/adishavit/argh


using namespace std;
using Random = effolkronium::random_static;

ifstream loadfile(string filename)
{
	//Load the file
	ifstream file(filename);
	//...or die trying
	if (!file)
	{
		cout << "Can't open " + filename + "!\n";
		exit(0);
	}

	return file;
}

struct RSG {

	string pickRandom(vector<string> infixes)
	{
		//Count how many lines we copied. Cast size_type to integer.
		int count = static_cast<int>(infixes.size());

		//Choose random element.
		int choice = Random::get<int>(0, count - 1);

		return infixes[choice];
	}

	string replaceBrackets(string directory, string infix)
	{
		bool replacing = false;
		string temptag, result = "";

		int count = static_cast<int>(infix.size());

		do {
			for (int c = 0; c < count; c++) {
				if (!replacing)
				{
					if (infix[c] == '<')
					{
						replacing = true;
					}
					else
					{
						result += infix[c];
					}
				}
				else
				{
					if (infix[c] == '>') {
						replacing = false;
						temptag = expand(directory, temptag);
						result += temptag;
						temptag = "";
					}
					else
					{
						temptag += infix[c];
					}
				}
			}

		} while (result.find('<') != std::string::npos);

		return result;
	}

	string expand(string directory, string filename)
	{
		ifstream file = loadfile(directory + filename);

		//Copy each line into vector of strings
		vector<string> strings;
		string line;

		while (getline(file, line))
		{
			strings.push_back(line);
		}

		/*Pull random line*/
		line = pickRandom(strings);
		/*Process lines recursively and return*/
		return replaceBrackets(directory, line);
	}

};

//Directory parsing garbage
string directory(string filename) {
	string filename_directory = filename.substr(0, filename.find_last_of('\\') + 1);
	//cout << filename_directory << "\n";
	return filename_directory;
}
string onlyfile(string filename) {
	string filename_end = filename.substr(filename.find_last_of('\\') + 1, filename.length() - 1);
	//cout << filename_end << "\n";
	return filename_end;
}


int main(int argc, char* argv[])
{
	//Step 1. Determine parameters

	argh::parser arguments(argc, argv, argh::parser::PREFER_PARAM_FOR_UNREG_OPTION);

	string filename, outfilename, outcount;
	arguments(1) >> filename;

	bool append = true;
	if (!arguments[{ "-a", "--append" }])
	{
		append = false;
	}
	
	arguments({ "-c", "--count" },1) >> outcount;

	//Directory parsing garbage
	string filename_directory = "";
	string filename_end = filename;
	if (filename.find('\\') != string::npos)
	{
		filename_directory = directory(filename);
		filename_end = onlyfile(filename);
	}

	//Step 2. Load first file into the first recursive function and get the ball rolling
	ifstream file = loadfile(filename);

	RSG rsg;
	for (int i = 0; i < stoi(outcount); i++) {

		string line = rsg.expand(filename_directory, filename_end); //Expands recursively. Be careful!

		//Output to cout
		cout << line << "\n";

		//Output to file(s)
		ofstream outfile;

		if (arguments({ "-o", "--output" }) >> outfilename)
		{
			if (append)
				outfile.open(outfilename, ios::app);
			else
				outfile.open(outfilename + "-" + to_string(i));
			outfile << line << "\n";
		}

	}

	return 0;

}
6 Likes

Ooh, I remember doing a school project very similar to this about a decade ago. It was really fun to play around with!

1 Like

nice, is it on github?

post can’t be empty

Thanks, I am bad at clicking