Jump to content
Banner by ~ Wizard

General Chat Thread


Apple      Bloom

Recommended Posts

1 minute ago, Ganaram Inukshuk said:

I haven't watched Pokéderp in forever...

I've never seen it


We have two ears and one mouth, so we should listen more than we say.

Link to comment
Share on other sites

19 minutes ago, Olly said:

<Content redacted to prevent theft>

OK, I won't.

Also, is it cruel to write about a story where the main character's family dies in a fire?

Also, it it cruel to feed that story into my new-and-improved Markov Text Generator?

#ifndef MARKOV_TEXT_GENERATOR_H_
#define MARKOV_TEXT_GENERATOR_H_

// Markov Text Generator
// This is an improved version of the old MTG, except it has two modes:
// - Character mode
// - Word mode

// Other changes:
// - Vectorstrings are used as intermediaries; for example, when a sentence
//   is made, it isn't made using a loop and string concatenation; instead,
//   it gets put into a vectorstring, and then the vectorstring is looped
//   separately to construct the sentence

#include <vector>
#include <string>
#include <map>      // Includes pair by default
#include <sstream>

class MarkovTextGenerator {
protected:
  // The main data structure looks like this: std::map<std::string, std::vector<std::string>>
  // New entries are added as a pair: std::pair<std::string, std::vector<std::string>>
  // Vectors of strings will be used throughout: std::vector<std::string>
  // Use these typedefs for programmer's convenience
  typedef std::vector<std::string> VectorString;
  typedef std::map<std::string, VectorString> StateTable;
  typedef std::pair<std::string, VectorString> StateTableEntry;

  StateTable state_table_;
  VectorString starters_;
  unsigned int length_;

  // Helper functions
  int Rng(int upper, int lower);
  //std::string GetGramAtIndex(int index, const VectorString vs);
  void SetMemberVariables(int length);

public:
  // Default constructor and destructor
  MarkovTextGenerator();
  ~MarkovTextGenerator();
  
  // Constructors
  MarkovTextGenerator(const std::string &inputString, int length);
  MarkovTextGenerator(const VectorString &vs, int length);

  // Member functions
  void AddSentence(const std::string &sentence);
  void AddFromTextFile(const std::string &filename);
  std::string GetRandomSentence();
  void PrintRandomSentence();
  void TrimSpaces(std::string &s);

  // Debug functions
  void PrintStateTable();
  void PrintStarters();
};

#endif
#include <math.h>
#include <ctime>
#include <fstream>
#include <iostream>
#include <assert.h>
#include <sstream>

#include "markov_text_generator.h"

// Use this for debugging and on a Windows machine
#include <Windows.h>

// Default constructor and destructor
MarkovTextGenerator::MarkovTextGenerator() {}
MarkovTextGenerator::~MarkovTextGenerator() {}

// Constructor that takes in a single string and length and populates a map
MarkovTextGenerator::MarkovTextGenerator(const std::string &input_string,
                                         int length) {
  SetMemberVariables(length);

  // Add sentence to state table by seeing if the string is a valid text file
  // If so, open it and put its contents into the state table
  // If not, that means it's an individual string so read that instead
  std::ifstream file(input_string);
  if (file.is_open()) {
    file.close();
    AddFromTextFile(input_string);
  } else AddSentence(input_string);
}

// Constructor that takes in a vectorstring instead of a file or string
MarkovTextGenerator::MarkovTextGenerator(const VectorString &vs,
                                         int length) {
  SetMemberVariables(length);

  // Iterate through the vectorstring and enter each string into the state table
  for (unsigned int i = 0; i < vs.size(); i++) AddSentence(vs[i]);
}

// Helper function for constructors
void MarkovTextGenerator::SetMemberVariables(int length) {
  // Check if length is valid
  // If length is 0, the MTG will assume word-based MTG; otherwise, char-based
  // Invalid length values will also default to word-based MTG
  if (length < 0 || length > 10) {
    length = 0;
    std::cout << "[MarkovTextGenerator] ERROR: Invalid length; defaulting to word-based MTG\n";
  } else length_ = length;
}

