หนังสือที่เต็มไปด้วยเรื่องไร้สาระ: ระบุลิเมอริค


15

อย่างที่เรารู้กันว่าโคลงสั้น ๆ บทกวีห้าบรรทัดบางครั้งลามกด้วยโครงการบทกวี AABBA และเครื่องวัด anapestic (อะไรก็ตามที่เป็น):

การเขียนเรื่องไร้สาระของ Limerick
บรรทัดที่หนึ่งและบรรทัดที่ห้าสัมผัสในคำ
และเช่นเดียวกับที่คุณได้คาดคิด
พวกเขาสัมผัสกับที่สอง
บรรทัดที่สี่จะต้องสัมผัสกับที่สาม

คุณได้รับมอบหมายให้เขียน โปรแกรมที่สั้นที่สุดซึ่งเมื่อป้อนข้อความเข้าให้พิมพ์ว่ามันคิดว่าการป้อนข้อมูลเป็นโคลงที่ถูกต้องหรือไม่ อินพุตอาจอยู่ในบรรทัดคำสั่งหรือผ่านอินพุตมาตรฐานที่ตัวเลือกของคุณและเอาต์พุตอาจเป็น "Y" / "N" แบบง่ายหรือคะแนนความเชื่อมั่นอีกครั้งที่ตัวเลือกของคุณ

นี่เป็นอีกตัวอย่างของการโคลงที่ถูกต้อง:

มีหญิงสาวคนหนึ่งซึ่งดวงตา
มีเอกลักษณ์แตกต่างกันไปตามขนาดและสี
เมื่อเธอเปิดกว้าง
คนทุกคนหันหลัง
และเริ่มประหลาดใจ

แต่บทกวีด้านล่างไม่ชัดเจนว่าเป็นโคลงเพราะไม่ได้สัมผัส:

มีชายชราคนหนึ่งของเซนต์ผึ้ง
ที่ถูกต่อยที่แขนโดยตัวต่อคือ
เมื่อถูกถามว่า "มันเจ็บหรือเปล่า?"
เขาตอบว่า "ไม่ไม่
ฉันดีใจมากที่ไม่ใช่แตน"

หรือสิ่งนี้ไม่ได้เนื่องจากมิเตอร์ผิดทั้งหมด:

ฉันได้ยินผู้ชายคนหนึ่งจากเบอร์ลิน
ที่เกลียดห้องที่เขาอยู่
เมื่อฉันถามว่าทำไม
เขาถึงพูดด้วยเสียงถอนหายใจ:
"เอาละคุณเห็นไหมเมื่อคืนนี้มีหมวกคลุมผมสองสามตัวที่กำลังฉลองหมีที่ชนะการสาปแช่ง การแข่งขันฟุตบอลโลกและพวกเขาดังมากฉันจึงนอนไม่หลับเพราะดิน "

เบาะแส

นี่คือเคล็ดลับบางอย่างที่คุณสามารถใช้เพื่อตัดสินใจว่าข้อมูลที่คุณป้อนนั้นเป็นข้อ จำกัด หรือไม่:

  • Limericks มีความยาวห้าบรรทัดเสมอ
  • บรรทัดที่ 1, 2 และ 5 ควรคล้องจอง
  • บรรทัดที่ 3 และ 4 ควรคล้องจอง
  • บรรทัดที่ 1, 2 และ 5 มีประมาณ 3x3 = 9 พยางค์ในขณะที่สามและสี่มี 2x3 = 6 พยางค์

โปรดทราบว่าสิ่งเหล่านี้ยกเว้นอันแรกนั้นยากและรวดเร็ว: ไม่สามารถให้คะแนนความถูกต้องได้ 100%

