Aiuto! Ho più compiti!


18

La mia insegnante era più che scontenta dei miei compiti marziani . Ho seguito tutte le regole, ma lei dice che quello che ho prodotto era incomprensibile ... quando l'ha guardato per la prima volta, era altamente sospettosa. "Tutte le lingue dovrebbero seguire la legge di Zipf blah blah blah" ... Non sapevo nemmeno quale fosse la legge di Zipf!

Si scopre che la legge di Zipf afferma che se si traccia il logaritmo della frequenza di ogni parola sull'asse y e il logaritmo del "posto" di ogni parola sull'asse x (più comune = 1, secondo più comune = 2, terzo più comune = 3, e così via), quindi la trama mostrerà una linea con una pendenza di circa -1, dare o prendere circa il 10%.

Ad esempio, ecco una trama per Moby Dick:

inserisci qui la descrizione dell'immagine

L'asse x è la n ° parola più comune, l'asse y è il numero di occorrenze della n esima parola più comune. La pendenza della linea è di circa -1,07.

Ora stiamo coprendo Venutian. Per fortuna, i Venutiani usano l'alfabeto latino. Le regole sono le seguenti:

  • Ogni parola deve contenere almeno una vocale (a, e, i, o, u)
  • In ogni parola possono esserci fino a tre vocali di fila, ma non più di due consonanti di fila (una consonante è qualsiasi lettera che non è una vocale).
  • Non ci sono parole più lunghe di 15 lettere
  • Opzionale: raggruppa le parole in frasi lunghe 3-30 parole, delimitate da punti

Poiché l'insegnante sente che ho tradito i miei compiti marziani, mi è stato assegnato il compito di scrivere un saggio lungo almeno 30.000 parole (in venutiano). Controllerà il mio lavoro usando la legge di Zipf, quindi quando una linea è montata (come descritto sopra) la pendenza deve essere al massimo di -0,9 ma non meno di -1,1 e vuole un vocabolario di almeno 200 parole. La stessa parola non deve essere ripetuta più di 5 volte di seguito.

Questo è CodeGolf, quindi vince il codice più breve in byte. Incolla l'output su Pastebin o su un altro strumento in cui posso scaricarlo come file di testo.


Sì, e se vuoi, puoi semplicemente pronunciare una frase di 32767 parole. La restrizione è che le frequenze delle parole nella frase devono seguire la legge di zipf
J. Antonio Perez,

1
L'aggettivo tradizionale per "da Venere" è Venerale, ma per qualche ragione è diminuito in popolarità. Venusian è comunemente usato nella fantascienza.
Peter Taylor,

Sto ipotizzando che la costruzione di un elenco di parole dopo la distribuzione di zipf e la mescolazione avrebbe un'alta probabilità di produrre una sequenza con coppie di parole consecutive anche dopo la distribuzione di zipf. Inoltre, con abbastanza parole diverse nell'elenco la probabilità di avere la stessa parola ripetuta più di 5 volte di seguito sarebbe davvero piccola. Nel caso in cui ho provato questo approccio e sono riuscito a produrre un saggio valido, sarebbe accettato?
Leone,

La tua congettura è ragionevole, anche se la pendenza sarebbe -0.35
J. Antonio Perez il

Sembrerebbe comunque una linea retta; è solo che la pendenza sarebbe troppo grande
J. Antonio Perez il

Risposte:


3

Mathematica, 102 byte

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

Funzione senza nome che non accetta input e restituisce una stringa composta da 40.320 parole venusiane di tre lettere con spazi finali.

Outer[StringJoin,a={"v","a","e","i","o","u"},a,a,{" "}]produce le 216 parole di tre lettere possibili usando solo le lettere "vaeiou", ognuna con il proprio spazio finale. La prima di queste parole, "vvv", non è valida venusiana, ma la Restbutta via.

Quindi RandomChoice[1/Range@215->...,8!]fa 8! = 40.320 scelte casuali dall'elenco di 215 parole risultante, con pesi di frequenza determinati dai reciproci dei primi 215 numeri interi ( 1/Range@215). Infine, <>""...concatena le stringhe nell'elenco risultante.

L'output è tutt'altro che deterministico; una corsa ha prodotto questo saggio venusiano .

Mathematica, 129 byte

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

Questo è deterministico. L'insieme base di 215 parole è lo stesso, ma ora ogni parola viene ripetuta un numero esatto di volte (la parola #j viene ripetuta all'incirca 7! / J volte) per forzare la legge di zipf. Quindi le parole vengono scambiate equamente per evitare ripetizioni. (Immagina che ogni parola sia disposta su un righello, con tutte le copie di quella parola equidistanti; quando tutte le parole sono lette in ordine, nessuna parola particolare si ripeterà molto, forse per niente.) Il risultato è una parola di 30.117 parole Saggio venusiano .