// Member function for accepting input from a text file
void MarkovTextGenerator::AddFromTextFile(const std::string &filename) {
  std::string line;
  std::ifstream file(filename);
  if (file.is_open()) {
    while (getline(file, line)) if (line.size() > length_) AddSentence(line);
    file.close();
  } else printf("[MarkovTextGenerator] ERROR: Unable to read text file.\n");
}

// Member function that accepts a sentence and adds it to the state table
void MarkovTextGenerator::AddSentence(const std::string &sentence) {
  // First, trim all the extra whitespace away
  std::string trimmed_sentence = sentence;
  TrimSpaces(trimmed_sentence);

  // If the sentence is blank, don't bother
  if (trimmed_sentence.size() == 0) return;

  //// Debug: print out the trimmed sentence
  //std::cout << "\"" << trimmed_sentence << "\"\n\n";

  // Determine which version of the MTG to use
  // Word-based MTG uses stringstream, char-based uses a string iterator
  // Either way, the broken-up sentence will then be put in a vectorstring
  VectorString vector_string;
  if (length_ == 0) {
    // Word-based MTG code
    std::istringstream vector_string_stream(trimmed_sentence);
    while (vector_string_stream) {
      std::string word;
      vector_string_stream >> word;
      vector_string.push_back(word);
    }
    // There's an extra blank entry at this point, so remove it
    vector_string.pop_back();

    // Add an end-of-string marker at the end of the vectorstring
    vector_string.push_back("<END-OF-STRING>");
  } else {
    // Char-based MTG code
    // Note: for char-based MTG mode for lengths greater than 1, the broken-up
    // sentence will be duplicated and the duplicates will be interleaved with
    // one another in a regular pattern

    // For example, consider "I'm fine" with length_ = 3
    // The resulting vectorstring (w/o end-of-string markers) will have this:
    //  0      1      2      3      4      5      6      7
    // ["I'm", "'m ", "m f", " fi", "fin", "ine", "ne",  "e"  ]
    // Entries 0, 3, and 6 combined will contain the complete sentence,
    // but entries 1+4+7 and 2+5 also contain the complete sentence (with some
    // missing letters at the beginning

    // Note: C++ substrings use two parameters:
    // The first parameter is the starting index
    // The second param is how far from the starting index you want your substr

    // At this stage, entries 6 and 7 would cause errors since those substrings
    // require characters outside the size of trimmed_sentence; extra code is
    // used to ensure that the substring length will always be 3 or less at
    // that part of the string

    int loop_limit = trimmed_sentence.size() - 1;
    for (int i = 0; i <= loop_limit; i++) {
      int substring_length;
      if ((i + length_) > trimmed_sentence.length())
        substring_length = i + length_ - trimmed_sentence.length();
      else substring_length = length_;
      vector_string.push_back(trimmed_sentence.substr(i, length_));
    }

    // Add multiple end-of-string markers to account for how each broken-up
    // sentence is interleaved with each other
    for (int i = 0; i < length_; i++)
      vector_string.push_back("<END-OF-STRING>");
  }

  //// Debug: print out the vectorstring
  //for (int i = 0; i < vector_string.size(); i++)
  //  std::cout << vector_string[i] << "\n";

  // Add the vectorstring to the state table
  // Also record the sentence beginning
  // The state table is an STL map with a key-value pair of 
  // strings and vectorstrings
  starters_.push_back(vector_string[0]);

  // First, determine the loop limit; this is dependent on whether the MTG
  // is char-based or word-based
  int loop_limit;
  if (length_ == 0 || length_ == 1) loop_limit = vector_string.size() - 1;
  else loop_limit = vector_string.size() - length_;
  for (int i = 0; i < loop_limit; i++) {
    std::string curr_gram = vector_string[i];

    // Extra code to accommodate the char-based MTG
    // The next_gram for the char-based MTG needs to be offset

    // Recall the previous example with "I'm fine" with length_ = 3
    // The resulting vectorstring (w/o end-of-string markers) will have this:
    //  0      1      2      3      4      5      6      7
    // ["I'm", "'m ", "m f", " fi", "fin", "ine", "ne",  "e"  ]
    // Entries 0, 3, and 6 contain the full sentence, but so does 1+4+7 and
    // 2+5 (with some missing characters at the beginning)

    // To proper populate the state diagram, the algorithm needs to make jumps
    // that are as big as length_, so "I'm" needs to skip "'m " and "m f" and
    // go straight to " fi"

    // NOTE: At this point, extra end-of-string markers would be added and
    // those would also be added to the state table

    std::string next_gram;
    if (length_ == 0) next_gram = vector_string[i + 1];
    else next_gram = vector_string[i + length_];
    
    // If the given ngram doesn't exist, add it
    if (state_table_.find(curr_gram) == state_table_.end()) {
      VectorString vs;
      state_table_.insert(StateTableEntry(curr_gram, vs));
    }

    // Add the ngram's next ngram to the ngram map
    state_table_[curr_gram].push_back(next_gram);
  }
}

