Tilfeldig generere Letters Ifølge deres bruksfrekvens?

stemmer
10

Hvordan kan jeg tilfeldig generere bokstaver i henhold til deres bruksfrekvens i felles tale?

Enhver pseudo-kode verdsatt, men en implementasjon i Java ville være fantastisk. Ellers bare et dytt i riktig retning ville være nyttig.

Merk: Jeg trenger ikke å generere frekvensene av bruk - Jeg er sikker på at jeg kan se at opp lett nok.

Publisert på 27/01/2010 klokken 20:11
kilden bruker
På andre språk...                            


5 svar

stemmer
11

En rask måte å gjøre det ville være å generere en liste av bokstaver, hvor hver bokstav dukket opp i listen i samsvar med sin frekvens. Si, hvis "e" ble brukt 25,6% av tiden, og listen hadde lengde 1000, ville det ha 256 "e" s.

Da kan du bare tilfeldig plukke flekker fra listen ved å bruke (int) (Math.random() * 1000)til å generere tilfeldige tall mellom 0 og 999.

Svarte 27/01/2010 kl. 20:14
kilden bruker

stemmer
18

Jeg antar at du lagrer frekvensene som flyttall mellom 0 og 1 som totalt å lage en.

Først bør du forberede en tabell over kumulative frekvenser, det vil si summen av hyppigheten av bokstaven og alle bokstavene før det.

For å forenkle, hvis du starter med dette frekvensfordeling:

A  0.1
B  0.3
C  0.4
D  0.2

Din kumulativ frekvens bord vil være:

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)

Nå generere et tilfeldig tall mellom 0 og 1, og se hvor i denne listen som nummer ligger. Velg bokstaven som har den minste kumulative frekvensen større enn tilfeldig tall. Noen eksempler:

Si at du tilfeldig plukke 0.612. Denne ligger mellom 0,4 og 0,8, dvs. mellom B og C, slik at du vil velge C.

Hvis tilfeldig tall var 0.039, som kommer før 0.1, dvs. før A, så velg A.

Jeg håper det er fornuftig, ellers gjerne spørre om avklaringer!

Svarte 27/01/2010 kl. 20:20
kilden bruker

stemmer
4

Ikke engang en pseudo-kode, men en mulig tilnærming er som følger:

La p1, p2, ..., pk være frekvensene som du ønsker å matche.

  1. Beregn den kumulative frekvenser: p1, p1 + p2, p1 + p2 + p3, ..., 1
  2. Generer et tilfeldig uniform (0,1) nummer x
  3. Sjekk hvilket intervall av de kumulative frekvenser x tilhører: hvis det er mellom f.eks p1 + .. + pi og P1 + ... + pi + p (i + 1), deretter utgangs den (i + 1) m bokstav

Avhengig av hvordan du implementerer intervallet-funn, er prosedyren vanligvis mer effektivt hvis p1, p2, ... er sortert i synkende rekkefølge, fordi du vil som regel finne intervall som inneholder x raskere.

Svarte 27/01/2010 kl. 20:20
kilden bruker

stemmer
5

Hva jeg vil gjøre er å skalere de relative frekvensene som flyttall, slik at deres sum er 1,0. Da ville jeg lage en rekke av de kumulative summer pr brev, det vil si antallet som må fylles for å få bokstaven og alle de "under" det. Si frekvensen av A er 10%, b er 2% og z er 1%; deretter bordet ditt vil se omtrent slik ut:

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

Deretter genererer du deg selv et tilfeldig tall mellom 0,0 og 1,0 og gjøre et binært søk i rekken for det første tallet mindre enn din tilfeldig tall. Deretter plukke brevet på den posisjonen. Ferdig.

Svarte 27/01/2010 kl. 20:23
kilden bruker

stemmer
2

Ved hjelp av en binær treet gir deg en fin, ren måte å finne riktig inngang. Her starter du med et frequencykart, hvor tastene er symboler (engelsk bokstaver), og verdiene er hyppigheten av deres forekomst. Dette blir invertert, og NavigableMaper opprettet hvor tastene er kumulative sannsynlighet, og verdiene er symboler. Som gjør oppslag enkelt.

  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();
  }
Svarte 27/01/2010 kl. 21:10
kilden bruker

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