Помогите! У меня больше домашней работы!

18

Мой учитель был более чем недоволен моей домашней работой . Я следовал всем правилам, но она говорит, что то, что я вывел, было бредом ... когда она впервые посмотрела на это, она была очень подозрительна. «Все языки должны следовать закону Ципфа, бла-бла-бла» ... Я даже не знал, что такое закон Ципфа!

Оказывается, закон Ципфа гласит, что если вы построите логарифм частоты каждого слова на оси у и логарифм «места» каждого слова на оси х (наиболее часто = 1, второй наиболее часто = 2, третье наиболее распространенное = 3 и т. д.), тогда на графике будет показана линия с уклоном около -1, с положительным или отрицательным значением около 10%.

Например, вот сюжет для Моби Дика:

введите описание изображения здесь

Ось x - это n- е наиболее распространенное слово, а ось y - количество вхождений n- го наиболее распространенного слова. Наклон линии около -1.07.

Теперь мы покрываем Venutian. К счастью, венецианцы используют латинский алфавит. Правила следующие:

  • Каждое слово должно содержать хотя бы одну гласную (a, e, i, o, u)
  • В каждом слове может быть до трех гласных подряд, но не более двух согласных подряд (согласная - это любая буква, которая не является гласной).
  • Нет слов длиннее 15 букв
  • Необязательно: сгруппируйте слова в предложения длиной 3-30 слов, разделенных точками

Поскольку учитель считает, что я изменял своему домашнему заданию на марсианском языке, мне поручили написать эссе длиной не менее 30 000 слов (на венетском). Она собирается проверить мою работу, используя закон Ципфа, поэтому, когда линия соответствует (как описано выше), наклон должен составлять не более -0,9, но не менее -1,1, и она хочет словарный запас не менее 200 слов. Одно и то же слово не должно повторяться более 5 раз подряд.

Это CodeGolf, поэтому выигрывает самый короткий код в байтах. Пожалуйста, вставьте вывод в Pastebin или другой инструмент, где я могу загрузить его в виде текстового файла.

Х. Антонио Перес
источник
Да, и если вы хотите, вы можете просто сделать предложение из 32767 слов. Ограничение состоит в том, что частоты слов в предложении должны соответствовать закону Зипфа
Х. Антонио Перес
1
Традиционное прилагательное для «от Венеры» венерическое, но по какой-то причине его популярность снизилась. Венерианский обычно используется в научной фантастике.
Питер Тейлор
Я предполагаю, что построение списка слов после распределения zipf и перетасовка его с большой вероятностью приведут к созданию последовательности с парами последовательных слов, также следующих за распределением zipf. Более того, при достаточном количестве разных слов в списке вероятность повторения одного и того же слова более 5 раз подряд будет очень мала. Если я попробую этот подход и смогу подготовить достоверное эссе, будет ли оно принято?
Лев
Ваша гипотеза обоснована, хотя уклон будет -0,35
Х. Антонио Перес
Это все равно будет выглядеть как прямая линия; просто уклон был бы слишком велик
Х. Антонио Перес

Ответы:

3

Mathematica, 102 байта

""<>RandomChoice[1/Range@215->Rest@Flatten@Outer[StringJoin,a={"v","a","e","i","o","u"},a,a,{" "}],8!]

Безымянная функция не принимает и возвращает строку, состоящую из 40 320 трехбуквенных венерианских слов с завершающими пробелами.

Outer[StringJoin,a={"v","a","e","i","o","u"},a,a,{" "}]создает 216 трехбуквенных слов, которые можно использовать, используя только буквы «vaeiou», каждое со своим собственным пробелом. Первое из этих слов, «vvv», не является действительным венерианцем, но Restвыбрасывает его.

Тогда RandomChoice[1/Range@215->...,8!]делает 8! = 40 320 случайных выборов из результирующего списка из 215 слов, с частотными весами, определенными на основе обратных значений первых 215 целых чисел ( 1/Range@215). Наконец, <>""...объединяет строки в результирующем списке.

Выход далеко не детерминирован; один прогон дал это эссе о Венере .

Mathematica, 129 байт

#2&@@@Sort[Join@@Table[{i,Rest@Flatten@Outer[StringJoin,a={"v","a","e","i","o","u"},a,a,{" "}]~Part~j},{j,215},{i,0,1,j/7!}]]<>""

Этот является детерминированным. Базовый набор из 215 слов одинаков, но теперь каждое слово повторяется точное количество раз (слово #j повторяется примерно 7! / J раз), чтобы заставить закон Ципфа соблюдать. Затем слова чередуются одинаково, чтобы избежать повторений. (Представьте, что каждое слово выложено на линейке, причем все копии этого слова расположены на одинаковом расстоянии; когда все слова прочитаны по порядку, никакое конкретное слово не повторится много, возможно, совсем не будет.) В результате получается 30 117 слов. Венерианский очерк .

Грег Мартин
источник
Не делает 8! псевдослучайный выбор означает, что вы можете получить 6 последовательных повторений одного и того же слова?
Деннис
Да, в теории.
Грег Мартин
@GregMartin На самом деле ... эссе, на которое вы ссылаетесь, не соответствует требованиям; vvaпоявляется шесть раз подряд. Я думаю, что, возможно, есть более серьезная проблема, хотя ... разве вызовы ответов не должны работать каждый раз? (А если нет, то как вы рисуете линию того, насколько вероятно, что они должны работать?)
Х Уолтерс
Это справедливая критика, и мне интересно посмотреть, как она закончится.
Грег Мартин
2

05AB1E ,34 33 32 байта

525DL/9*vNy<FD}})žMDâžNâJè3ô.rðý

