1 1一摞Python風格的紙牌

2021-08-29 05:20:54 字數 3636 閱讀 5293

參考資料luciano ramalho《流暢的python》

from collections import namedtuple

city = namedtuple('city', 'name,country,population,coordinates')

# 建立乙個具名元組需要兩個引數,乙個是類名,另乙個是類的各個欄位的名字。

# name country population coordinates都被稱為「欄位名」

# 後者也可以是由數個字串組成的可迭代物件

# ['name','country','population','coordinates']

# 或者是由空格或逗號分隔開的欄位名組成的字串

# 'name,country,population,coordinates'

# 'name country population coordinates'

tokyo = city('tokyo', 'jp', 36.933, (35.689722, 139.691667))

# 存放在對應欄位裡的資料要以一串引數的形式傳入到建構函式中(注意,元組的建構函式卻只接受單一的可迭代物件)

# 這個「卻」字是相對於上面具名元組的建立而言的,因為在上面,引數各個欄位名的傳入就可以用多種物件

print(tokyo)

# city(name='tokyo', country='jp', population=36.933, coordinates=(35.689722, 139.691667))

print(tokyo.population)

# 36.933

print(tokyo[1])

# jp

# 可以通過「欄位名」或者「位置(index)」來獲取乙個欄位的資訊。

import collections

card = collections.namedtuple('card', 'rank,suit')

class frenchdeck:

ranks = [str(n) for n in range(2, 11)] + list('jqka')

suits = 'spades diamonds clubs hearts'.split()

# [str(n) for n in range(2, 11)] + list('jqka') 即為['2', '3', '4', '5', '6', '7', '8', '9', '10', 'j', 'q', 'k', 'a']

# list('jqka') 即為['j', 'q', 'k', 'a']

# 'spades diamonds clubs hearts'.split()即為['spades', 'diamonds', 'clubs', 'hearts']

def __init__(self):

self._cards = [card(rank, suit) for suit in self.suits

for rank in self.ranks]

# 類frenchdeck的例項已被建立就會擁有屬性_cards,該屬性是乙個list,list中的元素都是有名元組,這些元組都是由生成器

# collections.namedtuple('card', 'rank,suit')生成的。在向這個生成器傳入引數時,運用了遍歷操作。

def __len__(self):

return len(self._cards)

# 定義了乙個例項方法,返回值是這個類的屬性_cards的長度

# 在計算機執行指令len(object)時,會立即對映這個方法,返回該方法的返回值,

# 此時,len指令沒有什麼關於len本身的特定意義,只是簡單地映**這個方法。

def __getitem__(self, position):

return self._cards[position]

# 在定義了方法__getitem__以後,這個物件就變得iterable,可以當做可迭代物件來使用

# 具體把它當做什麼可迭代物件,就要由__getitem__的返回值來定了

# 一般而言,這個可迭代物件儲存在例項的乙個屬性裡

deck = frenchdeck()

# 我們建立了乙個物件deck

# 它具有屬性_cards,它可具有方法__len__和__getitem__

# print(len(deck))

# print(deck[0]) # 第一張紙牌,應該是黑桃2

# print(deck[-1]) # 最後一張紙牌,應該是紅桃a

# 上兩行的**得以實現是因為方法__getitem__

# from random import choice

## print(choice(deck)) # 從乙個iterable中隨機選取乙個

# print(choice(deck))

# print(choice(deck))

# print(choice(deck))

# for card in deck:

# print(card)# 這裡用到了方法__getitem__

# # 還可以反向迭代

# for card in reversed(deck):

# print(card)

suit_values = dict(spades=3, hearts=2, diamonds=1, clubs=0) # suit的值

def spade_high(card):

rank_value = frenchdeck.ranks.index(card.rank) # rank的值

# 在例項deck裡面,每乙個元素都是乙個有名tuple,我們獲取這個tuple的屬性rank,即得到了撲克牌的點數,

# 然後用index函式得到了點數在列表frenchdeck.ranks中對應的索引,並將它作為撲克牌排序的依據之一賦值給rank_value

return rank_value * len(suit_values) + suit_values[card.suit]

# 這個排序依據的含義:

# suit_values[card.suit]就是花色在字典suit_values中對應的值

# len(suit_values)就是4

# rank_value*4,也就是撲克牌的數字乘以4,那麼要注意jqka的處理

for card in sorted(deck, key=spade_high): # deck是我們要進行排序的iterable,key=spade_high是排序依據

print(card)

# 這裡的排序依據是乙個函式,那麼肯定是這樣的:

# 將iterable的每乙個元素作為引數傳入這個函式,得到int型別的返回值,根據這個返回值來進行排序

# 由此可以推測,在spade_high函式體裡的card其實是可迭代物件deck的元素。

# sorted接受兩個引數

# arg1是需要進行排序的iterable

# arg2是乙個函式,這個函式應該滿足以下條件

# 引數是iterable arg1的element

# 返回值是element通過某種法則得到的int

一摞烙餅的排序(0621)

每乙個演算法都值得好好地分析 問題 假設有n塊大小不一的烙餅,那最少要翻幾次,才能達到最後大小有序的結果呢?這個排序問題非常有意思,首先我們要弄清楚解決問題的關鍵操作 單手每次抓幾塊餅,全部顛倒 每次我們只能選擇最上方的一堆餅,一起翻轉。而不能一張張地直接抽出來,然後進行插入,也不能交換任意兩塊餅子...

1 3 一摞烙餅的排序

一摞亂序擺放的烙餅,每次只能抓取最上面幾塊烙餅並翻轉,多次翻轉後能夠實現烙餅的從小到大 從上往下 的有序擺放。問題分析 這裡我們使用回溯法解決這個問題。直接用回溯法效率是低下的,因此要進行剪枝。這裡的剪枝條件是利用翻轉次數的上界和下界完成的。上界 4,2,1,5,3 5,1,2,4,3 3,4,2,...

1 3 一摞烙餅的排序

假設有n塊大小不一樣的烙餅,那麼最少要翻動幾次,才能達到最終有序的結果。思路 每次找到最大的然後從將最大的以及最大的上面的反轉,這時候最大的在最上面,然後將整個反轉,最大的就在最下面了。然後再對除了最下面的n 1個烙餅進行上述的操作,知道全部的烙餅有序。例如 13524 53124 42135 cl...