Tolong! Saya punya lebih banyak pekerjaan rumah!

18

Guru saya sangat tidak senang dengan Pekerjaan Rumah Mars saya . Saya mengikuti semua aturan, tetapi dia mengatakan bahwa apa yang saya hasilkan adalah omong kosong ... ketika dia pertama kali melihatnya, dia sangat curiga. "Semua bahasa harus mengikuti hukum Zipf, blah blah blah" ... Aku bahkan tidak tahu apa itu hukum Zipf!

Ternyata hukum Zipf menyatakan bahwa jika Anda memplot logaritma frekuensi setiap kata pada sumbu y, dan logaritma "tempat" setiap kata pada sumbu x (paling umum = 1, kedua paling umum = 2, commmon paling ketiga = 3, dan seterusnya), maka plot akan menunjukkan garis dengan kemiringan sekitar -1, memberi atau mengambil sekitar 10%.

Misalnya, inilah plot untuk Moby Dick:

masukkan deskripsi gambar di sini

Sumbu x adalah kata ke- n yang paling umum, sumbu-y adalah jumlah kemunculan kata ke- n yang paling umum. Kemiringan garis adalah sekitar -1,07.

Sekarang kita sedang meliput Venesia. Untungnya, orang-orang Venesia menggunakan alfabet latin. Aturannya adalah sebagai berikut:

  • Setiap kata harus mengandung setidaknya satu vokal (a, e, i, o, u)
  • Dalam setiap kata bisa ada hingga tiga vokal berturut-turut, tetapi tidak lebih dari dua konsonan berturut-turut (konsonan adalah huruf apa pun yang bukan vokal).
  • Tidak ada kata yang lebih panjang dari 15 huruf
  • Opsional: kelompokkan kata ke dalam kalimat yang panjangnya 3-30 kata, dibatasi oleh titik

Karena guru itu merasa saya selingkuh dengan pekerjaan rumah saya di Mars, saya ditugaskan menulis esai setidaknya 30.000 kata (dalam bahasa Venesia). Dia akan memeriksa pekerjaan saya menggunakan hukum Zipf, jadi ketika sebuah garis dipasang (seperti dijelaskan di atas) kemiringan harus paling banyak -0,9 tetapi tidak kurang dari -1.1, dan dia ingin kosakata minimal 200 kata. Kata yang sama tidak boleh diulang lebih dari 5 kali berturut-turut.

Ini adalah CodeGolf, jadi kode terpendek dalam byte menang. Silakan tempelkan output ke Pastebin atau alat lain tempat saya dapat mengunduhnya sebagai file teks.

J. Antonio Perez
sumber
Ya dan jika Anda mau, Anda bisa melakukan kalimat 32767 kata. Batasannya adalah bahwa frekuensi kata dalam kalimat harus mengikuti hukum zipf
J. Antonio Perez
1
Kata sifat tradisional untuk "from Venus" adalah Veneral, tetapi karena alasan tertentu popularitasnya menurun. Venusian biasanya digunakan dalam sci-fi.
Peter Taylor
Saya menduga bahwa membangun daftar kata-kata berikut distribusi zipf dan mengocoknya akan memiliki probabilitas tinggi untuk menghasilkan urutan dengan pasangan kata berturut-turut juga mengikuti distribusi zipf. Selain itu, dengan kata-kata yang cukup berbeda dalam daftar, kemungkinan kata yang sama diulang lebih dari 5 kali berturut-turut akan sangat kecil. Jika saya mencoba pendekatan ini dan berhasil menghasilkan esai yang valid, apakah itu akan diterima?
Leo
Dugaan Anda masuk akal, meskipun kemiringannya adalah -0,35
J. Antonio Perez
Itu akan tetap terlihat seperti garis lurus; hanya saja kemiringannya terlalu besar
J. Antonio Perez

Jawaban:

3

Mathematica, 102 byte

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

Fungsi yang tidak disebutkan namanya tidak menerima input dan mengembalikan string yang terdiri dari 40.320 kata Venus tiga huruf dengan spasi tambahan.

Outer[StringJoin,a={"v","a","e","i","o","u"},a,a,{" "}]menghasilkan 216 kata tiga huruf yang mungkin hanya menggunakan huruf "vaeiou", masing-masing dengan ruang trailingnya sendiri. Yang pertama dari kata-kata ini, "vvv", bukan bahasa Venus yang valid, tetapi Restdibuang begitu saja.

Maka RandomChoice[1/Range@215->...,8!]menghasilkan 8! = 40.320 pilihan acak dari daftar 215 kata yang dihasilkan, dengan bobot frekuensi ditentukan oleh kebalikan dari 215 bilangan bulat pertama ( 1/Range@215). Akhirnya, <>""...menyatukan string dalam daftar yang dihasilkan.

Outputnya jauh dari deterministik; satu run menghasilkan esai Venus ini .

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

