Socorro! Eu tenho mais lição de casa!


18

Meu professor estava mais do que infeliz com meu dever de casa marciano . Eu segui todas as regras, mas ela diz que o que eu produzi foi sem sentido ... quando ela olhou pela primeira vez, ela era altamente suspeita. "Todas as línguas devem seguir a lei de Zipf, blá, blá, blá" ... Eu nem sabia o que era a lei de Zipf!

Acontece que a lei de Zipf afirma que, se você plotar o logaritmo da frequência de cada palavra no eixo y, e o logaritmo do "local" de cada palavra no eixo x (mais comum = 1, segundo mais comum = 2, terceiro mais comum = 3, e assim por diante), o gráfico mostrará uma linha com uma inclinação de cerca de -1, mais ou menos 10%.

Por exemplo, aqui está uma trama para Moby Dick:

insira a descrição da imagem aqui

O eixo x é a n th palavra mais comum, o eixo y é o número de ocorrências do n th palavra mais comum. A inclinação da linha é de cerca de -1,07.

Agora estamos cobrindo Venutian. Felizmente, os venezianos usam o alfabeto latino. As regras são as seguintes:

  • Cada palavra deve conter pelo menos uma vogal (a, e, i, o, u)
  • Em cada palavra, pode haver até três vogais seguidas, mas não mais que duas consoantes seguidas (uma consoante é qualquer letra que não seja uma vogal).
  • Não há palavras com mais de 15 letras
  • Opcional: agrupe palavras em sentenças de 3 a 30 palavras, delimitadas por pontos

Como o professor acha que traí minha lição de casa marciana, fui designado para escrever uma redação com pelo menos 30.000 palavras (em venutiano). Ela vai verificar meu trabalho usando a lei de Zipf; portanto, quando uma linha é ajustada (como descrito acima), a inclinação deve ser no máximo -0,9, mas não inferior a -1,1, e ela quer um vocabulário de pelo menos 200 palavras. A mesma palavra não deve ser repetida mais de 5 vezes seguidas.

Este é o CodeGolf, então o código mais curto em bytes vence. Cole a saída em Pastebin ou outra ferramenta onde eu possa baixá-la como um arquivo de texto.


Sim, e se você quiser, basta fazer uma sentença de 32767 palavras. A restrição é que as frequências das palavras na sentença devem seguir a lei de zipf
J. Antonio Perez

1
O adjetivo tradicional de "de Vênus" é Veneral, mas, por algum motivo, diminuiu sua popularidade. Venusian é comumente usado em ficção científica.
31516 Peter

Suponho que construir uma lista de palavras após a distribuição zipf e embaralhá-la teria uma alta probabilidade de produzir uma sequência com pares de palavras consecutivas também após a distribuição zipf. Além disso, com palavras diferentes suficientes na lista, a probabilidade de repetir a mesma palavra mais de 5 vezes seguidas seria muito pequena. Caso eu tentasse essa abordagem e conseguisse produzir um ensaio válido, ele seria aceito?
Leo

Sua conjectura é razoável, embora a inclinação seja -0,35
J. Antonio Perez

Ainda pareceria uma linha reta; é apenas a inclinação seria muito grande
J. Antonio Perez

Respostas:


3

Mathematica, 102 bytes

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

Função sem nome, sem entrada e retornando uma sequência composta por 40.320 palavras venusianas de três letras com espaços à direita.

Outer[StringJoin,a={"v","a","e","i","o","u"},a,a,{" "}]produz as 216 palavras de três letras possíveis usando apenas as letras "vaeiou", cada uma com seu próprio espaço à direita. A primeira dessas palavras, "vvv", não é venusiana válida, mas a Restjoga fora.

Então RandomChoice[1/Range@215->...,8!]faz 8! = 40.320 escolhas aleatórias da lista de 215 palavras resultante, com pesos de frequência determinados pelos recíprocos dos primeiros 215 números inteiros ( 1/Range@215). Por fim, <>""...concatena as seqüências de caracteres na lista resultante.

A saída está longe de ser determinística; uma corrida rendeu este ensaio venusiano .

Mathematica, 129 bytes

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