// Member function for generating a random sentence
std::string MarkovTextGenerator::GetRandomSentence() {
  if (state_table_.size() == 0)
    return "[MarkovTextGenerator] ERROR: State table not populated.";
  else {
    // Pick a random word from the vector of starters to start the sentence
    // This will become the current gram, curr_gram
    VectorString vs_sentence;
    std::string curr_gram = starters_[Rng(starters_.size(), 0)];
    vs_sentence.push_back(curr_gram);

    // Based off of the current gram, pick a random gram to be next_gram
    std::string next_gram = state_table_[curr_gram][Rng(state_table_[curr_gram].size(), 0)];

    // Do this in a loop; generate a sentence by populating it in pieces in a
    // vectorstring, then assemble the sentence from the vectorstring
    while (state_table_[curr_gram].size() != 0 && next_gram != "<END-OF-STRING>") {
      curr_gram = next_gram;
      vs_sentence.push_back(curr_gram);
      next_gram = state_table_[curr_gram][Rng(state_table_[curr_gram].size(), 0)];
    }

    // Assemble the final sentence
    std::string final_sentence;
    if (length_ == 0) {
      for (int i = 0; i < vs_sentence.size(); i++) {
        final_sentence += vs_sentence[i];
        if (i < vs_sentence.size() - 1) final_sentence += " ";
      }
    } else {
      for (int i = 0; i < vs_sentence.size(); i++) {
        final_sentence += vs_sentence[i];
      }
    }

    return final_sentence;
  }
}

// Member function for printing a random sentence
void MarkovTextGenerator::PrintRandomSentence() {
  std::cout << "[MarkovTextGenerator] \"" << GetRandomSentence() << "\"\n";
}

// Helper function recycled from one of my software engineering assignments
// Function for removing extra whitespaces at ends of string
// https://tux4life.wordpress.com/2009/07/26/trimming-cpp-strings/
void MarkovTextGenerator::TrimSpaces(std::string &s) {
  std::string trim_chars = " \t";
  std::string::size_type pos = s.find_last_not_of(trim_chars);

  if (pos != std::string::npos) {
    s.erase(pos + 1);
    pos = s.find_first_not_of(trim_chars);
    if (pos != std::string::npos) s.erase(0, pos);
  } else
    s.erase(s.begin(), s.end());
}

// Helper function; this is a random number genreator
int MarkovTextGenerator::Rng(int upper, int lower) {
  assert(upper > lower);
  if (upper > 0) return rand() % upper + lower;
  else return lower;
}