Yang ini deterministik. Himpunan dasar dari 215 kata adalah sama, tetapi sekarang setiap kata diulangi beberapa kali dengan tepat (kata #j diulang kira-kira 7! / J kali) untuk memaksa hukum zipf berlaku. Kemudian kata-kata itu disisipkan secara sama untuk menghindari pengulangan. (Bayangkan setiap kata diletakkan di atas penggaris, dengan semua salinan dari kata itu ditempatkan dengan jarak yang sama; ketika semua kata dibaca berurutan, tidak ada kata tertentu yang akan berulang banyak, mungkin tidak sama sekali.) Hasilnya adalah 30,117 kata. Esai Venus .

Greg Martin
sumber
Tidak menghasilkan 8! Pilihan pseudo-acak berarti Anda bisa berakhir dengan 6 kali pengulangan kata yang sama?
Dennis
Ya, secara teori.
Greg Martin
@GregMartin Sebenarnya ... esai yang Anda tautkan tidak sesuai; vvamuncul enam kali berturut-turut. Saya pikir mungkin ada masalah yang lebih besar ... seharusnya tidak menantang jawaban bekerja setiap saat? (Dan jika tidak, bagaimana Anda menarik garis tentang seberapa besar kemungkinan mereka akan bekerja?)
H Walters
Ini adalah kritik yang adil, dan saya tertarik untuk melihat hasilnya.
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

Cobalah online!

Saya pikir ini masih cukup golf! Misalnya konstanta numerik dan vNy<FD}mungkin golf.

Contoh keluaran

Bagaimana cara kerjanya?

Ini menghasilkan semua kombinasi kata yang mengikuti aturan "vowel + vowel + konsonan", yang menghasilkan 525 kata unik yang valid (lebih dari 200). Ini kemudian mengaitkan dengan masing-masing dari mereka frekuensi yang memenuhi hukum di f(x) = 4725/xmanaxadalah peringkat kata saat ini, mulai dari 1 dan berakhir pada 525. Kemudian frekuensinya dinormalisasi dan dikalikan sehingga setidaknya ada 30000 kata. Kode ini selalu menghasilkan 32074 kata untuk membuat konstanta yang terlibat golf (lihat penjelasan kode). Jadi setiap kata diulangi berapa kali sesuai dengan frekuensi kata yang sama. Akhirnya kata-kata itu dikocok. Namun itu tidak menjamin bahwa sebuah kata tidak pernah diulang lima kali berturut-turut. Oleh karena itu program menghasilkan lebih dari 200 kata unik yang diperlukan untuk mengurangi kemungkinan kata diulang lima kali berturut-turut. Harap perhatikan bahwa kode ini selalu menghasilkan urutan kata yang sama. Satu-satunya hal yang berbeda antara dua putaran adalah hasil dari operasi pengocokan.

Bagaimana cara mengevaluasi frekuensi?

Saya membuat kode Python3 sederhana yang mengambil teks dalam file bernama "output" (dari sudut pandang algoritma, itu masuk akal!) Dan output ke "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")

Yang selalu menghasilkan distribusi berikut untuk kode saya: Hukum frekuensi

Jadi kemiringannya adalah -1.0138. Nilai ini sekarang kurang mendekati -1 daripada kemiringan kode sebelumnya, tetapi masih memenuhi kendala kemiringan.

Osable
sumber
Terima kasih atas skrip untuk mengevaluasi frekuensi, perhatikan bahwa Anda memiliki `ekstra di akhir. Juga, mengapa Anda menggunakan titik koma sebagai pemisah? csv biasanya mewakili nilai yang dipisahkan koma;)
Leo
1
Ya kamu benar haha! Saya bingung dengan penurunan harga sesaat. Saya menggunakan kode sebaris terlebih dahulu, kemudian menyadari bahwa itu lebih tepat untuk menggunakan blok kode tetapi saya lupa untuk menghapus `ekstra. Saya menggunakan titik koma sebagai pemisah csv karena saya orang Prancis dan beberapa perangkat lunak atau perusahaan digunakan untuk meletakkan nilai desimal dengan koma alih-alih titik seperti yang kita lakukan dengan nilai desimal tulisan tangan. Meskipun saya selalu menggunakan titik untuk memisahkan bagian integer dari bagian fraksional, saya menggunakan titik koma tanpa berpikir lebih jauh. Tapi hei, ssv juga bagus;)
Osable
0

Bash / Core Utils, 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)

Belum dibuka:

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)

The for wLoop menghasilkan 243 kata-kata yang berbeda. let ++x;kenaikan awalnya tidak diset x (per aturan ekspresi aritmatika selama eksekusi pertama, xdiperlakukan sebagai 0 dan dengan demikian kenaikannya menetapkan ke 1). Baris selanjutnya dengan demikian menghasilkan kata-kata berikutnya pada frekuensi 5575 / x untuk memperkirakan frekuensi zipf.

Langkah selanjutnya adalah mengubah urutan ini agar sesuai dengan persyaratan pengulangan; meskipun --random-sourcemerupakan nama bendera yang sangat besar, menggunakannya dengan shuf mengalahkan hitungan char dari tangan menggulung pemilih mul-mod. yes aesebenarnya adalah perangkat "acak" terpendek yang saya patuhi.

Ini menghasilkan esai 33729 kata ini [pastebin] .

Bash / Core Utils, 96 84 byte (tidak bersaing)

Untuk pendekatan non-deterministik, cukup potong bendera 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

Analisis

Kemiringan zipf disetel agar lurus. Menggunakan Excel untuk plot pada skala logaritmik:

Guru harus memperhatikan kemiringan zipf = -1,000764.

H Walters
sumber