話說幾天前 DR 看到一份填字題目,就是那種有三個中文字,例如「法」、「復」、「語」,然後填入一個相同的字讓各個配對可以組成合宜的字詞,以這個例子來說,可以填入的解答就例如有「古」、「國」等。而當 DR 在嘗試作答時,突然靈機一動想到,其實只要有適當的詞庫,這應該是可以用程式去協助解答的。
那麼去哪裡找詞庫呢?DR 很快的想起開放原始碼的新酷音輸入法,於是在 GitHub 上把新酷音輸入法的純文字詞庫檔(tsi.src)抓下來,接著就開始嘗試用 Python 寫出填字程式,所構思的程式運作流程大概像這樣:
- 讀取詞庫文字檔,篩選出兩個字的字詞。
- 三個題目字各自去搜尋符合的字詞,並存成三組詞庫。
- 清除三組詞庫中各自的題目字。
- 比對三組詞庫中的剩餘文字,三組詞庫皆有的字便是可用的答案。
由於 DR 主要是想測試觀念的實作,所以沒有設計任何的操作介面,執行的流程是先將題目字以逗點分隔的方式寫入 input.txt,然後執行 xword.py 便會將解答(如果有的話)輸出到 output.txt。完成的程式碼內容如下:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os, sys
import codecs
ENCODING = "utf-8"
LIBRARY = "tsi.src"
INPUT = "input.txt"
OUTPUT = "output.txt"
CHARS = 3
def readLibrary():
libs = []
libFile = codecs.open(LIBRARY, "r", ENCODING)
for line in libFile.readlines():
word = line.split(" ")[0]
if len(word) == 2:
libs.append(word)
libFile.close()
return libs
def readQuery():
inputFile = codecs.open(INPUT, "r", ENCODING)
queries = inputFile.read().replace(u"\uFEFF", "").split(u",")
for x in range(0, CHARS):
queries[x] = queries[x].strip()
inputFile.close()
return queries
def findWords(libs, queries):
wordSet = []
for x in range(0, CHARS):
words = []
for y in range(0, len(libs)):
if queries[x] in libs[y]:
words.append(libs[y])
wordSet.append(words)
return wordSet
def findDiff(diffSet, queries):
for x in range(0, CHARS):
char = []
for y in range(0, len(diffSet[x])):
diffSet[x][y] = diffSet[x][y].replace(queries[x], u"")
return diffSet
def findAnswers(diffSet):
outputFile = codecs.open(OUTPUT, "w", ENCODING)
outputFile.write(u"\uFEFF")
for x in range(0, len(diffSet[0])):
matches = 0
for y in range(1, len(diffSet)):
for z in range(0, len(diffSet[y])):
if diffSet[0][x] == diffSet[y][z]:
matches = matches + 1
break
if matches == (CHARS -1):
outputFile.write(u"%s\n" % diffSet[0][x])
outputFile.close()
def xword():
appdir = os.path.abspath(os.path.dirname(sys.argv[0]))
os.chdir(appdir)
if os.path.exists(LIBRARY):
if os.path.exists(INPUT):
libs = readLibrary()
queries = readQuery()
wordSet = findWords(libs, queries)
diffSet = findDiff(wordSet, queries)
findAnswers(diffSet)
print "Done."
else:
print "Input not found, abort."
else:
print "Library not found, abort."
if __name__ == "__main__":
xword()
原始碼加上詞庫的檔案包則在此:xword.zip。
這支程式確實可用,不過一個顯而易見的缺陷是:它無法處理疊字型態的字詞。