ช่วยด้วย! ฉันมีการบ้านมากกว่านี้!


18

ครูของฉันเป็นมากกว่าความสุขกับฉันทำการบ้านอังคาร ฉันปฏิบัติตามกฎทั้งหมด แต่เธอบอกว่าสิ่งที่ฉันส่งออกเป็นคำพูดพล่อยๆ ... เมื่อเธอดูเป็นครั้งแรกเธอสงสัยอย่างมาก "ทุกภาษาควรปฏิบัติตามกฎหมายของ Zipf blah blah blah" ... ฉันไม่รู้ด้วยซ้ำว่ากฎของ Zipf คืออะไร!

ปรากฎว่ากฎหมายของ Zipfระบุว่าหากคุณพล็อตลอการิทึมของความถี่ของแต่ละคำบนแกน y และลอการิทึมของ "สถานที่" ของแต่ละคำบนแกน x (พบมากที่สุด = 1, วินาทีที่พบมากที่สุด = 2, ส่วนใหญ่ที่สาม commmon = 3 และอื่น ๆ ) จากนั้นพล็อตจะแสดงเส้นที่มีความชันประมาณ -1 ให้หรือรับประมาณ 10%

ตัวอย่างเช่นนี่คือโครงเรื่องสำหรับ Moby Dick:

ป้อนคำอธิบายรูปภาพที่นี่

แกน x เป็นคำที่พบบ่อยที่สุดที่nแกน y คือจำนวนครั้งที่เกิดขึ้นของคำที่พบบ่อยที่สุดครั้งที่n ความชันของเส้นประมาณ -1.07

ตอนนี้เรากำลังครอบคลุม Venutian โชคดีที่ชาว Venutians ใช้ตัวอักษรละติน กฎมีดังนี้:

  • แต่ละคำจะต้องมีสระอย่างน้อยหนึ่งสระ (a, e, i, o, u)
  • ในแต่ละคำสามารถมีสระได้ถึงสามสระในหนึ่งแถว แต่ไม่เกินสองพยัญชนะในหนึ่งแถว (พยัญชนะเป็นตัวอักษรใด ๆ ที่ไม่ใช่สระ)
  • ไม่เกิน 15 ตัวอักษร
  • ทางเลือก: จัดกลุ่มคำเป็นประโยคยาว 3-30 คำคั่นด้วยเครื่องหมายจุด

เนื่องจากครูรู้สึกว่าฉันโกงการบ้านอังคารฉันจึงได้รับมอบหมายให้เขียนเรียงความอย่างน้อย 30,000 คำ (ใน Venutian) เธอจะตรวจสอบงานของฉันโดยใช้กฎของ Zipf ดังนั้นเมื่อมีการติดตั้งบรรทัด (ดังที่อธิบายไว้ด้านบน) ความชันจะต้องมีอย่างน้อยที่สุด -0.9 แต่ไม่น้อยกว่า -1.1 และเธอต้องการคำศัพท์อย่างน้อย 200 คำ คำเดียวกันไม่ควรซ้ำเกิน 5 ครั้งติดต่อกัน

นี่คือ CodeGolf ดังนั้นรหัสที่สั้นที่สุดในหน่วยไบต์ชนะ โปรดวางผลลัพธ์ลงใน Pastebin หรือเครื่องมืออื่นที่ฉันสามารถดาวน์โหลดเป็นไฟล์ข้อความได้


ใช่และถ้าคุณต้องการคุณก็สามารถทำประโยคคำ 32767 ข้อ จำกัด คือความถี่ของคำในประโยคจะต้องเป็นไปตามกฎหมายของ zipf
J. Antonio Perez

1
คำคุณศัพท์ดั้งเดิมสำหรับ "from Venus" คือ Veneral แต่ด้วยเหตุผลบางอย่างมันได้รับความนิยมลดลง Venusian ใช้กันทั่วไปใน sci-fi
Peter Taylor

ฉันคาดเดาว่าการสร้างรายการคำต่อไปนี้การกระจาย zipf และการสับจะมีความน่าจะเป็นสูงในการสร้างลำดับที่มีคู่ของคำต่อเนื่องเช่นกันหลังจากการกระจาย zipf ยิ่งกว่านั้นเมื่อใช้คำต่าง ๆ ในรายการความน่าจะเป็นที่มีคำซ้ำมากกว่า 5 ครั้งติดต่อกันจะมีขนาดเล็กมาก ในกรณีที่ฉันลองใช้วิธีการนี้และสามารถสร้างเรียงความที่ถูกต้องจะได้รับการยอมรับหรือไม่
Leo

การคาดเดาของคุณสมเหตุสมผลแม้ว่าความชันจะเป็น -0.35
J. Antonio Perez

มันจะดูเหมือนเป็นเส้นตรง มันเป็นเพียงความลาดชันจะยิ่งใหญ่เกินไป
เจ. อันโตนิโอเปเรซ

คำตอบ:


3

Mathematica, 102 ไบต์

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

ฟังก์ชั่นที่ไม่มีชื่อไม่มีการป้อนข้อมูลและส่งคืนสตริงที่ประกอบด้วยคำภาษา Venusian 40,320 ตัวอักษรสามตัวที่มีช่องว่างต่อท้าย

Outer[StringJoin,a={"v","a","e","i","o","u"},a,a,{" "}]ผลิต 216 คำสามตัวอักษรที่เป็นไปได้โดยใช้เพียงตัวอักษร "vaeiou" แต่ละคนมีพื้นที่ต่อท้ายของตัวเอง คำแรกของคำเหล่านี้ "vvv" ไม่ถูกต้อง Venusian แต่Restโยนทิ้งไป

