Skip to content

Instantly share code, notes, and snippets.

@MarksCode
Last active August 29, 2015 14:17
Show Gist options
  • Save MarksCode/29b3290a352af81e9e7a to your computer and use it in GitHub Desktop.
Save MarksCode/29b3290a352af81e9e7a to your computer and use it in GitHub Desktop.
/*********************************************************************/
/* Program: Markov ChainMaker */
/* Author: Ron Marks */
/* */
/* This programs applies Markov chains to textual input in order to */
/* generate not-quite-random sentences and words. */
/* */
/* */
/* Input: */
/* Text file as args0 */
/* Example: https://gist.github.com/MarksCode/6150b1dd4721b9a1c85f */
/* Example: java ChainMaker Moby.txt */
/* */
/* Output: */
/* Chain outputs words of text file using markov chain rule */
/* Char outputs characters of text file using markov chain rule */
/*********************************************************************/
import java.util.*;
import java.io.*;
class ChainMaker{
/***************/
/* MAIN METHOD */
/***************/
public static void main(String[] args) throws FileNotFoundException {
MarkovChain m = new MarkovChain();
m.training(args[0]);
m.generate(50, " ");
MarkovChar mc = new MarkovChar();
mc.training(args[0]);
mc.generate(150, "");
}
}
/**************************/
/* Chain Interface */
/* */
/* by Ron Marks (romarks) */
/**************************/
// Interface is contract to make sure rules are met when calling listed methods
interface Chain {
public void training(String filename) throws FileNotFoundException;
public void generate(int iterations, String delimeter);
}
/**************************/
/* MarkovChain Class */
/**************************/
class MarkovChain implements Chain {
private HashMap<String, List<String>> map = new HashMap<String, List<String>>();
/*******************/
/* Training Method */
/* Creates hashmap */
/* Input: File */
/*******************/
public void training(String filename) throws FileNotFoundException {
File file = new File(filename);
Scanner type = new Scanner(file);
String w1 = "";
String w2 = "";
// Checking there is a word to scan
if (!type.hasNext()){
System.out.println("Not Enough Words");
System.exit(0);
}
String w3 = type.next();
// Making combination String out of 1st and 2nd words for key
String comb = w1 + " " + w2;
// Making an ArrayList with 3rd word and putting it and key in my HashMap
List<String> vals = new ArrayList<String>();
vals.add(w3);
map.put(comb, vals);
// Loop keeps going as long as there are words to scan
while(type.hasNext()){
w1 = w2;
w2 = w3;
w3 = type.next();
comb = w1 + " " + w2;
// Checking if map contains key already
if(map.containsKey(comb)){
vals = map.get(comb);
vals.add(w3);
} else{
vals = new ArrayList<String>(Arrays.asList(w3));
map.put(comb, vals);
}
}
}
/**********************/
/* Generate Method */
/* Prints things */
/* Input: Iterations, */
/* seperator string */
/**********************/
public void generate(int iterations, String delim) {
String a1 = "";
String a2 = "";
int i = 0;
String key = a1 + " " + a2;
Boolean contKey = map.containsKey(key);
Random rand = new Random(4);
// Loop goes for iteration number or until key isn't found in HashMap
while(i<iterations && contKey){
List<String> words = map.get(key);
int randNum = rand.nextInt(words.size());
String val = words.get(randNum);
// Prints out the chosen value and seperator string
System.out.printf(val + delim);
a1 = a2;
a2 = val;
key = a1 + " " + a2;
contKey = map.containsKey(key);
i++;
}
System.out.printf("...");
System.out.println();
System.out.println("--");
}
}
/*******************************/
/* MarkovChar Class */
/*******************************/
class MarkovChar extends MarkovChain{
// Creating HashMap for Strings and Characters
private HashMap<String, List<Character>> cMap = new HashMap<String, List<Character>>();
/*******************/
/* Training Method */
/* Creates hashmap */
/* Input: File */
/*******************/
public void training(String filename) throws FileNotFoundException {
File file = new File(filename);
Scanner inType = new Scanner(file);
char c1 = '\u0000';
char c2 = '\u0000';
if (!inType.hasNext()){
System.out.println("Not Enough Chars");
System.exit(0);
}
// Creating combination of first 2 characters
String cComb = c1+""+c2;
List<Character> cvals = new ArrayList<Character>();
inType.useDelimiter("");
String blah = inType.next();
// Scanning for next char in document and changing it based on its value
char c3 = blah.charAt(0);
if(c3 == '\n'){
c3 = ' ';
}
if(c3 == ')'){
c3 = ' ';
}
if(c3 == '('){
c3 = ' ';
}
cvals.add(c3);
// Adding first bit to HashMap
cMap.put(cComb, cvals);
// Starting loop for rest of HashMap
while(inType.hasNext()){
c1 = c2;
c2 = c3;
cComb = c1 + "" + c2;
blah = inType.next();
c3 = blah.charAt(0);
if(c3 == '\n'){
c3 = ' ';
}
if(c3 == ')'){
c3 = ' ';
}
if(c3 == '('){
c3 = ' ';
}
// Checking if HashMap already contains key
if(cMap.containsKey(cComb)){
cvals = cMap.get(cComb);
cvals.add(c3);
} else{
cvals = new ArrayList<Character>();
cvals.add(c3);
cMap.put(cComb, cvals);
}
}
}
/***********************/
/* Generate Method */
/* Prints based on */
/* hashmap constructed */
/* Input: Iterations, */
/* seperating string */
/***********************/
public void generate(int iterations, String sep){
char p1 = '\u0000';
char p2 = '\u0000';
int i = 0;
String key = p1 + "" + p2;
Boolean contChar = cMap.containsKey(key);
Random rand = new Random(4);
// Checks for iterations gone through and if map contains key, then prints out a random value for corresponding key
while(i<iterations && contChar){
List<Character> myChars = cMap.get(key);
int randNum = rand.nextInt(myChars.size());
char newChar = myChars.get(randNum);
System.out.printf(newChar + "" + sep);
p1 = p2;
p2 = newChar;
key = p1 + "" + p2;
contChar = cMap.containsKey(key);
i++;
}
System.out.printf("...");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment