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))
特征
- 能够识别十四行诗(-150)
- 用打油诗回答打油诗(-150)
- 相对快:每次执行仅解析一个文件
用法
cat poem.txt | python poem-check.py
3种不同的输出是可能的:
- 轻声说如果是这样的话,输入就是一个
- 轻声说如果是这种情况,则输入不是一个
- 如果输入被识别为“ 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)
code-challenge
因为奖金。请阅读标签说明