กฎระเบียบ

  • รายการของคุณควรจัดหมวดหมู่ตัวอย่างที่ 1 ถึง 3 อย่างน้อยที่สุดอย่างถูกต้องในรูปแบบที่กำหนดขึ้นมา

  • คุณจะได้รับอนุญาตให้ใช้ภาษาการเขียนโปรแกรมใด ๆ ที่คุณต้องการยกเว้นการเขียนโปรแกรมภาษาหลักสูตรการออกแบบเฉพาะสำหรับการประกวดครั้งนี้ (ดูที่นี่ )

  • คุณไม่ได้รับอนุญาตให้ใช้ไลบรารีใด ๆ ยกเว้นข้อเสนอมาตรฐานของภาษาโปรแกรม

  • คุณจะได้รับอนุญาตให้สมมติว่าไฟล์นี้ , ซีเอ็มสฟิงซ์พจนานุกรมการออกเสียงอยู่ในไฟล์ที่เรียกว่า 'C' ในไดเรกทอรีปัจจุบัน

  • คุณไม่ได้รับอนุญาตให้ใช้รหัสแบบแข็งสำหรับอินพุตการทดสอบ: โปรแกรมของคุณควรเป็นเครื่องมือจัดหมวดหมู่แบบโคลงทั่วไป

  • คุณจะได้รับอนุญาตให้สมมติว่าใส่เป็น ASCII โดยไม่ต้องจัดรูปแบบพิเศษใด ๆ (เช่นในตัวอย่าง) แต่โปรแกรมของคุณไม่ควรจะสับสนโดย interpunction

โบนัส

โบนัสดังต่อไปนี้:

  • โปรแกรมของคุณแสดงผลลัพธ์เป็นโคลงหรือไม่? ลบโบนัสความยาว150 ตัวอักษร !
  • โปรแกรมของคุณระบุ sonnets อย่างถูกต้องหรือไม่ ลบโบนัสความยาวพิเศษ150 ตัวอักษร !
  • โปรแกรมของคุณแสดงผลลัพธ์เป็น sonnet เมื่อใช้กับ sonnet หรือไม่ ลบโบนัสความยาวเพิ่มอีก100 ตัวอักษร !

สุดท้าย ...

อย่าลืมพูดถึงโบนัสที่คุณคิดว่าคุณสมควรได้รับถ้ามีและลบโบนัสจากจำนวนตัวอักษรของคุณเพื่อให้ได้คะแนนของคุณ นี่คือการแข่งขันกอล์ฟรหัส : รายการที่สั้นที่สุด (เช่นรายการที่มีคะแนนต่ำสุด) ชนะ

หากท่านต้องการข้อมูลเพิ่มเติม (บวก) ข้อมูลการทดสอบตรวจสอบOEDILFหรือหนังสือไร้สาระ ข้อมูลการทดสอบเชิงลบควรสร้างได้ง่าย

โชคดี!


ควรจะเป็นcode-challengeเพราะโบนัส โปรดอ่านคำอธิบายแท็ก
user80551

2
@ user80551 ความสอดคล้องบนเมตาดูเหมือนจะเป็นอย่างอื่น
Doorknob

ฉันชี้แจงลักษณะของโบนัสฉันหวังว่าจะเคลียร์ความสับสน
Wander Nauta

2
Goooooooo Bears!
alvonellos

ฉันไม่เข้าใจโบนัส ฉันควรจะส่งออก "Y" ในรูปแบบของโคลง?
r3mainer

คำตอบ:


8

Python: 400 - 150 - 150 = 100

สคริปต์ที่สั้นที่สุดที่ฉันสามารถพบได้คือสคริปต์นั้น ...

import re,sys;f,e,c=re.findall,lambda l,w:f('^'+w.upper()+'  (.+)',l),lambda*v:all([a[i]==a[v[0]]for i in v]);a=[sum([[e(l,w)[0].split()for l in open('c')if e(l,w)][0]for w in f(r'\w+',v)],[])[-2:]for v in sys.stdin];n=len(a);print n==14and c(0,3,4,7)*c(1,2,5,6)*c(8,11)*c(9,12)*c(10,13)*"Sonnet"or"For a critic\nOf limerick\nWell-equipped\nIs this script.\n%s limerick!"%(n==5and c(0,1,4)and c(2,3))

