diff --git a/README.md b/README.md index ec0c894..0d251b7 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ и т.д. -Как видим, такой подход не позволяет нам генерировать слова, которые хотя бы отдалённо напоминали обычные - получается просто набор бысмысленных букв, который больше походит на пароли. +Как видим, такой подход не позволяет нам генерировать слова, которые хотя бы отдалённо напоминали обычные - получается просто набор бессмысленных букв, который больше походит на пароли. Чтобы придать словам натуральность и "человечность", нам нужно сделать как минимум две вещи (на мой взгляд): 1) Исключить появления более двух гласных/согласных при генерировании слова. Данная задача является тривиальной и ее не имеет смысла рассматривать. @@ -25,16 +25,7 @@ Используя всего два этих подхода, мы генерируем гораздо более натуральные "слова". Примеры: -- haetise -- earyn -- sayuri -- oathe -- aulnelo -- ureon -- reirgas -- theele - -и т.д. +![screenshot_0.png](https://github.com/bernd32/nickname-generator/blob/main/screenshots/screenshot_0.png?raw=true) ## Алгоритм выбора случайных элементов массива на основе весов в JS Относительно простой имплементацией подобного алгоритма является преобразование ряда рациональных чисел s1 (массива), являющимися весами для элементов, в ряд чисел s2, который @@ -47,14 +38,17 @@ Разберём алгоритм по шагам в JS: 1) Создаём в качестве примера два массива ``items`` и ``weights``, где ``items`` - это элементы, которые будут выбираться случайно, а ``weights`` - это весы этих элементов: -`const items = [ '🍌', '🍎', '🥕' ];` - -`const weights = [ 3, 7, 1 ];` +```javascript +const items = [ '🍌', '🍎', '🥕' ]; +const weights = [ 3, 7, 1 ]; +``` 2) Подготавливаем массив весов посредством кумулятивного сложения (то есть список ``cumulativeWeights``, который будет иметь то же количество элементов, что и исходный список весов ``weights``). В нашем случае такой массив будет выглядеть следующим образом: -` cumulativeWeights = [3, 3 + 7, 3 + 7 + 1] = [3, 10, 11] ` +```javascript +cumulativeWeights = [3, 3 + 7, 3 + 7 + 1] = [3, 10, 11] +``` 3) Генерируем случайное число `randomNumber` от `0` до самого высокого кумулятивного значения веса. В нашем случае случайное число будет находиться в диапазоне `[0..11]`. Допустим, что `randomNumber = 8`. @@ -65,24 +59,24 @@ Попробую наглядно показать это на нашем примере: +```javascript +const weights = [3, 7, 1 ]; - const weights = [3, 7, 1 ]; +const cumulativeWeights = [3, 10, 11]; - const cumulativeWeights = [3, 10, 11]; +// В псевдопредставлении мы можем представить cumulativeWeights следующим образом: - // В псевдопредставлении мы можем представить cumulativeWeights следующим образом: +const pseudoCumulativeWeights = [ - const pseudoCumulativeWeights = [ + 1, 2, 3, // <-- [3] числа - 1, 2, 3, // <-- [3] числа + 4, 5, 6, 7, 8, 9, 10, // <-- [7] чисел - 4, 5, 6, 7, 8, 9, 10, // <-- [7] чисел - - 11, // <-- [1] число +11, // <-- [1] число - ]; - -Как видим, более тяжёлые весы занимают более высокое числовое пространство, а следовательно, имеют более высокий шанс быть случайно выбранными. Процентное соотношение шанса выбора для элементо `weights` будет таким: +]; +``` +Как видим, более тяжёлые весы занимают более высокое числовое пространство, а следовательно, имеют более высокий шанс быть случайно выбранными. Процентное соотношение шанса выбора для элементов `weights` будет таким: Элемент `3`: ≈ 27%, @@ -102,22 +96,24 @@ и т.д. Самым простым решением этого вопроса является ограничение на чередование более двух гласных/согласных слов: - - if (vowelCounter >= maxVowelsInRow) { - i -= 1; - continue; - } - +```javascript +if (vowelCounter >= maxVowelsInRow) { + i -= 1; + continue; +} +``` и - - if (consonantCounter >= maxConsonantsInRow) { - i -= 1; - continue; - } - +```javascript +if (consonantCounter >= maxConsonantsInRow) { + i -= 1; + continue; +} +``` Пусть значения maxConsonantsInRow = 1 и maxVowelsInRow = 1, тогда сгенерированые слова будут выглядеть примерно так: +![screenshot_1.png](https://github.com/bernd32/nickname-generator/blob/main/screenshots/screenshot_1.png?raw=true) -Отметим, что th и ae являются диграмами, и считаются как одна буква. + +Отмечу здесь, что th и ae являются диграмами, и считаются как одна буква. Очевидной минус данного подхода заключается в том, что сгенерированные слова получаются более однотипными и с гораздо меньшим вариативным потенциалом. \ No newline at end of file