I need a little help in understanding how to run this Markov Chain program (It's one of those Mark V Shaney type programs). The code itself is from The Practice of Programming by Keringhan and Pike. It's on Page 81 if anyone is particularly interested in cross-referencing. The way I understood their instructions, I should be able to produce the formatted version of the processed file by typing java Markov <goo.txt |fmt. However, when I do this the text remains unchanged. If I simply type java Markov <goo.txt without the extension it will jumble the text according to the Markov algorithm, but print it on a one word one line basis. It's probably a very simple thing I'm missing, but my understanding of how to run java programs from the terminal is still very basic. If anyone wants me to give examples of the file content and the output for different commands I will provide it, but I don't want this post to get too long, and I think it's more important to show the sample code below.
import java.io.IOException; import java.io.InputStream; import java.io.StreamTokenizer; import java.util.Hashtable; import java.util.Random; import java.util.Vector; public class Chain { static final int NPREF = 2; //size of prefix static final String NONWORD = "\n"; //"word" that can't appear Hashtable statetab = new Hashtable(); //key = Prefix, value = suffix Vector Prefix prefix = new Prefix(NPREF,NONWORD); //initial prefix Random rand = new Random(); //Chain build: build State table from input stream void build (InputStream in )throws IOException{ @SuppressWarnings("deprecation") StreamTokenizer st = new StreamTokenizer(in); st.resetSyntax(); //remove default rules st.wordChars(0,Character.MAX_VALUE); //turn on all chars st.whitespaceChars(0, ' '); while(st.nextToken()!= st.TT_EOF) add(st.sval); add(NONWORD); } //Chain add: add word to suffix list, update prefix void add(String word){ Vector suf = (Vector) statetab.get(prefix); if(suf== null){ suf = new Vector(); statetab.put(new Prefix(prefix), suf); } suf.addElement(word); prefix.pref.removeElementAt(0); prefix.pref.addElement(word); } //Chain generate: generate output words void generate(int nwords){ prefix = new Prefix(NPREF,NONWORD); for(int i =0;i<nwords;i++){ Vector s = (Vector) statetab.get(prefix); int r = Math.abs(rand.nextInt())%s.size();String suf = (String) s.elementAt(r); if(suf.equals(NONWORD) ) break; System.out.println(suf); prefix.pref.removeElementAt(0); prefix.pref.addElement(suf); } } }
import java.util.Vector; public class Prefix { static final int MULTIPLIER = 31; public Vector pref; //Prefix constructor: duplicate existing prefix Prefix (Prefix p){ pref = (Vector) p.pref.clone(); } //Prefix constructor: n copies of str Prefix (int n, String str){ pref = new Vector(); for(int i = 0;i<n; i++) pref.addElement(str); } //Prefix hashcode: generate hash from all prefi words public int hashCode(){ int h = 0; for(int i =0; i<pref.size();i++) h = MULTIPLIER * h + pref.elementAt(i).hashCode(); return h; } //Prefix equals: compare two prefixes for equal words public boolean equals(Object o){ Prefix p = (Prefix)o; for(int i =0;i<pref.size();i++) if (!pref.elementAt(i).equals(p.pref.elementAt(i))) return false; return true; } }
import java.io.IOException; public class Markov { static final int MAXGEN = 1000;//maximum words generated public static void main (String [] args) throws IOException { Chain chain = new Chain(); int nwords = MAXGEN; chain.build(System.in); chain.generate(nwords); } }
--- Update ---
Actually, now that I've tried it again, both methods seem to be producing the words in the original order. Maybe something is wrong with the way I copied down the program?