うどんのこんぶだしが取れるまで時間があったので、ちょっと試しにつくってみました。
簡単なプログラムだけど、それっぽい結果がでてます。登録する文章しだいで結構おもしろくなりそう。
Igoはこれです。
Igo - a morphological analyzer
ここに書いてある手順で辞書バイナリを作ってください。
あとは、ソース中でその位置を指定します。
※ 追記 2023/4/6 GitHubに移行しているようです。
https://github.com/sile/igo
mecabはこちらに
https://taku910.github.io/mecab/
で、上側のテキストエリアに新聞記事をはりつけて「登録」ボタンを押します。
いくつか新聞記事を登録して「生成」ボタンを押すと、なんかそれっぽい文章が生成されます。
文章の生成自体は、簡単なプログラムでそれっぽいものができることがわかりました。
まあ、文章のクロールと、あとは記号なんかの処理が大事そうです。違う分野の文章をまぜたほうがおもしろい文章が生成されそう。
追記--
うどんおいしくできあがりました。
--追記ここまで
めんどいので、NetBeansの生成したそのままのソース。Java7でコンパイルするか、<>オペレータを適当に修正してください。
import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; import net.reduls.igo.Morpheme; import net.reduls.igo.Tagger; /** * @author naoki */ public class AsshukuFrame extends javax.swing.JFrame { Tagger tagger; /** Creates new form AsshukuFrame */ public AsshukuFrame() { try { tagger = new Tagger("path to dic");//辞書バイナリへのパス } catch (IOException ex) { ex.printStackTrace(); } noSeparate.addAll(Arrays.asList("「", "」", "(", ")","、", "・")); initComponents(); } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code"> private void initComponents() { jScrollPane1 = new javax.swing.JScrollPane(); taArticle = new javax.swing.JTextArea(); jScrollPane2 = new javax.swing.JScrollPane(); taLog = new javax.swing.JTextArea(); btnRegister = new javax.swing.JButton(); btnGenerate = new javax.swing.JButton(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); taArticle.setColumns(20); taArticle.setRows(5); jScrollPane1.setViewportView(taArticle); taLog.setColumns(20); taLog.setRows(5); jScrollPane2.setViewportView(taLog); btnRegister.setText("登録"); btnRegister.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { btnRegisterActionPerformed(evt); } }); btnGenerate.setText("生成"); btnGenerate.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { btnGenerateActionPerformed(evt); } }); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 470, Short.MAX_VALUE) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 470, Short.MAX_VALUE) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(btnGenerate) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(btnRegister))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 112, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(btnRegister) .addComponent(btnGenerate)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 270, Short.MAX_VALUE) .addContainerGap()) ); pack(); }// </editor-fold> static Set<String> noSeparate = new HashSet<>(); private static class Morph{ String word; String element; int nextCount = 0; public Morph() { } public Morph(Morpheme m) { word = m.surface; element = m.feature; } Map<Morph, Integer> counter = new HashMap<>(); void add(Morph m){ int count = 0; if(counter.containsKey(m)){ count = counter.get(m); } counter.put(m, count + 1); ++nextCount; } boolean isSeparator(){ if(!element.startsWith("記号,")){ return false; } return !noSeparate.contains(word); } @Override public int hashCode() { return getKey().hashCode(); } @Override public boolean equals(Object obj) { if(obj == null) return false; if(!(obj instanceof Morph)) return false;//継承したオブジェクトも受け入れてみる。 return ((Morph)obj).getKey().equals(getKey()); } public String getKey(){ return element; } } private static class StartMorphs extends Morph{ } private static class Endmorph extends Morph{ @Override boolean isSeparator() { return true; } } Morph start = new StartMorphs(); Morph end = new Endmorph(); Map<Morph, Morph> morphs = new HashMap<>();//比較キーを試しに切り替えるためにこんなことに。 private Morph createMorph(Morpheme m){ Morph key = new Morph(m); if(morphs.containsKey(key)){ return morphs.get(key); }else{ morphs.put(key, key); return key; } } private void btnRegisterActionPerformed(java.awt.event.ActionEvent evt) { String str = taArticle.getText(); str = str.trim(); if(str.isEmpty()) return; //形態素解析 List<Morpheme> morphList = tagger.parse(str); Morph preMorph = start; for(Morpheme m : morphList){ Morph mm = createMorph(m); preMorph.add(mm); if(mm.isSeparator()){ preMorph = start; }else{ preMorph = mm; } } if(preMorph != start){ preMorph.add(end); } taLog.append(morphList.size() + "単語を登録\n"); } Random rand = new Random(); private void btnGenerateActionPerformed(java.awt.event.ActionEvent evt) { Morph pre = start; WORD: for(int i = 0; i < 100; ++i){ int next = rand.nextInt(pre.nextCount); int c = 0; for(Map.Entry<Morph, Integer> ent : pre.counter.entrySet()){ c += ent.getValue(); if(next < c){ pre = ent.getKey(); if(pre instanceof Endmorph) break WORD; taLog.append(pre.word); if(pre.isSeparator()) break WORD; break; } } } taLog.append("\n"); } /** * @param args the command line arguments */ public static void main(String args[]) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new AsshukuFrame().setVisible(true); } }); } // Variables declaration - do not modify private javax.swing.JButton btnGenerate; private javax.swing.JButton btnRegister; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JTextArea taArticle; private javax.swing.JTextArea taLog; // End of variables declaration }