Este é determinístico. O conjunto básico de 215 palavras é o mesmo, mas agora cada palavra é repetida um número exato de vezes (a palavra #j é repetida aproximadamente 7! / J vezes) para forçar a lei da zipf. Em seguida, as palavras são intercaladas igualmente para evitar repetições. (Imagine que cada palavra seja colocada em uma régua, com todas as cópias dessa palavra igualmente espaçadas; quando todas as palavras forem lidas em ordem, nenhuma palavra em particular se repetirá muito, talvez nem seja.) O resultado é 30.117 palavras. Ensaio venusiano .


Não faz 8! escolha pseudo-aleatória significa que você pode terminar com 6 repetições consecutivas da mesma palavra?
Dennis

Sim, em teoria.
Greg Martin

@GregMartin Na verdade ... o ensaio ao qual você vinculou não é compatível; vvaaparece seis vezes consecutivas. Eu acho que existe um problema maior ... embora as respostas do desafio não funcionem sempre? (E se não, como você desenhar a linha de como provável é que eles devem estar ao trabalho?)
H Walters

Esta é uma crítica justa, e estou interessado em ver como ela se desenrola.
Greg Martin

2

05AB1E ,34 33 32 bytes

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

Experimente online!

Eu acho que ainda é bem jogável! Por exemplo, as constantes numéricas e vNy<FD}podem ser jogáveis.

Exemplo de saída

Como funciona?

Ele gera todas as combinações de palavras seguindo a regra "vogal + vogal + consoante", que torna 525 palavras válidas exclusivas (mais de 200). Em seguida, associa a cada um deles uma frequência que satisfaz a lei f(x) = 4725/xondexé a classificação da palavra atual, iniciando em 1 e terminando em 525. Em seguida, as frequências são normalizadas e multiplicadas para que haja pelo menos 30000 palavras. Esse código sempre produz 32074 palavras para tornar as constantes envolvidas em golf (consulte a explicação do código). Portanto, cada palavra é repetida a quantidade de vezes correspondente à frequência da mesma palavra. Finalmente, as palavras são embaralhadas. No entanto, não garante que uma palavra nunca seja repetida cinco vezes seguidas. Portanto, os programas geram mais do que as 200 palavras únicas necessárias para diminuir a probabilidade de repetir uma palavra cinco vezes seguidas. Observe que esse código sempre gera a mesma sequência de palavras. A única coisa que difere entre duas execuções é o resultado da operação de reprodução aleatória.

Como avaliar a frequência?

Eu criei um código Python3 simples que pega o texto no arquivo chamado "output" (do ponto de vista do algoritmo, faz sentido!) E gera para "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")

O que sempre gera a seguinte distribuição para o meu código: Lei da frequência

Portanto, a inclinação é -1,0138. Agora esse valor está menos próximo de -1 do que a inclinação do código anterior, mas ainda satisfaz as restrições de inclinação.


Obrigado pelo script para avaliar a frequência, observe que você tem um `extra no final. Além disso, por que você usa ponto e vírgula como separadores? csv geralmente significa valores separados por vírgula;)
Leo

1
Sim, você está certo, haha! Fiquei confuso com a remarcação por um segundo. Eu usei o código embutido primeiro, depois percebi que era mais apropriado usar um bloco de código, mas esqueci de remover o extra `. Uso ponto-e-vírgula como separadores csv porque sou francês e alguns softwares ou empresas estão acostumados a colocar valores decimais com vírgulas em vez de pontos, como fazemos com valores decimais manuscritos. Embora eu sempre use o ponto para separar a parte inteira da parte fracionária, uso o ponto-e-vírgula sem pensar mais. Mas ei, ssv também é ótimo;) #
Osable

0

Utilitários Bash / Core, 122 110 bytes

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)

Desenrolado:

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)

O for wloop gera 243 palavras distintas. let ++x;incrementos inicialmente não definidos x (por regras de expressão aritmética durante a primeira execução, xsão tratados como 0 e, portanto, seu incremento o define como 1). A próxima linha gera palavras sucessivas na frequência 5575 / x para aproximar a frequência zipf.

O próximo passo é permutar isso deterministicamente para atender ao requisito de repetição; apesar de --random-sourceser um nome de bandeira terrivelmente grande, usá-lo com shuf supera a contagem de caracteres de rolagem manual de um seletor multi-mod. yes aeé realmente o menor dispositivo "aleatório" fixo que eu encontrei em conformidade.

Isso gera este ensaio de 33729 palavras [pastebin] .

Utilitários Bash / Core, 96 84 bytes (não concorrentes)

Para uma abordagem não determinística, basta cortar os sinalizadores 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

Análise

A inclinação do zipf é ajustada para ser reta. Usando o Excel para plotar em escalas logarítmicas:

O professor deve observar uma inclinação zipf de = -1.000764.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.