Случайная Генерация Письма По их частоте использования?

голоса
10

Как я могу генерировать случайным образом буквы в соответствии с их частотой использования в обычной речи?

Любой псевдокод ценится, но реализация в Java будет фантастической. В противном случае просто тыкать в правильном направлении было бы полезно.

Примечание: мне не нужно, чтобы генерировать частоты использования - я уверен, что я могу посмотреть, что до достаточно легко.

Задан 27/01/2010 в 21:11
источник пользователем
На других языках...                            


5 ответов

голоса
11

Один быстрый способ сделать это было бы создать список писем, где каждая буква появилась в списке в соответствии с его частотой. Скажем, если «е» было использовано 25,6% времени, а список был длиной 1000, она будет иметь 256 «е» с.

Тогда вы можете просто случайно выбрать места из списка, используя (int) (Math.random() * 1000)для генерации случайных чисел в диапазоне от 0 до 999.

Ответил 27/01/2010 в 21:14
источник пользователем

голоса
18

Я предполагаю, что вы будете хранить частоты, число с плавающей точкой между 0 и 1, что общим сделать 1.

Во-первых, вы должны подготовить таблицу кумулятивных частот, т.е. сумму частоты этого письма и все письма до него.

Для упрощения, если вы начнете с этим распределением частот:

A  0.1
B  0.3
C  0.4
D  0.2

Ваша совокупная таблица частот будет:

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)

Теперь генерировать случайное число в диапазоне от 0 до 1 и увидеть, где в этом списке, что число лежит. Выберите букву, которая имеет наименьшую кумулятивную частоту больше, чем ваш случайное число. Некоторые примеры:

Допустим, вы случайно выбрать 0,612. Это лежит в диапазоне от 0,4 до 0,8, то есть между B и C, так что вы выбрали бы C.

Если случайное число было 0,039, что предшествует 0,1, то есть до А, так выберите A.

Я надеюсь, что имеет смысл, в противном случае, не стесняйтесь обратиться за разъяснения!

Ответил 27/01/2010 в 21:20
источник пользователем

голоса
4

Не даже псевдо-код, но возможный подход заключается в следующем:

Пусть p1, p2, ..., рк частоты, которые вы хотите, чтобы соответствовать.

  1. Расчет кумулятивных частот: p1, p1 + p2, p1 + p2 + p3, ..., 1
  2. Генерировать случайную форму (0,1) число х
  3. Проверьте, какой интервал кумулятивных частот х принадлежит: если, скажем, между p1 + .. + пи и p1 + ... + р + р (я + 1), то вывести (я + 1) -м буквы

В зависимости от того, как вы реализуете интервал-вывод, процедура, как правило, более эффективно, если p1, p2, ... отсортированы в порядке убывания, потому что, как правило, найти интервал, содержащий х раньше.

Ответил 27/01/2010 в 21:20
источник пользователем

голоса
5

Что я хотел бы сделать это масштабировать относительные частоты , как числа с плавающей точкой , такими , что их сумма равна 1,0. Тогда я хотел бы создать массив из кумулятивных сумм в письме, то есть число , которое должно быть увенчана , чтобы получить это письмо и всех тех , кто «ниже» это. Скажем , частота А составляет 10%, Ь 2% , а г = 1%; то ваша таблица будет выглядеть примерно так:

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

Тогда вы создаете себе случайное число в диапазоне от 0,0 до 1,0 и сделать бинарный поиск в массиве для первого числа меньше вашего случайного числа. Затем выберите букву в этой позиции. Готово.

Ответил 27/01/2010 в 21:23
источник пользователем

голоса
2

Использование двоичного дерева дает хороший, чистый способ найти правильную запись. Здесь, вы начинаете с frequencyкартой, где ключи являются символами (английские буквы), а значения частоты их возникновения. Это инвертируется, и NavigableMapсоздается где ключи кумулятивная вероятность, а значения символов. Это делает поиск легким.

  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();
  }
Ответил 27/01/2010 в 22:10
источник пользователем

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