按五个部首分作对,且每个字和其部首有一定联系
烟锁池塘柳,著名绝对,最早出自明代陈子升的作品《中洲草堂遗集》,自诞生以来,以“意境优美、蕴含五行”闻名天下,难度极高,被誉为千古第一绝对,无数的才子佳人纷纷试对,却难以完美对出下联。五行是该对联的的主要难度来源,五个字偏旁分别是火金水土木,五行相生相克,矛盾对立统一;意境,是该对联的第二难度来源,“烟雾弥漫、池塘幽静、绿柳成荫”,有一种清幽朦胧美。
网上有很多人对了下联,我们来欣赏下:
不大正经的有:深圳铁板烧、锈堵油烟机、油烧坊本钱、钠沾烧杯壁、森焱淼鑫垚···
比较有意境的:桃燃锦江堤、雾笼灵城钟、炮镇海城楼···
我们今天尝试用计算机程序自动化的来对这个对联,看看能不能找到更好的。通过对这个任务的处理,帮助我们更好的去做内容风控的对抗。看完传统文化水平提高了,风控水平也提高了, 真是one stone two birds!!!
对联的第一步,要找到五个字需要的五个部首,因此,我们需要对每个部首提取所有可能的汉字,我去github上找到了汉字部首拆分的明细,下载地址为:
通过这个数据,我们就可以提取每个部首的所有汉字,然后把所有的汉字进行随机组合排列,并且满足韵律需求,就是我们要找的对联了。
#工作空间设置
import os
path = 'C:\\\\Users\\\\伍正祥\\\\Desktop\\\\NLP任务实验\\\\'
os.chdir(path)
os.getcwd()
# 读取数据表 并存储到字典里面
file = open('chaizi.txt',encoding='UTF-8')
kv = {}
for line in file:
line = line.strip()
k, v = line.split('\ ')[0:2]
kv[k] = v
### 每个部首的字存储
jin = []
for k,v in kv.items():
if v.find('金')>=0:
jin.append(k)
print(jin)
print(len(jin))#272
mu = []
for k,v in kv.items():
if v.find('木')>=0:
mu.append(k)
print(mu)
print(len(mu))#784
shui = []
for k,v in kv.items():
if v.find('水')>=0:
shui.append(k)
print(shui)
print(len(shui))#849
huo = []
for k,v in kv.items():
if v.find('火')>=0:
huo.append(k)
print(huo)
print(len(huo))#362
tu = []
for k,v in kv.items():
if v.find('土')>=0:
tu.append(k)
print(tu)
print(len(tu))#405
# 我们可以测试下效果
import random
for i in range(100):
a = random.choice(jin)
b = random.choice(mu)
c = random.choice(shui)
d = random.choice(huo)
e = random.choice(tu)
last = [a,b,c,d,e]
random.shuffle(last)
print('烟 锁 池 塘 柳')
print(' '.join(last))
print('\
')
烟 锁 池 塘 柳
堐 洲 钗 烒 椤
烟 锁 池 塘 柳
铅 溥 垔 熠 槬
烟 锁 池 塘 柳
爀 埧 栵 泯 锈
烟 锁 池 塘 柳
埣 铎 榽 澶 燐
烟 锁 池 塘 柳
炀 钊 淦 塝
通过上面的计算,如果考虑金木水火土顺序,有272*784*849*362*405=26543381598720种可能!!也就是26万亿种下联,这对出来一辈子都看不完,真的要对穿肠,非常夸张的量级,如果不考虑量级呢,那更是夸张。
煲 锒 查 老 渘,炝 槿 锅 凼 坊,镥 填 烟 榠 渡,这都什么鬼,看着还像那么回事。淘 熬 铙 棋 尘,椔 圩 熻 铡 沭,枯 坻 炁 钙 淂,锚 墭 梽 漌 焂,锵 煾 泛 楏 坥····,这些更加离谱
到这一步,我们完成了基础的部首提取,但是对联,还讲究韵律,因此,我们还得搞个韵律识别模块,接着往下看。
所谓的韵律,就是读音,这里我们可以使用一个汉字转拼音的库,pypinyin,下面还是文档资料和对应的安装方法。
#文档资料
GitHub:
文档:
PyPi:
#可以使用 pip 进行安装
pip install pypinyin
#easy_install 安装
easy_install pypinyin
#源码安装
python setup.py install
韵律规则:
一声二声为平,
三声四声为仄。
对仗规则:
上联韵律:平仄平平仄
下联应对:平平仄仄平
因此,要识别对联的韵律,首先要获取拼音的声调,并且提取出来,用拼音包里的pinyin这个函数就可以了,示例入下
from pypinyin import pinyin,Style
pinyin('烟锁池塘柳', style=Style.TONE3, heteronym=False)
[['yan1'], ['suo3'], ['chi2'], ['tang2'], ['liu3']]
我们来定义一个韵律提取函数yunlv(),开始我以为很简单,写的过程还挺复杂的,主要有两个bug,生僻字没有拼音,还有轻声没有1234,需要处理。
#开始随便写了个,发现有两个bug,生僻字没有拼音,还有轻声需要处理
from pypinyin import pinyin,Style
def yunlv(s):
yun = []
for i in s:
pin = pinyin(i, style=Style.TONE3, heteronym=False)[0][0]
if pin==i: # 生僻字没有返回拼音,等于自己
return '-1'
else:
if pin[-1].isalpha(): # 对轻声进行处理 '橺' 'jian'
yun.append(int(1))
else:
yun.append(int(pin[-1]))
return ''.join(['平' if i<=2 else '仄' for i in yun])
#测试下效果
yunlv('烟锁池塘柳')
'平仄平平仄'
yunlv('锈堵油烟机')
'仄仄平平平'
可以看到,很完美的得到了韵律提取函数。得到了部首和韵律,我们就可以进行对联的提取了,并且部分字不认识,我们可以把注音也打出来。
import random
for i in range(10000):
a=random.choice(jin)
b=random.choice(mu)
c=random.choice(shui)
d=random.choice(huo)
e=random.choice(tu)
last=[a,b,c,d,e]
random.shuffle(last)
cnt=Bihua.count(last)
yun=yunlv(last)
if yun=='平平仄仄平':
#if cnt<=60 and yun=='平平仄仄平':
#print('烟 锁 池 塘 柳')
print(' '.join([i[0]for i in pinyin(last)]))
print(' '.join(last))
# 下面是一些示例,大家可以反复运行或者修改运行参数,随随便便跑出几千个下联
chuí tóng dòu hàn zhū
垂 燑 浢 鋎 株
hū zhú huì yì yáng
滹 烛 橞 鈠 垟
qiū yíng jìn zèng qī
坵 謍 濅 锃 桼
cháng féng pù jìn hūn
塲 漨 铺 賮 棔
gē án liè chì mó
鎶 儑 埒 湁 模
qiáng huáng mì xiǎn yé
墙 潢 樒 烍 铘
zhuó xī chèn tuò yíng
灂 釸 疢 柝 茔
tóng shī tǔ zhuàn líng
銅 湿 钍 灷 欞
pí pú yào zhàn xún
焷 圤 钥 栈 潯
tiáo zhuó zhì yì qiān
鋚 濁 櫍 燚 圲
yóu jiē mǎn zhǔ xí
鈾 堦 満 煑 槢
xíng róng zì dòng lián
型 镕 渍 栋 燫
yú lái yǐ tàng jiē
堣 梾 鈘 烫 湝
yā tāng shuò guǐ shān
壓 鐋 烁 氿 杉
jué duó dǎn kě háng
爑 铎 澸 坷 杭
kē zā mèi juǎn mén
柯 沞 煝 埍 钔
yíng sī mì zhì bó
楹 鐁 塓 治 煿
zī tāo yàn lǔ yīn
椔 濤 烻 镥 堙
pō luán què ài huī
钋 滦 燩 塧 楎
gāng xīng yǐng làn táo
钢 皨 潁 爁 檮
biāo chén hào lěi guā
鑣 尘 浩 耒 ?
jiāo tán zhì sì rén
燋 錟 垁 汜 朲
yán tián lèi zhàn fén
炎 沺 銇 棧 坟
jiá lán jiǒng luò fán
圿 钄 颎 漯 杋
hóu tī dàng xù hōng
鍭 梯 圵 洫 灴
pī nóng diàn niè bāng
鈹 燶 澱 臬 垹
biāo máng liàn cǎi zhá
墂 铓 澰 采 煠
tái xī zhì huò gān
枱 焬 滍 镬 坩
léi qiāo yuè yì shuāng
鐳 墝 瀹 焲 欆
nóng yíng yǎn bào táo
燶 塋 沇 鑤 檮
rán zhū miǎn lì xiāng
燃 橥 湎 壢 镶
我们可以看到,部分对联,还是比较生僻,如果为了简单点,我们可以加一个笔画总数约束,也就是尽量找些简单的字来进行对联。
为了得到笔画数,同样,我们需要找到汉字的笔画拆分表,提取每个汉字的笔画,并进行汇总计算,笔画下载地址:
下面构建一个类,输出笔画明细+笔画统计
# 笔画存储
class Chinese2Bihua():
def __init__(self):
#path='C:\\\\Users\\\\伍正祥\\\\Desktop\\\\sin_chinese_feature.txt'
cache_file=open('bihua.txt',encoding='UTF-8')
kv={}
for line in cache_file:
line=line.strip()
if not line:
continue
k, v=line.split(' ')
kv[k]=v
cache_file.close()
self.kv=kv
def word(self,word):
return self.kv.get(word)
def count(self,sen):
bihua=0
for i in sen:
if self.kv.get(i) is None:
continue
else:
bihua +=len(self.kv.get(i))
return bihua
# 测试下数据
Bihua=Chinese2Bihua()# 类的初始化
Bihua.count('二')
2
Bihua.count('我 的')
15
#非常完美,没毛病
我们加个笔画约束看看下面的效果
import random
for i in range(10000):
a=random.choice(jin)
b=random.choice(mu)
c=random.choice(shui)
d=random.choice(huo)
e=random.choice(tu)
last=[a,b,c,d,e]
random.shuffle(last)
cnt=Bihua.count(last)
yun=yunlv(last)
if cnt<=60 and yun=='平平仄仄平':
#print('烟 锁 池 塘 柳')
print(' '.join([i[0]for i in pinyin(last)]))
print(' '.join(last))
huá méi yǎng kěn tuán
釪 煤 柍 垦 漙
qiān qiāng fǒu hào yíng
鉛 缹 滈 茔
wēi shā cuì qià qīn
渨 榝 焠 圶 欽
shū chán biàn dì jī
梳 廛 汴 焍 錤
fēng míng xiè chǎo láng
沨 铭 塮 焣 榔
bó tái cè xǐ huá
浡 炱 墄 鈢 釫
jiān shū chì wò jí
椾 倐 赤 沃 鍓
xiā chā tǔ sè zhī
煆 杈 钍 瀒 坧
xiá hū mì làn quán
鍜 垀 沕 烂 权
fāng lián xiè jì jūn
坊 梿 炨 漃 鍕
duī náo jiǎo mǐn chá
垖 铙 煍 潣 查
xīng xián kài rì hé
皨 閑 炌 釰 渮
yáng wā yǔ tǔ jú
钖 洼 楀 吐 焗
táng pī lìn dù cén
樘 鈚 焛 杜 涔
wū zhuó jiǒng sè fēng
圬 鐯 颎 洓 楓
duī xué bǐng lù méi
堆 燢 柄 錄 没
shū zhuó yàn ruì méi
枢 圴 燕 銳 没
tuó cōng zhì chì chán
沱 鍯 楖 灻 廛
diān pō gěng yì jīn
滇 坡 梗 熼 惍
chuī fá duǒ gǒng gū
炊 橃 埵 汞 鈲
jiāo xún jù biàn fán
焦 栒 锯 汴 墦
xī bīn mǔ zhàn xí
欽 沅 炒 壋 檑
yíng yóu zhà niè bā
塋 沋 炸 鑈 柭
xí zhí bǐ qiàn chēng
隰 釞 朼 壍 浾
yīng shēn lǐ běng chú
煐 罙 锂 埄 滁
sī zhōu chǒu rǒng chóng
鉰 洲 杻 坈 爞
dāo xiá yè xiù wēi
釖 舝 烨 溴 楲
yáo zhá yù mǎo qú
垚 煠 銉 泖 淭
yīn jué sè mù zhōng
溵 鈌 啬 炑 柊
bū xué pǐ mò juān
钸 壆 銢 末 焆
桥 苂 溹 塊 錟
zhū chéng pàn bì yí
橥 洆 鋬 熚 圯
yú cuán xiè chì dāo
漁 櫕 炧 赤 釖
cōng tuō rì hè shā
枞 涶 釰 垎 煞
dá mín dàn qù jūn
炟 鈱 柦 去 汮
qián huī zhà yǒng ōu
钤 楎 炸 涌 塸
kē nóng è shù wā
錒 燶 垩 朮 溛
wā tuān yù sào lú
溛 煓 钰 埽 栌
zūn yān qì huǒ gū
壿 漹 炁 钬 柧
zuó ní shǎng shuò lóng
鈼 棿 垧 烁 泷
chān hú gùn guǐ cháng
鉆 煳 棍 氿 塲
可以看到,结果简单了很多,认识的字更多了,突然又觉得自己有文化了。我们把每次找到的对联都存下来,然后打印出来看看。
import random
result=[]
for i in range(10000):
a=random.choice(jin)
b=random.choice(mu)
c=random.choice(shui)
d=random.choice(huo)
e=random.choice(tu)
last=[a,b,c,d,e]
random.shuffle(last)
cnt=Bihua.count(last)
yun=yunlv(last)
if cnt<=60 and yun=='平平仄仄平':
result.append(''.join(last))
print(';'.join(result))
垺焩黍铄榤 ; 钳縈圣滏椸 ; 垟锵钬瀎杔 ; 湡铨燤圵梮 ; 灾鍻圢櫖淤 ; 滣埁螙釙炱 ; 枨鈙淀坄燌 ; 钖潸汌喣塭 ; 烓涢塔栅鈛 ; 坚錅焘涍棆 ; 栞焢坿浬鉐 ; 鉗沿槏垕熆 ; 圾湨鳥檞鈹 ; 沞封煗錠桩 ; 濤堃朽烢銮 ; 潝堆鈢炮衔 ; 栀鈁炁泮埑 ; 煎埩柮泪錃 ; 垖梂焕鎮泉 ; 墝杷焥铁洖 ; 榹沂炁圡鈙 ; 鋜烑朼堟浵 ; 浹樴者钮燒 ; 查崯灸潰敖 ; 然榅埦涨铛 ; 煠樍靯钙淋 ; 楲铿垕埊然 ; 漥袁枧铞隰 ; 杇漹钺寺熪 ; 坩榸灷鋷沖 ; 楣钔漠熽尘 ; 堘梑汻錽災 ; 鍋枹塛汩狄 ; 闲浗垎焖钸 ; 桜鏠圮洩熢 ; 滖圱钓燪椖 ; 煬鍤柏埧洲 ; 钦埕梪煥源 ; 陞杉烗砅錂 ; 柖漊塊煟锕 ; 铎樔烄沔坟 ; 熵埐榓鈅汲 ; 烣櫡浘锁坮 ; 垣渹镜朹螢 ; 王汍炄検針 ; 閑汘燡埔鈼 ; 栀鎉墄炮沣 ; 柊塋焋滞铘 ; 温铭墤杘瑩 ; 垡鉈柝炨鸿 ; 濄倐釠李坮 ; 沣烠橠塂鋮 ; 灲鈱隶塮棬 ; 墙汀铰枓煨 ; 塇沣镁炈栥 ; 塖钧澯炧栝 ; 涡烦栔錁茔 ; 桲镕焝渧圾 ; 泅墣焌钝极 ; 瑩枌圼泂镌 ; 塲烤隶鋵 ; 柒烔钰淯坻 ; 鈯圱泆熝柑 ; 壆橭烁钚浀 ; 坨榮烱鉩溦 ; 溏然塟柀鉆 ; 棔錡沭焲堗 ; 桢鎥沸坴炊 ; 洵錂圵柍燌 ; 柎謍鉲圽洃 ; 楄灯堓治鎣 ; 銁泉烙垑柊 ; 梌炊鐌垱淮 ; 膋洨壑末蓥 ; 涔垞桎炬锋 ; 庄焂潄錑棏 ; 埏烎錈桺濁 ; 泊銖凷煹椐 ; 濕埘炙柄鋒 ; 炘洐镲塙栓 ; 桹淣錧伙垃 ; 湞烝樸钍垆 ; 鉷焯乐坸潘 ; 栖錂墋氾勲 ; 垶柗澻鋻炢 ; 锡浹柶煃堘 ; 汪槽煮銌垂 ; 舝鵭熐枿汃 ; 焏沧壙铯柖 ; 焞枵涻坅鋐 ; 樋锒堕热活 ; 鋜潭烙赤椏 ; 圭铥栵潻熋 ; 杆沢墤爛钻 ; 橈鋑堌汝炡 ; 坡汆鈷档灼 ; 鑘條坬灿沲 ; 垥熟钮渂機 ; 渠炥銙堿沖 ; 杓垶炼錝滹 ; 烹清堊锞楅 ; 炟铮坬棅淘 ; 塼柭洝鎮阦 ; 楊汮喪点铅 ; 沣堂梞釢焢 ; 激坃梀焊釫 ; 欽煙杌氹塋 ; 栏荧凼鉧坵 ; 漒镃炌枸庄 ; 墚桸渡鍔灮 ; 朾镈焛滠坰 ; 埢汐爓銏柉 ; 湥爑垗铲极 ; 汮棂钑堊熉 ; 沗煴梬钌坰 ; 溓炠堌枻鎣 ; 淭炂鐠埊埘 ; 溇熛垍鋬柟 ; 锎杨煚坠漓 ; 囶燢漴桂铩
再跑一次看看
庄钘榇烙洺;沟煊墡栗菳;沽焷坘榖锒;浉櫄钙疢均;釭漦炫堕梌;杊铼埗炨溻;沦镃垱熐椑;烓椖漌钇坣;镭堆炾尿柌;汐椝熤釜堙;汯塥锃焸梒;洄炢樚堛铛;槭锤炳洷封;栴铟灿垗渶;灼钫栔垾河;杅崯耂澔熑;栿游寺锞熿;铖墎栩溉炊;坰铹漇枕熷;崟垬煜溅桉;熆杧垩铰沨;墘棳炴溽铜;桙滽去铸炋;堞燷钏柢湰;钞熬浻坿杆;铟濓埾栵焯;圴镕槨湼烀;炇棔锴淏坥;壛炘狇淦浽;桼滔铲场烊;洮墔桘灭铥;羔埞潟铝桤;垃椓焖砅钳;沱椈狴烕银;镎澌焥肚柗;格汹老焍铧;沾墪楛钮熆;柌炢铯浅垆;钶倐桽堍溜;炰棸锩坈漦;铥林熝埱氷;釭炡沐橡堦;涟焗朼锓垠;埴铀漤柷煊;镗涎焻栤圿;梢钩汖墥煌;焦锎棈堩泶;镝榙湴烅均;镩煲埱柝汈;镯圻涊焻杗;炉薄铆堡楫;楆浡焙坬锪;杯锝热杜湑;堤焂洱枥铗;梅坽洰锏炻;钹狄梙垼溇;燷钨栺幸汲;衔埛浼槱枭;焉沲堛榚铂;锪墒泲烳樟;炛铥境沸模;铗漽炌垼琹;淓烆坋铳槃;炥坧錾棹溾;铮燫槥肚洭;潴锜炬柲埅;槰炦埱沫针;枝塬泰煗镃;坛椆烈氿錖;泦崟煑塎楆;杝然壤涬钞;锚湡槒炕垠;澓栊镱埜灼;漕柂垱熳锫;樈镖垅泝?;锺爔牡浬柊;榵炰圡濥钲;涵坯煗栚锜;铟涞焫柚培;铀椑烻湫圾;桡垣趛隶畑;熥庄柬录钟;坉倐锴湳楂;镡渮柳垛焆;锖烑栳埒渎;熻汮锻楐囶;镖吙沮埲樨;铔燍扗溆框;楹渔邩镆城;椔涎铽埌焀;锔桏丧熮潀;煌枖圡沆铂;垬铥烂采溓;羙潼铈靯栭;锾枋煝注培;锄堶氼烬栞;滁堐烈桖铌;钦杯燧壻淆;坚炱沝镨楔;柑堾焐锐汐;铃煆洂槾墎;浝铜杌坶阦;煆潆垏钿梎;焷垐溅镚杷;朻锵浨垅倐;栘渄钇舃墂;铎熋朹派壅;埕汲锊炴杇;镎烯圢洩檘;堘淘棐焱钟;铅坚榇渴燔;渔楢坳钼煓;瀛铃炌梪茔;埿炛暴铲椄;埞杠泚灸铭;销濍烜埊梸;墎框汫焌钳;泀埞锏檓烰;铃坛点澍櫋;塄滃钯炌樶;熆塳钣楍洮;茔锣沌炓椃;先铹淌柿熣;铊沦灸柞圪;垥苂锉杻洺;棇渨垌煹惍;镩狄湳垴梭;崯炪涨垢椐;熸镯坈汞桋;炡溟堮镐梛;煘楠泖垍针;沏根坬灺钢;烆梡沥钷圭;畑圱溸檚铟;漘铃燥杪埢