Python填字游戲算法題

今天在OpenHatch上找到一個(gè)涉及到很多Python知識(shí)點(diǎn)的問題接谨,這個(gè)問題寫著適于中級水平的Python程序員自測,需求是編寫一個(gè)帶評分功能的英文填字圖版游戲胧洒,我嘗試用2.7版本的Python對其進(jìn)行了編碼肌厨。

詳細(xì)需求:

practice breaking down a problem and solving it in Python from scratch
practice command line argument parsing
practice reading from files
practice working with dictionaries and for loops

翻譯作中文如下:

題中給了一個(gè)叫做sowpods.txt文件,這個(gè)文件中每一行是一個(gè)大寫單詞
用戶輸入一個(gè)單詞凰狞,通過運(yùn)行程序顯示這個(gè)單詞中的字母能組成的新單詞(小寫)
對于單詞中的字母篇裁,題目對每個(gè)字母給到一個(gè)數(shù)字分?jǐn)?shù),根據(jù)單詞中的字母得到的分?jǐn)?shù)進(jìn)行降序排序

sowpods.txt文件示意圖:


sowpods.jpeg

項(xiàng)目鏈接:

http://webcache.googleusercontent.com/search?q=cache:xcsq7ruu3NoJ:wiki.openhatch.org/Scrabble_challenge+&cd=9&hl=zh-CN&ct=clnk&gl=cn

如果你可以不看我的答案獨(dú)立解出這個(gè)問題赡若,相信你已經(jīng)是個(gè)不錯(cuò)的Python程序員了达布。

如果你有疑問,以下是我的詳細(xì)的思考編碼過程逾冬,也許你可以參考一下黍聂。

既然定義為中級水平,這個(gè)題目還是涉及到幾個(gè)知識(shí)點(diǎn)的身腻,我把我代碼中涉及到的Python知識(shí)點(diǎn)羅列了出來产还,如下:

1.文件操作
2.函數(shù)的使用
3.列表解析的應(yīng)用
4.Python的collections庫中Counter類的巧妙應(yīng)用
5.sys.argv取到用戶輸入的參數(shù)(個(gè)人選擇,用argparse庫效果類似)
   ...

構(gòu)思過程:
用面向函數(shù)的思想對這個(gè)問題進(jìn)行了解答。

程序分為5個(gè)函數(shù):
1.main函數(shù)負(fù)責(zé)接受用戶參數(shù)嘀趟,調(diào)用其他函數(shù)雕沉,和對結(jié)果進(jìn)行排序(你也可以把接受函數(shù)和對結(jié)果排序獨(dú)立為兩個(gè)新函數(shù));
2.get_word_list函數(shù)負(fù)責(zé)把sowpods中的單詞放到一個(gè)list中去件;
3.get_valid_words函數(shù)篩選有效單詞并將其放在list中返回坡椒;
4.lower_valid_words函數(shù)負(fù)責(zé)把get_valid_words函數(shù)變?yōu)樾?若你仔細(xì)做了這個(gè)題目,請?jiān)诹粞灾谢卮疬@個(gè)函數(shù)的好處)尤溜;
5.get_scores函數(shù)負(fù)責(zé)計(jì)算每個(gè)單詞的分?jǐn)?shù)倔叼,并將結(jié)果存放在一個(gè)dict中。

這個(gè)題目的難點(diǎn)在于get_valid_words函數(shù)的編寫宫莱,最初我的思路是把用戶輸入的單詞
sowpods中單詞的比較丈攒,說的具體一點(diǎn),當(dāng)我輸入helo時(shí),程序輸出的結(jié)果是不可以出現(xiàn)hello的巡验,因?yàn)?code>輸入單詞中l的個(gè)數(shù)為1际插,而hellol的個(gè)數(shù)為2,在首次編碼時(shí)显设,用list對用戶輸入單詞進(jìn)行了存儲(chǔ)比較框弛,每當(dāng)找到一個(gè)單詞后就把list中的對應(yīng)的字母移走,寫出來的代碼像這樣:

def get_valid_words(words, rack):
    valid_words = []
    for word in words:
        rack_list = list(rack)
        found = True
        for c in word:
            if c in rack_list:
                rack_list.remove(c)
            else:
                found = False
                break
        if found:
            valid_words.append(word)
    return valid_words

后來我想到collectionsCounter可以進(jìn)行加減運(yùn)算捕捂,可以大大簡化我的代碼瑟枫,而且提高代碼可讀性,更改后的代碼像下面這樣:

def get_valid_words(word_list, rack):
    c = Counter(rack)
    return [word for word in word_list if not (Counter(word) - c)]

參考資料鏈接:
https://pymotw.com/2/collections/counter.html

Counter用法.png

