All pastes #25691 Raw Edit

Untitled

public text v1 · immutable
#25691 ·published 2005-10-16 21:02 UTC
rendered paste body
/* 

Copyright Paul James Mutton, 2001-2004, http://www.jibble.org/



This file is part of JMegaHal.



This software is dual-licensed, allowing you to choose between the GNU

General Public License (GPL) and the www.jibble.org Commercial License.

Since the GPL may be too restrictive for use in a proprietary application,

a commercial license is also provided. Full license information can be

found at http://www.jibble.org/licenses/



$Author: pjm2 $

$Id: JMegaHal.java,v 1.4 2004/02/01 13:24:06 pjm2 Exp $



*/



package org.jibble.jmegahal;



import java.util.*;

import java.net.*;

import java.io.*;



public class JMegaHal implements Serializable {

    

    // These are valid chars for words. Anything else is treated as punctuation.

    public static final String WORD_CHARS = "abcdefghijklmnopqrstuvwxyz" +

                                            "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +

                                            "0123456789";

    public static final String END_CHARS = ".!?";

    

    /**

     * Construct an instance of JMegaHal with an empty brain.

     */

    public JMegaHal() {

        

    }

    

    /**

     * Adds an entire documents to the 'brain'.  Useful for feeding in

     * stray theses, but be careful not to put too much in, or you may

     * run out of memory!

     */

    public void addDocument(String uri) throws IOException {

        BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(uri).openStream()));

        StringBuffer buffer = new StringBuffer();

        int ch = 0;

        while ((ch = reader.read()) != -1) {

            buffer.append((char) ch);

            if (END_CHARS.indexOf((char) ch) >= 0) {

                String sentence = buffer.toString();

                sentence = sentence.replace('\r', ' ');

                sentence = sentence.replace('\n', ' ');

                add(sentence);

                buffer = new StringBuffer();

            }

        }

        add(buffer.toString());

        reader.close();

    }

    

    /**

     * Adds a new sentence to the 'brain'

     */

    public void add(String sentence) {

        sentence = sentence.trim();

        ArrayList parts = new ArrayList();

        char[] chars = sentence.toCharArray();

        int i = 0;

        boolean punctuation = false;

        StringBuffer buffer = new StringBuffer();

        while (i < chars.length) {

            char ch = chars[i];

            if ((WORD_CHARS.indexOf(ch) >= 0) == punctuation) {

                punctuation = !punctuation;

                String token = buffer.toString();

                if (token.length() > 0) {

                    parts.add(token);

                }

                buffer = new StringBuffer();

                //i++;

                continue;

            }

            buffer.append(ch);

            i++;

        }

        String lastToken = buffer.toString();

        if (lastToken.length() > 0) {

            parts.add(lastToken);

        }

        

        if (parts.size() >= 4) {

            for (i = 0; i < parts.size() - 3; i++) {

                //System.out.println("\"" + parts.get(i) + "\"");

                Quad quad = new Quad((String) parts.get(i), (String) parts.get(i + 1), (String) parts.get(i + 2), (String) parts.get(i + 3));

                if (quads.containsKey(quad)) {

                    quad = (Quad) quads.get(quad);

                }

                else {

                    quads.put(quad, quad);

                }



                if (i == 0) {

                    quad.setCanStart(true);

                }

                //else if (i == parts.size() - 4) {

                if (i == parts.size() - 4) {

                    quad.setCanEnd(true);

                }

                

                for (int n = 0; n < 4; n++) {

                    String token = (String) parts.get(i + n);

                    if (!words.containsKey(token)) {

                        words.put(token, new HashSet(1));

                    }

                    HashSet set = (HashSet) words.get(token);

                    set.add(quad);

                }

                

                if (i > 0) {

                    String previousToken = (String) parts.get(i - 1);

                    if (!previous.containsKey(quad)) {

                        previous.put(quad, new HashSet(1));

                    }

                    HashSet set = (HashSet) previous.get(quad);

                    set.add(previousToken);

                }

                

                if (i < parts.size() - 4) {

                    String nextToken = (String) parts.get(i + 4);

                    if (!next.containsKey(quad)) {

                        next.put(quad, new HashSet(1));

                    }

                    HashSet set = (HashSet) next.get(quad);

                    set.add(nextToken);

                }

                

            }

        }

        else {

            // Didn't learn anything.

        }

        

    }

    

    /**

     * Generate a random sentence from the brain.

     */

    public String getSentence() {

        return getSentence(null);

    }

    

    /**

     * Generate a sentence that includes (if possible) the specified word.

     */

    public String getSentence(String word) {

        LinkedList parts = new LinkedList();

        

        Quad[] quads;

        if (words.containsKey(word)) {

            quads = (Quad[]) ((HashSet) words.get(word)).toArray(new Quad[0]);

        }

        else {

            quads = (Quad[]) this.quads.keySet().toArray(new Quad[0]);

        }

        

        if (quads.length == 0) {

            return "";

        }

        

        Quad middleQuad = quads[rand.nextInt(quads.length)];

        Quad quad = middleQuad;

        

        for (int i = 0; i < 4; i++) {

            parts.add(quad.getToken(i));

        }

        

        while (quad.canEnd() == false) {

            String[] nextTokens = (String[]) ((HashSet) next.get(quad)).toArray(new String[0]);

            String nextToken = nextTokens[rand.nextInt(nextTokens.length)];

            quad = (Quad) this.quads.get(new Quad(quad.getToken(1), quad.getToken(2), quad.getToken(3), nextToken));

            parts.add(nextToken);

        }

        

        quad = middleQuad;

        while (quad.canStart() == false) {

            String[] previousTokens = (String[]) ((HashSet) previous.get(quad)).toArray(new String[0]);

            String previousToken = previousTokens[rand.nextInt(previousTokens.length)];

            quad = (Quad) this.quads.get(new Quad(previousToken, quad.getToken(0), quad.getToken(1), quad.getToken(2)));

            parts.addFirst(previousToken);

        }

        

        StringBuffer sentence = new StringBuffer();

        Iterator it = parts.iterator();

        while (it.hasNext()) {

            String token = (String) it.next();

            sentence.append(token);

        }

        

        return sentence.toString();

    }

    

    // This maps a single word to a HashSet of all the Quads it is in.

    private HashMap words = new HashMap();

    

    // A self-referential HashMap of Quads.

    private HashMap quads = new HashMap();

    

    // This maps a Quad onto a Set of Strings that may come next.

    private HashMap next = new HashMap();

    

    // This maps a Quad onto a Set of Strings that may come before it.

    private HashMap previous = new HashMap();

    

    private Random rand = new Random();

    

}