Générer des lettres au hasard selon leur fréquence d'utilisation?

voix
10

Comment puis-je générer au hasard des lettres en fonction de leur fréquence d'utilisation dans le langage courant?

Tout pseudo-code apprécié, mais une implémentation en Java serait fantastique. Sinon, juste un coup de coude dans la bonne direction serait utile.

Note: Je ne ai pas besoin pour générer les fréquences d'utilisation - je suis sûr que je peux regarder que assez facilement.

Créé 27/01/2010 à 21:11
source utilisateur
Dans d'autres langues...                            


5 réponses

voix
11

Un moyen rapide de le faire serait de générer une liste de lettres, où chaque lettre a été publiée dans la liste conformément à sa fréquence. Dites, si « e » a été utilisé 25,6% du temps, et votre liste avait longueur 1000, il aurait 256 « e » s.

Ensuite , vous pouvez simplement choisir au hasard des points de la liste en utilisant (int) (Math.random() * 1000)pour générer des nombres aléatoires entre 0 et 999.

Créé 27/01/2010 à 21:14
source utilisateur

voix
18

Je suppose que vous stockez les fréquences comme nombres à virgule flottante compris entre 0 et 1 que le total pour faire 1.

D'abord, vous devez préparer une table de fréquences cumulées, soit la somme de la fréquence de cette lettre et toutes les lettres dont elle est saisie.

Pour simplifier, si vous commencez avec cette distribution de fréquence:

A  0.1
B  0.3
C  0.4
D  0.2

Votre table de fréquence cumulée serait la suivante:

A  0.1
B  0.4 (= 0.1 + 0.3)
C  0.8 (= 0.1 + 0.3 + 0.4)
D  1.0 (= 0.1 + 0.3 + 0.4 + 0.2)

Maintenant générer un nombre aléatoire entre 0 et 1 et voir où dans cette liste ce nombre est. Choisissez la lettre qui a la plus petite fréquence cumulée plus grande que votre nombre aléatoire. Quelques exemples:

Dites que vous choisissez au hasard 0,612. Cela se situe entre 0,4 et 0,8, soit entre B et C, de sorte que vous choisirait C.

Si votre numéro aléatoire était 0,039, qui vient avant 0,1, soit avant A, afin de choisir A.

J'espère que le bon sens, sinon ne hésitez pas à demander des éclaircissements!

Créé 27/01/2010 à 21:20
source utilisateur

voix
4

Pas même un pseudo-code, mais une approche possible est la suivante:

Laissez-p1, p2, ..., Pk les fréquences que vous souhaitez correspondre.

  1. Calculer les fréquences cumulatives: p1, p2 + p1, p1 + p2 + p3, ..., 1
  2. Générer un nombre aléatoire uniforme (0,1) x
  3. Vérifiez quel intervalle des fréquences cumulées x appartient à: si elle est entre, disons, p1 + .. + pi et p1 + ... + pi + p (i + 1), puis la sortie (i + 1) st lettre

Selon la façon dont vous implémentez la conclusion d'intervalle, la procédure est généralement plus efficace si les p1, p2, ... sont classés par ordre décroissant, parce que vous trouverez généralement l'intervalle contenant x plus tôt.

Créé 27/01/2010 à 21:20
source utilisateur

voix
5

Ce que je ferais est l' échelle des fréquences relatives comme nombres à virgule flottante de telle sorte que leur somme est de 1,0. Ensuite , je créerais un tableau des cumulatifs totaux par lettre, à savoir le nombre qui doit être surmonté pour obtenir cette lettre et tous ceux « ci - dessous » il. Dire la fréquence de A est de 10%, b est de 2% et z est de 1%; alors votre table ressemblerait à quelque chose comme ceci:

0.000 A ; from 0% to 10% gets you an A
0.100 B ; above 10% is at least a B
0.120 C ; 12% for C...
...
0.990 Z ; if your number is >= 99% then you get a Z

Ensuite, vous vous générer un nombre aléatoire entre 0.0 et 1.0 et effectuez une recherche binaire dans le tableau pour le premier numéro plus petit que votre nombre aléatoire. Ensuite, choisissez la lettre à cette position. Terminé.

Créé 27/01/2010 à 21:23
source utilisateur

voix
2

L' utilisation d' un arbre binaire vous donne un moyen agréable, propre pour trouver la bonne entrée. , Vous commencez ici avec une frequencycarte, où les clés sont les symboles (lettres en anglais), et les valeurs sont la fréquence de leur apparition. Cela devient inversé, et NavigableMapest créé où les clés sont la probabilité cumulative, et les valeurs sont des symboles. Cela rend la recherche facile.

  private final Random generator = new Random();

  private final NavigableMap<Float, Integer> table = 
    new TreeMap<Float, Integer>();

  private final float max;

  public Frequency(Map<Integer, Float> frequency)
  {
    float total = 0;
    for (Map.Entry<Integer, Float> e : frequency.entrySet()) {
      total += e.getValue();
      table.put(total, e.getKey());
    }
    max = total;
  }

  /** 
   * Choose a random symbol. The choices are weighted by frequency.
   */ 
  public int roll()
  {
    Float key = generator.nextFloat() * max;
    return table.higherEntry(key).getValue();
  }
Créé 27/01/2010 à 22:10
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more