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原理,理解函数抽象
posted @ 2020-12-05 14:40  hzy&hmcj  阅读(146)  评论(0)    收藏  举报