Willekeurig Genereer Letters Volgens hun frequentie van gebruik?

stemmen
10

Hoe kan ik willekeurig te genereren letters op basis van hun frequentie van het gebruik in de omgangstaal?

Elke pseudo-code gewaardeerd, maar een implementatie in Java zou fantastisch zijn. Anders gewoon een por in de goede richting zou nuttig zijn.

Opmerking: Ik heb geen behoefte om de frequenties van het gebruik genereren - ik weet zeker dat ik kan kijken dat tot gemakkelijk genoeg.

De vraag is gesteld op 27/01/2010 om 21:11
bron van user
In andere talen...                            


5 antwoorden

stemmen
11

Een snelle manier om dit te doen zou zijn om een ​​lijst met letters, waarbij elke brief verscheen in de lijst in overeenstemming met de frequentie te genereren. Zeggen, als "e" werd gebruikt 25,6% van de tijd, en je lijst hadden lengte 1000, zou het 256 "e" s.

Dan kon je gewoon willekeurig pick-spots van de lijst met behulp van (int) (Math.random() * 1000)willekeurige getallen tussen 0 en 999 te genereren.

antwoordde op 27/01/2010 om 21:14
bron van user

stemmen
18

Ik ga ervan uit dat u de frequenties op te slaan als floating point getallen tussen 0 en 1, die in totaal te maken 1.

Eerst moet je een tabel met cumulatieve frequenties te bereiden, dat wil zeggen de som van de frequentie van die brief en alle letters voordat het.

Ter vereenvoudiging, als je begint met deze frequentie verdeling:

A  0.1
B  0.3
C  0.4
D  0.2

Uw cumulatieve frequentietabel zou zijn:

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)

Nu is het genereren van een willekeurig getal tussen 0 en 1 en zien waar in deze lijst dat getal ligt. Kies de brief dat de kleinste cumulatieve frequentie groter is dan je willekeurig getal heeft. Een paar voorbeelden:

Stel dat je willekeurig plukken 0,612. Het ligt tussen 0,4 en 0,8, dat wil zeggen tussen B en C, zodat u C. zou kiezen

Als je willekeurig getal 0,039 was, dat komt voor 0,1, dat wil zeggen vóór A, dus kies A.

Ik hoop dat zinvol is, anders voel je vrij om te vragen om opheldering!

antwoordde op 27/01/2010 om 21:20
bron van user

stemmen
4

Niet eens een pseudo-code, maar een mogelijke aanpak is als volgt:

Laat P1, P2, ..., pk zijn de frequenties die u wilt aan te passen.

  1. Bereken de cumulatieve frequenties: p1, p1 + p2, p1 + p2 + p3, ..., 1
  2. Genereer een willekeurige uniform (0,1) getal x
  3. Controleer welke interval van de cumulatieve frequenties x aangesloten: als het tussen bijvoorbeeld p1 + .. + pi en p1 + ... + pi + p (i + 1), vervolgens via de (i + 1) ste letter

Afhankelijk van hoe u het interval-finding te voeren, de procedure is meestal efficiënter als de P1, P2, ... gesorteerd in aflopende volgorde, omdat je meestal vindt u de interval waarin x eerder.

antwoordde op 27/01/2010 om 21:20
bron van user

stemmen
5

Wat ik zou doen is de schaal van de relatieve frequenties als floating point getallen zodanig dat hun som is 1,0. Dan zou ik een array van het creëren cumulatieve totalen per brief, dat wil zeggen het nummer dat moet worden aangevuld met die letter en al die "onder" het te krijgen. Zeggen de frequentie van A is 10%, b 2% en z is 1%; dan zou uw tafel er als volgt uitzien:

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

Vervolgens genereert u zelf een willekeurig getal tussen 0,0 en 1,0 en doe een binary search in de reeks voor het eerste getal kleiner dan je random number. Vervolgens kiest u de brief op die positie. Gedaan.

antwoordde op 27/01/2010 om 21:23
bron van user

stemmen
2

Met behulp van een binaire boom geeft je een mooie, schone manier om de juiste ingang te vinden. Hier begin je met een frequencykaart, waar de toetsen zijn de symbolen (Engels letters), en de waarden van de frequentie van voorkomen. Dit wordt omgekeerd, en NavigableMapwordt gecreëerd waarin de keys cumulatieve kans en de waarden symbolen. Dat maakt de lookup gemakkelijk.

  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();
  }
antwoordde op 27/01/2010 om 22:10
bron van user

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