Non fare 8! scelta pseudo-casuale significa che potresti finire con 6 ripetizioni consecutive della stessa parola?
Dennis il

Sì, in teoria.
Greg Martin,

@GregMartin In realtà ... il saggio a cui ti sei collegato non è conforme; vvaappare sei volte consecutive. Penso che ci sia forse un problema più grande ... non dovresti sfidare le risposte a lavorare ogni volta? (E in caso contrario, come si fa a tracciare la linea di probabilità che dovrebbero funzionare?)
H Walters,

Questa è una critica giusta, e sono interessato a vedere come va.
Greg Martin,

2

05AB1E ,34 33 32 byte

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

Provalo online!

Penso che sia ancora abbastanza giocabile! Ad esempio le costanti numeriche e vNy<FD}potrebbero essere giocabili a golf.

Esempio di output

Come funziona?

Genera tutte le combinazioni di parole seguendo la regola "vocale + vocale + consonante", che rende 525 parole valide uniche (più di 200). Quindi associa a ciascuno di essi una frequenza che soddisfa la legge in f(x) = 4725/xcuixè il rango della parola corrente, che inizia con 1 e termina con 525. Quindi le frequenze vengono normalizzate e moltiplicate in modo che vi siano almeno 30000 parole. Questo codice restituisce sempre 32074 parole per rendere golfabili le costanti coinvolte (vedere la spiegazione del codice). Quindi ogni parola viene ripetuta per il numero di volte corrispondente alla frequenza della stessa parola. Alla fine le parole vengono mescolate. Tuttavia non garantisce che una parola non venga mai ripetuta cinque volte di seguito. Quindi i programmi generano più delle 200 parole univoche necessarie per ridurre la probabilità che una parola venga ripetuta cinque volte di seguito. Si noti che questo codice genera sempre la stessa sequenza di parole. L'unica cosa che differisce tra due corse è il risultato dell'operazione di mescolamento.

Come valutare la frequenza?

Ho creato un semplice codice Python3 che prende il testo nel file chiamato "output" (dal punto di vista dell'algoritmo, ha senso!) E l'output in "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")

Che produce sempre la seguente distribuzione per il mio codice: Legge sulla frequenza

Quindi la pendenza è -1.0138. Questo valore è ora meno vicino a -1 della pendenza del codice precedente, ma soddisfa ancora i vincoli di pendenza.


Grazie per lo script per valutare la frequenza, nota che hai un extra `alla fine. Inoltre, perché usi i punti e virgola come separatori? csv di solito sta per valori separati da virgola;)
Leo

1
Sì hai ragione haha! Mi sono confuso con Markdown per un secondo. Ho usato prima il codice inline, poi ho capito che era più appropriato usare un blocco di codice ma ho dimenticato di rimuovere il `extra. Uso i punti e virgola come separatori CSV perché sono francese e alcuni software o società sono abituati a inserire valori decimali con virgole anziché punti come facciamo con valori decimali scritti a mano. Anche se uso sempre il punto per separare la parte intera dalla parte frazionaria, uso il punto e virgola senza pensarci più. Ma hey, anche ssv è eccezionale;)
Osable il

0

Utilità Bash / Core, 122 110 byte

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)

srotolato:

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)

Il for wciclo genera 243 parole distinte. let ++x;gli incrementi inizialmente non impostati x (per le regole di espressione aritmetica durante quella prima esecuzione, xviene trattato come 0 e quindi il suo incremento lo imposta su 1). La riga successiva genera quindi le parole successive alla frequenza 5575 / x per approssimare la frequenza zipf.

Il prossimo passo è permetterlo in modo deterministico di adattarsi al requisito di ripetizione; nonostante --random-sourcesia un nome di bandiera terribilmente grande, usarlo con shuf batte il conteggio dei caratteri della mano che rotola un selettore mul-mod. yes aeè in realtà il dispositivo "casuale" fisso più corto che ho trovato conforme.

Questo genera questo saggio di 33729 parole [pastebin] .

Utilità Bash / Core, 96 84 byte (non concorrenti)

Per un approccio non deterministico, basta tagliare i flag 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

Analisi

La pendenza zipf è ottimizzata per essere dritta. Utilizzo di Excel per tracciare su scale logaritmiche:

L'insegnante dovrebbe notare una pendenza zipf di = -1.000764.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.