// Debug function: Print table
void MarkovTextGenerator::PrintStateTable() {
  std::cout << "[MarkovTextGenerator] Printing state table...\n";
  for (StateTable::iterator i = state_table_.begin(); i != state_table_.end(); ++i) {
    std::cout << "Key: \"" << i->first << "\"\n" << "Values: ";
    if (i->second.size() == 0)
      std::cout << "NO VALUES ASSOCIATED WITH KEY";
    else {
      for (unsigned int j = 0; j < i->second.size(); j++) {
        std::cout << "\"" << i->second[j] << "\", ";
      }
    }
    std::cout << std::endl << std::endl;
  }
  std::cout << "[MarkovTextGenerator] End of state table reached.\n\n";
}

void MarkovTextGenerator::PrintStarters() {
  std::cout << "[MarkovTextGenerator] Printing sentence-starting grams: ";
  for (int i = 0; i < starters_.size(); i++) {
    std::cout << "\"" << starters_[i] << "\", ";
  }
  std::cout << std::endl << std::endl;
}

 


a0AgWVX.png

<>

Link to comment
Share on other sites

7 minutes ago, Miss H said:

I think its more cruel to not spoiler a wall like that, but that's just me.

I crutspoit itha to illithatoinor bue thal thatoil wale t thil bue think t, lil no spot t, wa not, cre wa t lik lelel walinor toit ike to al it but buerelile al at tot, thatorue tst, mor it wator s cr il t, moik llinor juthitha to thatha watha thit's thathat mot il justha t tstspoikeruel me just lino jue bue mo buspor noil ithalit t thile.

I'm sorry... (Also, I added more functionality to the MTG, so that code's outdated already.)


a0AgWVX.png

<>

Link to comment
Share on other sites

17 hours ago, Miss H said:

I think its more cruel to not spoiler a wall like that, but that's just me.

ganaram takes no prisoners. 


We have two ears and one mouth, so we should listen more than we say.

Link to comment
Share on other sites

@Sir Punicpunch. @Olly, @Miss H

You guys think you can try this? Physically divide up this wheel into pieces and then name each piece by what colours you think they are. (I've tried asking around but no one understood the instructions, so I'm defaulting to you three because I have no one else to turn to.)

wheel_of_hues.png.d1fe9c2ff26623c180d7215f9ba3e348.png

Your result should be like one of these:

capture_colour_test_wheel.thumb.PNG.b86b9398d13e265063378bea2e3d667f.PNG


a0AgWVX.png

<>

Link to comment
Share on other sites

5 hours ago, Ganaram Inukshuk said:

@Sir Punicpunch. @Olly, @Miss H

You guys think you can try this? Physically divide up this wheel into pieces and then name each piece by what colours you think they are. (I've tried asking around but no one understood the instructions, so I'm defaulting to you three because I have no one else to turn to.)

wheel_of_hues.png.d1fe9c2ff26623c180d7215f9ba3e348.png

Your result should be like one of these:

capture_colour_test_wheel.thumb.PNG.b86b9398d13e265063378bea2e3d667f.PNG

Well, after hours of messing with paint.net it finally works again, so I will get right on this.


img-26989-1-img-26989-1-img-26989-1-img-

Your Resident Robot Cyberneticist

 

 

 

 

Link to comment
Share on other sites

5 hours ago, Ganaram Inukshuk said:

@Sir Punicpunch. @Olly, @Miss H

You guys think you can try this? Physically divide up this wheel into pieces and then name each piece by what colours you think they are. (I've tried asking around but no one understood the instructions, so I'm defaulting to you three because I have no one else to turn to.)

 

Your result should be like one of these:

 

oh.png.b9eefc4f774a69ec0644eeb0b64ae684.png

Your request was quite rude, tbh.

 

 

 

 

 

 

Though, not as rude as that. I'm colorblind, fyi, but not 100%. I'm just mildly deutranopia (red/green) or however you spell it. So, it blends really hard, but not that hard.

Edited by Miss H

7Crdz3K.png

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Join the herd!

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...