Toute la solution dans une
archive markov.tar.gz,
avec les classes WordReader
et Args
données.
Voici encore une fois,
l’archive bovary.tar.gz
qui contient le texte de Madame Bovary divisé en 36 chapitres.
Une fois récupérées les archives, voici comment obtenir
un nouveau chapitre de Madame Bovary.
# tar zxf markov.tar.gz
# cd markov
# tar zcf ../bovary.tar.gz
# javac Markov.java
# java Markov
import java.util.* ;
class WordList {
String val ;
WordList next ;
WordList (String val, WordList next) {
this.val = val ;
this.next = next ;
}
static int length(WordList p) {
int r = 0 ;
for ( ; p != null ; p = p.next)
r++ ;
return r ;
}
static String [] toArray(WordList p) {
// D'abord allouer le tableau.
int sz = length(p) ;
String [] r = new String[sz] ;
// Puis copier les éléments de la liste dans le tableau.
for (int k = 0 ; k < sz ; k++) {
r[k] = p.val ;
p = p.next ;
}
return r ;
}
public String toString() {
StringBuilder r = new StringBuilder () ;
r.append(this.val) ;
for (WordList p = this.next ; p != null ; p = p.next) {
r.append(" " + p.val) ;
}
return r.toString() ;
}
}
class Prefix {
final static String start = "<START>", end = "<END>", par = "<PAR>" ;
// Le préfixe est un tableau de n mots.
String [] t ;
Prefix(int n) {
t = new String [n] ;
for (int k = 0 ; k < n ; k++)
t[k] = start ;
}
// Glissement du préfixe.
private Prefix(String [] t) {
this.t = t ;
}
Prefix shift(String w) {
int n = t.length ;
String [] tt = new String [n] ;
for (int k = 0 ; k < n-1 ; k++)
tt[k] = t[k+1] ;
tt[n-1] = w ;
return new Prefix(tt) ;
}
/*****************/
/* Redéfinitions */
/*****************/
// Pas nécessaire, mais peut aider à mettre le programme au point.
public String toString() {
StringBuilder r = new StringBuilder () ;
int n = t.length ;
for (int k = 0 ; k < n-1 ; k++) {
r.append(t[k]) ; r.append(" ") ;
}
r.append(t[n-1]) ;
return r.toString() ;
}
// Suffisant en pratique : mélange des hashCode() des mots du préfixe.
public int hashCode() {
int r = 0 ;
for (String s : t) {
r += 37*r + s.hashCode() ;
}
return r ;
}
// Égalité structurelle des préfixes.
public boolean equals(Object o) {
Prefix op = (Prefix) o;
int n = t.length ;
for (int k = 0 ; k < n ; k++) {
if (!t[k].equals(op.t[k])) return false ;
}
return true ;
}
}
import java.util.* ;
class Markov {
/****************************/
/* Construction de la table */
/****************************/
static HashMap<Prefix,String []> build(String [] files, int n) {
// Lire l'entrée, donne une table prefixe -> Liste de n+unième mots
HashMap<Prefix,WordList> t = new HashMap<Prefix,WordList> () ;
for (String name : files) {
WordReader reader = new WordReader (name) ;
String w ;
Prefix pref = new Prefix (n) ;
while ((w = reader.read()) != null) {
t.put(pref, new WordList (w,t.get(pref))) ;
pref = pref.shift(w) ;
}
t.put(pref, new WordList (Prefix.end,t.get(pref))) ;
}
// Transformer la table, prefixe -> tableau de n+unième mots
HashMap<Prefix,String []> r = new HashMap<Prefix,String []> () ;
for (Map.Entry<Prefix,WordList> e : t.entrySet()) {
r.put(e.getKey(),WordList.toArray(e.getValue())) ;
}
return r ;
}
/************************/
/* Production du texte */
/************************/
static void chain(HashMap<Prefix,String []> t, int n) {
Prefix p = new Prefix (n) ;
Random rand = new Random () ;
for ( ; ; ) {
String [] ws = t.get(p) ;
String w = ws[rand.nextInt(ws.length)] ;
if (w.equals(Prefix.end)) {
System.out.println() ;
return ;
}
dump(w) ;
p = p.shift(w) ;
}
}
/****************************************************************/
/* Affichage pas trop moche (et conforme au format de l'entrée) */
/****************************************************************/
private static boolean fst = true ;
static void dump(String w) {
if (w.equals(Prefix.par)) {
System.out.println() ;
System.out.print(w) ;
System.out.println() ;
fst = true ;
} else {
if (!fst) System.out.print(" ") ;
System.out.print(w) ;
fst = false ;
}
}
public static void main (String [] arg) {
Args a = new Args (arg) ;
chain(build(a.files,a.prefixLength),a.prefixLength) ;
}
}
Ce document a été traduit de LATEX par HEVEA