Wsparcie! Mam więcej pracy domowej!

18

Mój nauczyciel był bardziej niż niezadowolony z mojej pracy domowej na Marsie . Przestrzegałem wszystkich zasad, ale ona powiedziała, że ​​to, co wydałem, było bełkotem ... kiedy po raz pierwszy na to spojrzała, była bardzo podejrzliwa. „Wszystkie języki powinny być zgodne z prawem Zipfa bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla

Okazuje się, że prawo Zipfa stwierdza, że ​​jeśli wykreślisz logarytm częstotliwości każdego słowa na osi y, i logarytm „miejsca” każdego słowa na osi x (najczęściej = 1, drugi najczęściej = 2, 3. najbardziej commmon = 3 itd.), następnie wykres pokaże linię o nachyleniu około -1, da lub zajmie około 10%.

Na przykład, oto fabuła dla Moby Dicka:

wprowadź opis zdjęcia tutaj

Oś x jest n- tym najczęściej używanym słowem, oś y to liczba wystąpień n- tego najczęściej używanego słowa. Nachylenie linii wynosi około -1,07.

Teraz omawiamy Wenutian. Na szczęście Wenucjanie używają alfabetu łacińskiego. Reguły są następujące:

  • Każde słowo musi zawierać co najmniej jedną samogłoskę (a, e, i, o, u)
  • W każdym słowie mogą znajdować się maksymalnie trzy samogłoski z rzędu, ale nie więcej niż dwie spółgłosek z rzędu (spółgłoska to każda litera, która nie jest samogłoską).
  • Brak słów dłuższych niż 15 liter
  • Opcjonalnie: pogrupuj słowa w zdania o długości 3-30 słów, oddzielone kropkami

Ponieważ nauczyciel uważa, że ​​oszukałem pracę domową na Marsie, powierzono mi napisanie eseju o długości co najmniej 30 000 słów (po wenecku). Zamierza sprawdzić moją pracę na podstawie prawa Zipfa, więc kiedy dopasowana jest linia (jak opisano powyżej) nachylenie musi wynosić co najwyżej -0,9, ale nie mniej niż -1,1, i chce słownictwa o długości co najmniej 200 słów. Tego samego słowa nie należy powtarzać więcej niż 5 razy z rzędu.

To jest CodeGolf, więc wygrywa najkrótszy kod w bajtach. Wklej dane wyjściowe do Pastebin lub innego narzędzia, z którego mogę je pobrać jako plik tekstowy.

J. Antonio Perez
źródło
Tak, a jeśli chcesz, możesz po prostu zrobić zdanie 32767 słów. Ograniczeniem jest to, że częstotliwości słów w zdaniu muszą być zgodne z prawem zipf
J. Antonio Perez,
1
Tradycyjnym przymiotnikiem „z Wenus” jest Veneral, ale z jakiegoś powodu jego popularność spadła. Venusian jest powszechnie używany w science fiction.
Peter Taylor,
Przypuszczam, że zbudowanie listy słów po dystrybucji zipf i przetasowanie jej miałoby duże prawdopodobieństwo utworzenia sekwencji z parami kolejnych słów również po dystrybucji zipf. Co więcej, przy wystarczającej liczbie różnych słów na liście prawdopodobieństwo powtórzenia tego samego słowa więcej niż 5 razy z rzędu byłoby naprawdę małe. Gdybym spróbował tego podejścia i udało mi się napisać prawidłowy esej, czy zostałby zaakceptowany?
Leo
Twoja hipoteza jest rozsądna, chociaż nachylenie wynosi -0,35
J. Antonio Perez
Nadal wyglądałby jak linia prosta; po prostu nachylenie byłoby zbyt duże
J. Antonio Perez

Odpowiedzi:

3

Mathematica, 102 bajty

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

Nienazwana funkcja nie przyjmuje danych wejściowych i zwraca łańcuch składający się z 40 320 trzyliterowych słów wenusjańskich ze spacjami końcowymi.

Outer[StringJoin,a={"v","a","e","i","o","u"},a,a,{" "}]tworzy 216 trzyliterowych słów, używając tylko liter „vaeiou”, każde z własną spacją. Pierwsze z tych słów, „vvv”, nie jest ważne wenusjańskim, ale Restje wyrzuca.

Potem RandomChoice[1/Range@215->...,8!]robi 8! = 40 320 losowych wyborów z wynikowej listy zawierającej 215 słów, z wagami częstotliwości wyznaczonymi przez odwrotność pierwszych 215 liczb całkowitych ( 1/Range@215). Na koniec <>""...konkatenuje łańcuchy z wynikowej listy.

Wynik jest daleki od deterministycznego; jeden bieg przyniósł ten esej wenusjański .

Mathematica, 129 bajtów

#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!}]]<>""

