1. 程式人生 > 實用技巧 >Python基礎講義(十):組合型別綜合

Python基礎講義(十):組合型別綜合

單元專案

0x01內容導圖

0x02九宮算術

  • 問題描述:將1-9填入3*3的矩陣,滿足行、列、對角線和都相等,可擴充套件為n*n的矩陣(n為奇數)
  • 由來:河圖洛書中的洛書

  • 《射鵰英雄傳》中黃蓉口訣:戴9履1,左3右7,2、4為肩,6、8為足,5坐中間

  • 填數規則:

    • 規則1:最大數位於中間行最後列
    • 規則2:行+1,列+1,未填則填數
    • 規則3:否則退回原處,列減1,填數

  • 實現分析

    • 搭建程式框架
      • 初始化二維列表
      • 填數
      • 顯示
    • 初始化:列表推導式,深拷貝

  • 顯示:二維列表,多重迴圈
  • 填數流程圖

  • 完整程式碼
def init():
    n = int(input())
    grid = [[0]*3 for j in range(n)]
    return grid

def fill(grid):
    n = len(grid)
    r, c = n // 2, n - 1
    for i in range(n*n, 0, -1):
        grid[r][c] = i
        r = (r + 1) % n
        c = (c + 1) % n
        if grid[r][c] != 0:
            r, c = r - 1, c - 2

def disp(grid):
    n = len(grid)
    for i in range(n):
        for j in range(n):
            print("{:3}".format(grid[i][j]), end="")
        print()

def run():
    grid = init()
    fill(grid)
    disp(grid)

if __name__ == "__main__":
    run()

0x03約瑟夫環

  • 問題描述:n個小孩圍成一圈,從第1個小孩開始報數,報到m的倍數離開,直到最後一個。求最後小孩的編號。

  • 由來:據說著名猶太曆史學家Josephus有過以下的故事:在羅馬人佔領喬塔帕特後,39 個猶太人與Josephus及他的朋友躲到一個洞中,39個猶太人決定寧願死也不要被敵人抓到,於是決定了一個自殺方式,41個人排成一個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,然後再由下一個重新報數,直到所有人都自殺身亡為止。

  • 常見問題求解:

    • 剩下n人的編號
    • 求離隊順序
  • 實現分析:

    • 搭建執行框架
      • 初始化列表
      • 求解
      • 獲得獲勝編號
    • 初始化:列表推導式
    • 獲得獲勝編號:列表推導式
    • 求解:圍成一圈、迴圈設計

  • 完整程式碼
def init():
    n, m = map(int, input().split())
    kids = [i for i in range(1, n+1)]
    return kids, m

def solve(kids, m):
    n = r = len(kids)
    count, index = 0, -1
    while r > 1:
        index = (index + 1) % n
        if kids[index] == 0: continue
        count += 1
        if count == m:
            kids[index] = 0
            r -= 1
            count = 0
    return getwinner(kids)

def getwinner(kids):
    ls = [i for i in kids if i != 0]
    return ls[0]

def run():
    kids, m = init()
    winner = solve(kids, m)
    print(winner)

if __name__ == "__main__":
    run()

0x04單詞統計

  • Google公司開發的流行分散式計算框架

  • map過程:建立對映

  • 分組過程:按鍵進行分組

  • reduce過程:合併過程

  • 過程分析

    • 包含單詞的文字或檔案
    • map:(hello, 1), (this, 1), (is 1), (a, 1), (pen 1), (this, 1), (is, 1), (world, 1), (hello, 1)...
    • 分組:{hello:[1, 1], this:[1, 1], is: [1, 1], pen:[1]...
    • reduce: (hello, 2), (this, 2), (is, 2), (pen, 1)...
    • 程式碼實現
    def split_words(text):				#拆分單詞,返回單詞列表
        import re
        p = re.compile(r"\b\w+\b")
        words = re.findall(p, text)
        return words
    
    def word_map(word):					#為單詞建立詞頻條目
        return (word, 1) 
    
    def partition(wordmap):				#按鍵分組
        dic = {}
        for item in wordmap:
            key, value = item[0], item[1]
            ls = dic.get(key, [])
            ls.append(value)
            dic[key] = ls
        return dic.items()
    
    def reduce_words(item):				#合併,此處就是統計過程
        return (item[0], sum(item[1]))
    
    def init_data():
        s = "this is a pen.this is a dog.it is lovely."
        return split_words(s)
    
    def handle_data(data):
        m = [word_map(w) for w in data]					#map
        items = partition(m)
        return [reduce_words(item) for item in items]	#reduce
    
    def run():    
        data = init_data()   
        result = handle_data(data)
        print(result)
    
    if __name__ == "__main__":
        run()
    

    案例擴充套件:

    1. 成績統計,等級統計
    2. 倒排索引

0x05小結

  • 熟悉組合型別的使用場合
  • 熟練掌握組合型別常用操作並能靈活應用
  • 理解MapReduce原理,理解函式抽象