Saçma dolu kitaplar: Limerickleri tanımlayın


15

Hepimizin bildiği gibi, limerickler kısa, beş satırlı, bazen ahlaksız şiirleri olan bir AABBA kafiye şeması ve bir anapestimetre (her ne ise):

Limerick'in saçma bir
satır ve beşinci satır kelimesini yazmak
Ve tıpkı tahmin ettiğiniz gibi
İkinci ile kafiyeli
Dördüncü satır üçüncü ile kafiyeli olmalı

Bir giriş metni beslendiğinde, girdinin geçerli bir limerick olduğunu düşünüp düşünmediğini yazdıran en kısa programı yazmakla görevlendirilirsiniz . Giriş, komut satırında veya standart giriş aracılığıyla, sizin tercihinize göre olabilir ve çıkış, yine kendi seçiminize bağlı olarak basit bir "Y" / "N" veya bir güven puanı olabilir.

Doğru bir limerick örneği:

Gözleri
renk ve boyuta göre benzersiz olan bir Genç Leydi vardı
Onları geniş açtığında
İnsanlar bir kenara döndü
ve şaşkınlıkla başladı

Ancak aşağıdaki şiir açıkça bir limerick değildir , çünkü kafiyeli değildir:

Arı
kovanı ile koluna sokulan yaşlı bir Aziz Arılar vardı.
"Acıyor mu?"
"Hayır, değil,
eşek arısı olmadığı için çok mutluyum."

Sayaç yanlış olduğu için bu da değil:

Berlin'den
, içinde bulunduğu odadan nefret eden bir adam duydum. İç çekerek
neden
söyleyeceğini sorduğumda :
"Şey, görüyorsun, dün gece, etraftaki karartmayı kazanan Ayıları kutlayan birkaç davlumbaz vardı Dünya Kupası ve din nedeniyle uyuyamadım bu yüzden gerçekten yüksek. "

İpuçları

Girdinizin bir limerick olup olmadığına karar vermek için kullanabileceğiniz ipuçlarından bazıları şunlardır:

  • Limericks her zaman beş satır uzunluğundadır.
  • 1, 2 ve 5 numaralı hatlar kafiye yapmalıdır.
  • 3. ve 4. hatlar kafiye yapmalıdır.
  • 1, 2 ve 5 numaralı satırlarda yaklaşık 3x3 = 9 hece bulunurken, üçüncü ve dördüncü satırlarda 2x3 = 6 hece vardır

Birincisi dışında bunların hiçbirinin hızlı ve hızlı olmadığını unutmayın:% 100 doğruluk derecesi imkansızdır.

kurallar

  • Girişiniz en azından 1'den 3'e kadar olan örnekleri belirleyici bir şekilde doğru bir şekilde kategorize etmelidir .

  • Sen edilir özellikle (bkz bu yarışma için tasarlanmış ders programlama dillerinin dışında istediğiniz herhangi bir programlama dili kullanmasına izin burada ).

  • Sen değil programlama dilinin standart teklifleri dışında herhangi kütüphane kullanma izin verdi.

  • Sen edilir varsaymak izin bu dosyayı , CMU Sfenks okunuş sözlük, geçerli dizinde 'c' adlı bir dosyada olduğunu.

  • Sen edilir değil Test girişler için sabit kod izin: Programınız genel limerik Kategorilere olmalıdır.

  • Sen olan herhangi bir özel biçimlendirme olmadan (örneklerde gibi), giriş ASCII olduğunu varsaymak izin verilir, ancak program interpunction tarafından karıştırılmamalıdır.

Bonuslar

Aşağıdaki bonuslar mevcuttur:

  • Programın sonucu bir limerick olarak çıktı? Çıkar 150 karakter uzunluğu ikramiye!
  • Programınız son ağları da doğru olarak tanımlıyor mu? Çıkar 150 karakter ekstra uzunluğu ikramiye!
  • Programınız, bir sonnet üzerinde kullanıldığında sonucu bir sonnet olarak verir mi? Çıkar 100 karakter ek ekstra uzunluğu bonusu!