遺憾的是指攒,我對更改后的代碼進(jìn)行運(yùn)行測試慷妙,對于相同的用戶輸入單詞ZZAAEEI ,第一種函數(shù)運(yùn)行需要1.2s,而后一種寫法需要5.4s,這個(gè)問題我沒有細(xì)究允悦,有空我會(huì)看看Counter的源碼膝擂。

下面我貼出每個(gè)函數(shù):
1.main函數(shù)

def main():
    if len(sys.argv) != 2:
        raise SystemExit('Usage: scrabble_change.py RACK')

    rack = sys.argv[1]

    word_list = get_word_list('sowpods.txt')
    valid_words = get_valid_words(word_list, rack.upper())

    valid_words = lower_valid_words(valid_words)

    d = get_scores(valid_words)
    for val, key in sorted(zip(d.values(), d.keys()), reverse=True):
        print(val, key)

2.get_word_list函數(shù)

def get_word_list(file_name):
    word_list = []
    with open(file_name) as f:
        for line in f:
            word_list.append(line.strip())
    return word_list

3.get_valid_words函數(shù)

def get_valid_words(word_list, rack):
    c = Counter(rack)
    return [word for word in word_list if not (Counter(word) - c)]

4.lower_valid_words函數(shù)

def lower_valid_words(words):
    return [word.lower() for word in words]

5.get_scores函數(shù)

def get_scores(words):
    d = {}
    for word in words:
        d[word] = sum(scores[c] for c in word)
    return d

以下是全部代碼,供參考:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

from __future__ import print_function
import sys
from collections import Counter

scores = {"a": 1, "c": 3, "b": 3, "e": 1, "d": 2, "g": 2,
          "f": 4, "i": 1, "h": 4, "k": 5, "j": 8, "m": 3,
          "l": 1, "o": 1, "n": 1, "q": 10, "p": 3, "s": 1,
          "r": 1, "u": 1, "t": 1, "w": 4, "v": 4, "y": 4,
          "x": 8, "z": 10}


def get_word_list(file_name):
    word_list = []
    with open(file_name) as f:
        for line in f:
            word_list.append(line.strip())
    return word_list


def get_valid_words(word_list, rack):
    c = Counter(rack)
    return [word for word in word_list if not (Counter(word) - c)]


def lower_valid_words(words):
    return [word.lower() for word in words]


def get_scores(words):
    d = {}
    for word in words:
        d[word] = sum(scores[c] for c in word)
    return d


def main():
    if len(sys.argv) != 2:
        raise SystemExit('Usage: scrabble_change.py RACK')

    rack = sys.argv[1]

    word_list = get_word_list('sowpods.txt')
    valid_words = get_valid_words(word_list, rack.upper())

    valid_words = lower_valid_words(valid_words)

    d = get_scores(valid_words)
    for val, key in sorted(zip(d.values(), d.keys()), reverse=True):
        print(val, key)


if __name__ == '__main__':
    main()

運(yùn)行效果圖:

運(yùn)行效果

總結(jié):
除了上面指出的知識(shí)點(diǎn)隙弛,本程序函數(shù)的命名也符合<代碼整潔之道>的規(guī)范猿挚,本程序遵守PEP8規(guī)范,若有錯(cuò)誤驶鹉,請大家勘正绩蜻。

歡迎各位指出這個(gè)程序可以改進(jìn)的地方!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末室埋,一起剝皮案震驚了整個(gè)濱河市办绝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌姚淆,老刑警劉巖孕蝉,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異腌逢,居然都是意外死亡降淮,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門搏讶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來佳鳖,“玉大人,你說我怎么就攤上這事媒惕∠捣裕” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵妒蔚,是天一觀的道長穿挨。 經(jīng)常有香客問我月弛,道長,這世上最難降的妖魔是什么科盛? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任帽衙,我火速辦了婚禮,結(jié)果婚禮上贞绵,老公的妹妹穿的比我還像新娘厉萝。我一直安慰自己,他們只是感情好但壮,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著常侣,像睡著了一般蜡饵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胳施,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天溯祸,我揣著相機(jī)與錄音,去河邊找鬼舞肆。 笑死焦辅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的椿胯。 我是一名探鬼主播筷登,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼哩盲!你這毒婦竟也來了前方?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤廉油,失蹤者是張志新(化名)和其女友劉穎惠险,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抒线,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡班巩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嘶炭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抱慌。...
    茶點(diǎn)故事閱讀 40,503評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖眨猎,靈堂內(nèi)的尸體忽然破棺而出遥缕,到底是詐尸還是另有隱情,我是刑警寧澤宵呛,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布单匣,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏户秤。R本人自食惡果不足惜码秉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鸡号。 院中可真熱鬧转砖,春花似錦、人聲如沸鲸伴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽汞窗。三九已至姓赤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間仲吏,已是汗流浹背不铆。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留裹唆,地道東北人誓斥。 一個(gè)月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像许帐,于是被迫代替她去往敵國和親劳坑。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容