จากนั้นRandomChoice[1/Range@215->...,8!]ทำให้ 8! = 40,320 ตัวเลือกแบบสุ่มจากรายการ 215 คำที่มีน้ำหนักความถี่กำหนดโดยส่วนกลับของจำนวนเต็ม 215 ตัวแรก ( 1/Range@215) ในที่สุด<>""...เชื่อมสตริงในรายการผลลัพธ์

ผลลัพธ์อยู่ไกลจากที่กำหนดไว้ หนึ่งวิ่งให้เรียงความ Venusianนี้

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 ครั้ง) เพื่อบังคับใช้กฎหมายของ zipf จากนั้นคำเหล่านี้จะสอดแทรกอย่างเท่าเทียมกันเพื่อหลีกเลี่ยงการซ้ำ (ลองนึกภาพคำแต่ละคำที่วางไว้บนไม้บรรทัดพร้อมสำเนาทั้งหมดของคำนั้นที่เว้นระยะเท่ากันเมื่อทุกคำอ่านตามลำดับไม่มีคำใดที่ซ้ำกันมากอาจจะไม่มากเลย) ผลลัพธ์ที่ได้คือ30,117 คำ เรียงความศุกร์


ไม่ได้ทำ 8! ทางเลือกที่หลอกแบบสุ่มหมายความว่าคุณสามารถจบด้วยการซ้ำคำติดต่อกัน 6 ครั้งของคำเดียวกันได้หรือไม่
Dennis

ใช่ในทางทฤษฎี
Greg Martin

@GregMartin จริงๆแล้ว ... เรียงความที่คุณเชื่อมโยงไปนั้นไม่สอดคล้อง vvaปรากฏหกครั้งติดต่อกัน ฉันคิดว่าอาจมีปัญหาที่ใหญ่กว่าแม้ว่า ... ไม่ควรท้าทายคำตอบทุกครั้งใช่ไหม (และถ้าไม่คุณจะวาดเส้นของวิธีการที่พวกเขาควรจะทำงานอย่างไร)
H Walters

นี่เป็นคำวิจารณ์ที่ยุติธรรมและฉันสนใจที่จะดูว่ามันเล่นอย่างไร
Greg Martin

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 จากนั้นความถี่จะถูกทำให้เป็นมาตรฐานและคูณดังนั้นจึงมีอย่างน้อย 30,000 คำ รหัสนี้ให้ผลตอบแทน 32074 คำเพื่อให้ค่าคงที่ที่เกี่ยวข้องสามารถเล่นได้ (โปรดดูคำอธิบายรหัส) ดังนั้นแต่ละคำจะถูกทำซ้ำจำนวนครั้งที่สอดคล้องกับความถี่ของคำเดียวกัน ในที่สุดคำพูดจะถูกสับ อย่างไรก็ตามไม่รับประกันว่าคำจะไม่ซ้ำห้าครั้งในแถว ดังนั้นโปรแกรมจึงสร้างคำที่ไม่ซ้ำกันมากกว่า 200 คำเพื่อลดความน่าจะเป็นที่จะมีคำซ้ำห้าครั้งติดต่อกัน โปรดทราบว่ารหัสนี้จะสร้างลำดับคำเดียวกันเสมอ สิ่งเดียวที่แตกต่างระหว่างการวิ่งสองครั้งคือผลลัพธ์ของการดำเนินการสับ

จะประเมินความถี่ได้อย่างไร

ฉันสร้างรหัส Python3 อย่างง่ายที่ใช้ข้อความในไฟล์ชื่อ "เอาท์พุท" (จากมุมมองอัลกอริทึมมันสมเหตุสมผลแล้ว!) และเอาท์พุทเป็น "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 น้อยกว่าความชันของรหัสก่อนหน้า แต่ยังคงเป็นไปตามข้อ จำกัด ของความชัน


ขอบคุณสำหรับสคริปต์ในการประเมินความถี่โปรดทราบว่าคุณมี "พิเศษ" ในตอนท้าย นอกจากนี้ทำไมคุณใช้เครื่องหมายอัฒภาคเป็นตัวคั่น csv หมายถึงค่าที่คั่นด้วยเครื่องหมายจุลภาค;)
Leo

1
ใช่คุณพูดถูก! ฉันสับสนกับ markdown เป็นครั้งที่สอง ฉันใช้โค้ดอินไลน์ก่อนจากนั้นจึงตระหนักว่าเหมาะสมกว่าที่จะใช้บล็อกโค้ด แต่ฉันลืมลบส่วนเสริม ' ฉันใช้เครื่องหมายอัฒภาคเป็นตัวคั่น csv เพราะฉันเป็นคนฝรั่งเศสและมีซอฟท์แวร์หรือ บริษัท บางแห่งที่ใช้ในการใส่ค่าทศนิยมด้วย comas แทนจุดเช่นเดียวกับที่เราใช้กับค่าทศนิยมที่เขียนด้วยลายมือ แม้ว่าฉันจะใช้จุดเพื่อแยกส่วนจำนวนเต็มออกจากส่วนที่เป็นเศษส่วน แต่ฉันใช้เครื่องหมายอัฒภาคโดยไม่ต้องคิดเพิ่ม แต่เดี๋ยวก่อน ssv ดีมากเช่นกัน;)
Osable

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 นับจำนวนถ่านในมือที่หมุนตัวเลือก mul-mod yes aeจริง ๆ แล้วเป็นอุปกรณ์ "สุ่ม" ที่สั้นที่สุดที่ฉันพบว่าสอดคล้อง

นี้จะสร้างนี้เรียงความ 33,729 คำ [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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.