Ten jest deterministyczny. Podstawowy zestaw 215 słów jest taki sam, ale teraz każde słowo powtarza się dokładnie tyle razy (słowo #j powtarza się około 7! / J razy), aby wymusić utrzymanie prawa zipf. Następnie słowa są przeplatane równo, aby uniknąć powtórzeń. (Wyobraź sobie, że każde słowo jest ułożone na linijce, a wszystkie jego kopie są rozmieszczone w równych odstępach; gdy wszystkie słowa zostaną odczytane w kolejności, żadne konkretne słowo nie będzie się wiele powtarzać, być może wcale). 117 słów Esej wenusjański .

Greg Martin
źródło
Nie robi 8! wybór pseudolosowy oznacza, że ​​możesz skończyć z 6 kolejnymi powtórzeniami tego samego słowa?
Dennis,
Tak, teoretycznie.
Greg Martin
@GregMartin Właściwie ... esej, z którym się łączysz, jest niezgodny; vvapojawia się sześć razy pod rząd. Myślę, że może być większy problem ... czy nie powinno się kwestionować odpowiedzi za każdym razem? (A jeśli nie, to jak narysować granicę prawdopodobieństwa, że ​​powinni oni działać?)
H Walters,
To uczciwa krytyka i jestem ciekawy, jak się to potoczy.
Greg Martin
2

05AB1E ,34 33 32 bajty

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

Wypróbuj online!

Myślę, że wciąż można grać w golfa! Na przykład stałe liczbowe i vNy<FD}mogą być grywalne.

Przykład wyjściowy

Jak to działa?

Generuje wszystkie kombinacje słów zgodnie z regułą „samogłoska + samogłoska + spółgłoska”, co czyni 525 unikalnymi poprawnymi słowami (ponad 200). Następnie przypisuje każdemu z nich częstotliwość zgodną z prawem f(x) = 4725/xgdziexto ranga bieżącego słowa, zaczynająca się od 1, a kończąca na 525. Następnie częstotliwości są znormalizowane i mnożone, więc jest co najmniej 30000 słów. Ten kod zawsze daje 32074 słów, aby zaangażowane w grę stałe były możliwe do gry w golfa (zobacz objaśnienie kodu). Każde słowo powtarza się tyle razy, ile odpowiada częstotliwości tego samego słowa. Wreszcie słowa są tasowane. Nie gwarantuje to jednak, że słowo nigdy nie zostanie powtórzone pięć razy z rzędu. Dlatego programy generują więcej niż potrzebne 200 unikalnych słów, aby zmniejszyć prawdopodobieństwo powtórzenia słowa pięć razy z rzędu. Należy pamiętać, że ten kod zawsze generuje tę samą sekwencję słów. Jedyne, co różni się między dwoma przebiegami, to wynik operacji tasowania.

Jak ocenić częstotliwość?

Stworzyłem prosty kod Python3, który pobiera tekst z pliku o nazwie „output” (z punktu widzenia algorytmu ma to sens!) I wypisuje go do „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")

Co zawsze daje następującą dystrybucję mojego kodu: Prawo częstotliwości

Nachylenie wynosi -1.0138. Ta wartość jest teraz mniej zbliżona do -1 niż nachylenie poprzedniego kodu, ale nadal spełnia ograniczenia nachylenia.

Osable
źródło
Dziękujemy za skrypt oceniający częstotliwość, zauważ, że masz dodatkowe `na końcu. Ponadto, dlaczego używasz średników jako separatorów? csv zwykle oznacza wartości oddzielone przecinkami;)
Leo
1
Tak, masz rację haha! Przez sekundę pomyliłem się z obniżką cen. Najpierw użyłem kodu wbudowanego, a potem zdałem sobie sprawę, że lepiej jest użyć bloku kodu, ale zapomniałem usunąć dodatkowe `. Używam średników jako separatorów csv, ponieważ jestem Francuzem, a niektóre oprogramowanie lub firmy są przyzwyczajone do umieszczania wartości dziesiętnych przecinkami zamiast kropek, tak jak w przypadku odręcznych wartości dziesiętnych. Chociaż zawsze używam kropki, aby oddzielić część całkowitą od części ułamkowej, używam średnika bez dalszego zastanawiania się. Ale hej, ssv też jest świetny;)
Osable
0

Bash / Core Utils, 122 110 bajtów

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)

Rozwinięty:

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 wPętla wytwarza 243 różnych słów. let ++x;początkowo inkrementuje x (zgodnie z regułami wyrażeń arytmetycznych podczas pierwszego wykonania,x jest traktowane jako 0, a zatem jego przyrost ustawia go na 1). W ten sposób następny wiersz generuje kolejne słowa przy częstotliwości 5575 / x w celu przybliżenia częstotliwości zipf.

Następnym krokiem jest permutacyjne ustalenie tego w celu dopasowania do wymogu powtarzania; pomimo --random-sourcetego, że jest to strasznie duża nazwa flagi, użycie jej z shuf bije liczbę znaków ręki toczącej się po selektorze wielu modów. yes aejest właściwie najkrótszym ustalonym „losowym” urządzeniem, które spełniłem.

To generuje 33729 esejów słów [pastebin] .

Bash / Core Utils, 96 84 bajtów (niekonkurujące)

W przypadku podejścia niedeterministycznego po prostu odetnij flagi 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

Analiza

Nachylenie zipf jest ustawione na prostą. Używanie programu Excel do drukowania w skalach logarytmicznych:

Nauczyciel powinien zauważyć nachylenie zipf = -1.000764.

H Walters
źródło