... แต่อย่าลองด้วยซ้ำ มันแยกวิเคราะห์พจนานุกรมที่มีให้สำหรับทุกคำที่ตรงดังนั้นจึงช้ามาก นอกจากนี้ข้อผิดพลาดจะถูกสร้างขึ้นเมื่อใดก็ตามที่คำไม่ได้อยู่ในพจนานุกรม

รหัสยังคงเป็นไปตามข้อกำหนดที่: จำได้ว่าข้อความที่ส่งผ่านstdinนั้นเป็นโคลง, โคลงหรือไม่นั้น

ด้วยอักขระเพิ่มเติมเพียง 20 ตัวนี่คือรุ่นที่ปรับให้เหมาะสม:

import re,sys;f,e,c=re.findall,lambda l:f(r'^(\w+)  (.+)',l),lambda*v:all([a[i]==a[v[0]]for i in v]);d={e(l)[0][0]:e(l)[0][1].split()for l in open('c')if e(l)};a=[sum([d.get(w.upper(),[])for w in f(r'\w+',v)],[])[-2:]for v in sys.stdin];n=len(a);print n==14and c(0,3,4,7)*c(1,2,5,6)*c(8,11)*c(9,12)*c(10,13)*"Sonnet"or"For a critic\nOf limerick\nWell-equipped\nIs this script.\n%s limerick!"%(n==5and c(0,1,4)and c(2,3))

คุณสมบัติ

  • สามารถรับรู้ sonnets (-150)
  • คำตอบสำหรับ limericks ด้วย limerick (-150)
  • ค่อนข้างเร็ว: มีการแยกวิเคราะห์ไฟล์เพียงไฟล์เดียวต่อการประมวลผล

การใช้

cat poem.txt | python poem-check.py

3 เอาต์พุตที่เป็นไปได้:

  • ลิมเมอร์ริคที่พูดว่าอินพุตเป็นสิ่งที่ถ้าเป็นจริง
  • limmerick บอกว่าการป้อนข้อมูลไม่ใช่อย่างใดอย่างหนึ่งถ้ามันเป็นกรณี
  • "Sonnet" ถ้าอินพุตถูกจดจำเช่นนั้น

โค้ดขยายพร้อมคำอธิบาย

import re, sys

# just a shortened version of the 're.findall' function...
f = re.findall
# function used to parse a line of the dictionary
e = lambda l:f(r'^(\w+)  (.+)', l)

# create a cache of the dictionary, where each word is associated with the list of phonemes it contains
d = {e(l)[0][0]:e(l)[0][1].split(' ') for l in open('c') if e(l)}

# for each verse (line) 'v' found in the input 'sys.stdin', create a list of the phoneme it contains;
# the result array 'a' contains a list, each item of it corresponding to the last two phonemes of a verse
a = [sum([d.get(w.upper(), []) for w in f(r'\w+',v)],[])[-2:] for v in sys.stdin]

# let's store the length of 'a' in 'n'; it is actually the number of verses in the input
n = len(a)
# function used to compare the rhymes of the lines which indexes are passed as arguments
c = lambda*v:all([a[i] == a[v[0]] for i in v])

# test if the input is a sonnet, aka: it has 14 verses, verses 0, 3, 4 and 7 rhyme together, verses 1, 2, 5 and 6 rhyme together, verses 8 and 11 rhyme together, verses 9 and 12 rhyme together, verses 10 and 13 rhyme together
if n==14 and c(0,3,4,7) and c(1,2,5,6) and c(8,11) and c(9,12) and c(10,13):
    print("Sonnet")
else:
    # test if the input is a limerick, aka: it has 5 verses, verses 0, 1 and 4 rhyme together, verses 2 and 3 rhyme together
    is_limerick = n==5 and c(0,1,4) and c(2,3)
    print("For critics\nOf limericks,\nWell-equipped\nIs this script.\n%s limerick!", is_limmerick)