En sonunda...

Varsa, hangi bonusları hak ettiğinizi düşündüğünüzü belirtmeyi unutmayın ve puanınıza ulaşmak için bonusu karakter sayınızdan çıkarın. Bu bir kod golf yarışmasıdır: en kısa giriş (yani en düşük puanlı giriş) kazanır.

Daha fazla (pozitif) test verisine ihtiyacınız varsa, OEDILF veya Saçmalık Kitabı'na bakın . Negatif test verilerinin oluşturulması kolay olmalıdır.

İyi şanslar!


Bu code-challengebonuslardan dolayı olmalı . Lütfen etiket açıklamalarını okuyun
user80551

2
@ user80551 Meta üzerinde fikir birliği olduğu anlaşılıyor.
Kapı tokmağı

Bonusların doğasını netleştirdim, umarım bu karışıklığı giderir.
Wander Nauta

2
Goooooooo Ayılar!
alvonellos

Bonusları anlamıyorum. Nasıl "lim" şeklinde "Y" çıktı almalıyım?
r3mainer

Yanıtlar:


8

Python: 400-150-150 = 100

Ortaya çıkabilecek en kısa senaryo ...

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))

... ama denemeyin bile. Karşılaştığı her sözcük için sağlanan sözlüğü ayrıştırır, böylece çok yavaş olur. Ayrıca, sözlükte bir sözcük olmadığında bir hata oluşur.

Kod yine de gereksinimleri karşılar: stdin'den geçen metnin bir limerick, bir sonnet veya bunların hiçbiri olup olmadığını anlamak .

Sadece 20 karakter daha, optimize edilmiş sürüm:

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))

Özellikleri

  • son ağları tanıyabilme (-150)
  • bir limerick ile limericks cevaplar (-150)
  • nispeten hızlı: yürütme başına yalnızca bir dosya ayrıştırma

kullanım

cat poem.txt | python poem-check.py

3 farklı çıkış mümkündür:

  • eğer durum böyleyse girdinin bir olduğunu söyleyen bir limmerick
  • durum söz konusu olduğunda girdinin bir olmadığını söyleyen bir limmerick
  • Giriş bu şekilde tanınırsa "Sonnet"

Açıklamalarla birlikte genişletilmiş kod

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)

Havalı görünüyor! Henüz test etmedim, ancak bunun "komut satırında veya standart girdi üzerinden" girdi aldığından emin misiniz (soruya bakın)? Değilse, eklemeniz (muhtemelen a sys.stdin.read()veya bir open(sys.argv[1]).read()yerde) ve yeniden saymanız gerekir.
Wander Nauta

Tamam! Düzeltildi :)
Mathieu Rodic

Algoritma tekerlemeleri nasıl denetler?
DavidC

Soruda Wander Nauta tarafından sağlanan dosyanın yardımıyla! Gerçekten yardımcı oldu.
Mathieu Rodic

1
Temiz! Utanç seni iki kez vuramıyorum.
Nauta

2

ECMAScript 6 (138 puan; Firefox'ta deneyin):

288- 150Limerick dahil etmek için puan bonusu (@MathieuRodic'ten sıkıştırılmış).

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!')

Notlar:

Değişkeni bekler cDüz ECMAScript'te dosyaları okuyamayacağınızdan sözlük dosyasının içeriğini içermesini .

ECMAScript'in standart girişi yoktur, ancak promptgenellikle "standart girdi" olarak kabul edilir; Ancak, promptsatır sonlarını çoğu tarayıcıda (hepsi değilse de) boşluklara dönüştürdüğü için, değişkenin girdisini kabul ediyorumi .

Kod çözülmemiş kod:

// 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!');

Temiz! Ancak bu, soru için gerekli olan 'komut satırında veya standart girdi üzerinden' girişi almaz. Belki de Node.js veya başka bir şey kullanmak için yeniden yazabilirsiniz.
Wander Nauta

@WanderNauta Teşekkürler. Standart girdiyi neden kullanmadığımı açıkladığım için lütfen en son düzenlemeye bakın .
Diş Fırçası
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.