525DL                            Yield [1, ..., 525]
     /                           Yield [525/1, ..., 525/525]
      9*                         Yield [4725/1, ..., 4725/525]. It's the number of occurences of each word. The sum of this array is greater than 30000
        v                        For each value (y = value, N = iteration counter starting from 0)
         N                       Push iteration counter
          y<FD}                  Push an array of "int(value)" times the iteration counter
               }                 End for
                )                Wrap everything in an array. At this point the array countains the sorted indices of all words that matches the frequency specs
                 žM              Push "aeiou"
                   Dâ            Cartesian product with itself (["aa", "ae", ...])
                     žN          Push the consonants
                       âJ        Cartesian product and join the values to make valid venutian words
                         è       Compute a big string with all words that correspond to the formerly computed indices
                          3ô     Since all words are concatenated, separate them into blocks of 3 letters
                            .r   Shuffle
                              ðý Join with whitespaces and implicitly display

Попробуйте онлайн!

Я думаю, что это все еще довольно играбельно! Например, числовые константы и vNy<FD}могут быть пригодными для игры в гольф.

Пример вывода

Как это работает?

Он генерирует все комбинации слов, следуя правилу «гласный + гласный + согласный», что составляет 525 уникальных допустимых слов (более 200). Затем он ассоциирует с каждым из них частоту, которая удовлетворяет закону, f(x) = 4725/xгдеxэто ранг текущего слова, начинающийся с 1 и заканчивающийся на 525. Затем частоты нормализуются и умножаются так, чтобы было не менее 30000 слов. Этот код всегда дает 32074 слова, чтобы сделать соответствующие константы пригодными для игры (см. Объяснение кода). Таким образом, каждое слово повторяется количество раз, соответствующее частоте одного и того же слова. Наконец слова перемешиваются. Однако это не гарантирует, что слово никогда не будет повторяться пять раз подряд. Следовательно, программы генерируют более 200 уникальных слов, чтобы уменьшить вероятность повторения слова пять раз подряд. Обратите внимание, что этот код всегда генерирует одну и ту же последовательность слов. Единственное, что отличается между двумя прогонами, это результат операции тасования.

Как оценить частоту?

Я сделал простой код Python3, который берет текст в файле с именем «output» (с точки зрения алгоритма это имеет смысл!) И выводит его в «stats.csv».

from collections import Counter
from math import log10

with open("output", "r") as f:
    with open("stats.csv", "w") as stats:
        words = f.read().split()
        freqs = Counter(words)
        freqs = sorted([(i,freqs[i]) for i in freqs],key=lambda x:-x[1])

        print(len(words), "words")
        stats.write("logX;logF\n")
        for i, (key, f) in enumerate(freqs):
            stats.write(str(log10(i+1))+";"+str(log10(f))+"\n")

Который всегда дает следующий дистрибутив для моего кода: Частотный закон

Таким образом, уклон -1.0138. Это значение теперь менее близко к -1, чем уклон предыдущего кода, но все же удовлетворяет ограничениям наклона.

Osable
источник
Спасибо за скрипт для оценки частоты, обратите внимание, что у вас есть дополнительный `в конце. Кроме того, почему вы используете точки с запятой в качестве разделителей? csv обычно обозначает значения, разделенные запятыми;)
Лев
1
Да, ты прав, ха-ха! Я запутался с уценкой на секунду. Сначала я использовал встроенный код, затем понял, что более целесообразно использовать блок кода, но я забыл удалить лишний `. Я использую точки с запятой в качестве разделителей csv, потому что я француз, и некоторые программы или компании привыкли ставить десятичные значения с запятыми вместо точек, как мы делаем с рукописными десятичными значениями. Хотя я всегда использую точку, чтобы отделить целую часть от дробной, я использую точку с запятой, не задумываясь. Но эй, ssv также
хорош
0

Bash / Core Utils, 122 110 байт

for w in {b,c,d}{a,e,i}{f,g,h}{o,u,a}{j,k,l};{ let ++x;yes $w|head -$[5575/x];}|shuf --random-source=<(yes ae)

раскатали:

for w in {b,c,d}{a,e,i}{f,g,h}{o,u,a}{j,k,l};{
    let ++x
    yes $w|head -$[5575/x]
}|shuf --random-source=<(yes ae)

for wЦикл генерирует 243 различных слов. let ++x;инкрементно изначально устанавливает x (для каждого правила арифметического выражения во время этого первого выполнения xобрабатывается как 0 и, следовательно, его приращение устанавливает его в 1). Следующая строка, таким образом, генерирует последующие слова на частоте 5575 / x, чтобы приблизить частоту zipf.

Следующий шаг состоит в том, чтобы переставить это детерминистически, чтобы соответствовать требованию повторения; Несмотря на то, --random-sourceчто это очень большое имя флага, использование его с shuf превосходит количество символов, используемых при переключении мультимодного селектора. yes aeна самом деле это самое короткое фиксированное «случайное» устройство, которое я нашел соответствующим.

Это создает это 33729 слов эссе [pastebin] .

Bash / Core Utils, 96 84 байта (не конкурирует)

Для недетерминированного подхода просто отрубите флаги shuf:

for w in {b,c,d}{a,e,i}{f,g,h}{o,u,a}{j,k,l};{ let ++x;yes $w|head -$[5575/x];}|shuf

Анализ

Наклон Zipf настроен так, чтобы он был прямым. Использование Excel для построения графиков в логарифмических масштабах:

Учитель должен заметить наклон zipf = -1.000764.

H Уолтерс
источник