ดูเท่! ฉันยังไม่ได้ทดสอบ แต่คุณแน่ใจหรือว่านี่ใช้อินพุต "บนบรรทัดคำสั่งหรือผ่านอินพุตมาตรฐาน" (ดูคำถาม) ถ้าไม่คุณควรเพิ่มที่ (อาจเป็นsys.stdin.read()หรือopen(sys.argv[1]).read()บางแห่ง) และเล่าขาน
Wander Nauta

ตกลง! แก้ไขแล้ว :)
Mathieu Rodic

อัลกอริทึมตรวจสอบ Rhymes อย่างไร
DavidC

ด้วยความช่วยเหลือของไฟล์ที่จัดทำโดย Wander Nauta ในคำถาม! มันช่วยได้จริงๆ
Mathieu Rodic

1
เรียบร้อย! ความอัปยศฉันไม่สามารถลงคะแนนให้คุณสองครั้ง
Wander Nauta

2

ECMAScript 6 (138 คะแนนลองใน Firefox):

288- 150คะแนนโบนัสสำหรับการรวมโคลง (ที่บีบจาก @MathieuRodic)

a=i.split(d=/\r?\n/).map(x=>x.split(' '));b=/^\W?(\w+) .*? (\w+\d( [A-Z]+)*)$/;c.split('\r\n').map(x=>b.test(x)&&eval(x.replace(b,'d["$1"]="$2"')));e=f=>d[a[f][a[f].length-1]];alert('For critics\nOf limericks,\nWell-equipped\nIs this script.\n'+(a[4]&&e(0)==e(1)&e(0)==e(4))+' limerick!')

หมายเหตุ:

คาดว่าตัวแปร cจะมีเนื้อหาของไฟล์พจนานุกรมเนื่องจากคุณไม่สามารถอ่านไฟล์ใน ECMAScript ธรรมดา

ECMAScript ไม่มีอินพุตมาตรฐาน แต่promptโดยทั่วไปถือว่าเป็น "อินพุตมาตรฐาน"; อย่างไรก็ตามเมื่อpromptแปลงตัวแบ่งบรรทัดเป็นช่องว่างในเบราว์เซอร์ส่วนใหญ่ (ถ้าไม่ใช่ทั้งหมด) ฉันยอมรับการป้อนข้อมูลจากตัวแปรiเบราว์เซอร์ผมยอมรับการป้อนข้อมูลจากตัวแปร

รหัสไม่ได้รับการตอบกลับ:

// If you paste a string with multiple lines into a `prompt`, the browser replaces each line break with a space, for some reason.
//input = prompt();

// Split into lines, with each line split into words
lines = input.split('\n').map(x => x.split(' '));

dictionaryEntryRegEx = /^\W?(\w+) .*? (\w+\d( [A-Z]+)*)$/;
dictionary = {};
// Split it into
c.split(/\r?\n/).map(x => dictionaryEntryRegEx && eval(x.replace(dictionaryEntryRegEx, 'dictionary["$1"] = "$2"')));

// Get the last word in the line
getLastWordOfLine = (lineNumber) => dictionary[line[lineNumber][line[lineNumber].length - 1]]

alert('For critics\nOf limericks,\nWell-equipped\nIs this script.\n' + (lines[4] && getLastWordOfLine(0) === getLastWordOfLine(1) && getLastWordOfLine(0) === getLastWordOfLine(4)) + ' limerick!');

เรียบร้อย! สิ่งนี้ไม่ได้ใช้ 'อินพุตบนบรรทัดคำสั่งหรือผ่านอินพุตมาตรฐาน' ซึ่งจำเป็นสำหรับคำถาม บางทีคุณอาจจะเขียนมันซ้ำเพื่อใช้ Node.js หรืออะไรทำนองนั้น
Wander Nauta

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