Python算法之旅列表的紛爭之二進(jìn)制編碼

列表的紛爭之二進(jìn)制編碼

小美:最近數(shù)學(xué)老師給我們玩了有趣的猜年齡游戲棚贾,他顯示了6張表格逞力,你只要觀察這6張表格锅论,然后回答“是”與“不是”就可以了祈纯。老師可以根據(jù)你的回答猜出你的年齡是多少令宿。

阿福:真有這么厲害?我也想玩玩看腕窥。

小美:好的粒没。請看下圖的6張表格,然后回答“是”與“不是”簇爆。準(zhǔn)備好了嗎癞松?

阿福:準(zhǔn)備好了。

小美:第1張表格中是否包含了你的年齡入蛆?

阿福:不是响蓉。

小美:第2張表格中是否包含了你的年齡?

阿福:不是安寺。

小美:第3張表格中是否包含了你的年齡厕妖?

阿福:不是。

小美:第4張表格中是否包含了你的年齡挑庶?

阿福:是言秸。

小美:第5張表格中是否包含了你的年齡?

阿福:不是迎捺。

小美:第6張表格中是否包含了你的年齡举畸?

阿福:是。

小美:你今年40歲凳枝。不對抄沮,你虛報(bào)年齡跋核。這應(yīng)該是你老爸的年齡才對。

阿福:沒錯叛买,這就是我老爸的年齡砂代。我不讓你猜我的歲數(shù),還不是因?yàn)槟惚緛砭椭牢叶啻舐收酰遗履阕鞅茁铩?/p>

小美:作弊刻伊?本小姐是這種人嗎?我告訴你椒功,這是科學(xué)捶箱!科學(xué),你懂嗎动漾?

阿福:對對對丁屎,科學(xué),科學(xué)旱眯。開個玩笑嘛晨川。不過你這科學(xué)的力量挺強(qiáng)大的,還真猜出我心里想的數(shù)字了键思。能告訴我這背后有什么原理嗎础爬?

小美:這個嘛。吼鳞。看蚜。。赔桌。供炎。我先不告訴你,給你一張圖疾党,看你能不能找出規(guī)律來音诫。

阿福:二進(jìn)制數(shù)。

小美:沒錯雪位,就是二進(jìn)制數(shù)竭钝。你看出這些二進(jìn)制數(shù)有什么規(guī)律了嗎?

阿福:看出來了雹洗,圖2表格中的每一個二進(jìn)制數(shù)都跟圖1表格中的十進(jìn)制數(shù)一一對應(yīng)香罐。

小美:還有呢?

阿福:還有时肿?暫時沒看出來庇茫。

小美:這都看不出來?眼睛白長了螃成。我再給你點(diǎn)提示吧旦签,看看每個表格中所有的二進(jìn)制數(shù)符號1的位置和表格編號的關(guān)系查坪。

阿福:符號1的位置,表格編號宁炫。偿曙。。淋淀。遥昧。覆醇。它們有什么關(guān)系呢朵纷?再讓我想想。永脓。袍辞。。常摧。搅吁。看到了落午!表格1中所有二進(jìn)制數(shù)的第1位(從右往左數(shù))都是1谎懦,表格2中所有二進(jìn)制數(shù)的第2位(從右往左數(shù))都是1,一直到表格6中所有二進(jìn)制數(shù)的第6位(從右往左數(shù))都是1溃斋。

小美:沒錯界拦,正是這樣!孺子可教也梗劫!

阿福:可是這樣的規(guī)律又有什么用呢享甸?

小美:有什么用?你個榆木腦袋梳侨。這樣就可以計(jì)算你的年齡了啊蛉威。你剛才不是說了嗎,第幾張表格就對應(yīng)二進(jìn)制數(shù)的第幾位走哺,這個位上面是符號1蚯嫌,就代表你的年齡出現(xiàn)在了這張表格中啊。哪幾張表格出現(xiàn)了你的年齡丙躏,就代表你的年齡對應(yīng)的二進(jìn)制數(shù)在這幾個位上的符號是1择示,否則就代表這個位上的符號是0。

阿福:原來是這樣彼哼。我明白了对妄,剛才你是根據(jù)二進(jìn)制數(shù)各個位的情況,轉(zhuǎn)化成十進(jìn)制數(shù)以后得到我的年齡的啊敢朱。讓我算一算剪菱,0*2^0 + 0*2^1 + 0*2^2 + 1*2^3 + 0*2^4 + 1*2^5 = 40摩瞎,完全正確。

小美:這回搞懂了吧孝常?

阿福:總算明白了旗们。沒想到這里還隱藏著二進(jìn)制編碼的奧秘。不錯构灸,有點(diǎn)意思上渴。對了,小美喜颁,我覺得這是一個編程的好素材啊稠氮。你不是擅長海龜作圖嗎,能不能用turtle把上面那兩張圖畫出來啊半开。

小美:這有什么難的隔披,不就是畫幾張表格嗎?我只需要用一個二維列表table存儲每一個表格中的數(shù)字就行了寂拆。例如table[0] = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63]奢米,表示table[0]存儲了表1中的所有數(shù)字。我只要寫一個函數(shù)依次把表格編號纠永,表格線和數(shù)字畫出來就行了鬓长。


題目1:

函數(shù)功能:根據(jù)輸入的表格內(nèi)容,畫len(table)個4行col列的二維表格

函數(shù)名:draw_table(x0,y0, h, w, table)

參數(shù)表:x0, y0 -- 存儲了第一張表格的左上角坐標(biāo)

??????? h, w --分別表示表格的高度和寬度

??????? table --存儲了表格內(nèi)容的二維列表尝江。

返回值:沒有返回值涉波。


代碼1:

def draw_table(x0,y0, h, w, table):

??? n = len(table)

??? col = len(table[0]) // 4 #每張表均分成4行col列

??? for i in range(n):#從上到下依次排列共n張4行col列的二維表格

??????? y0 -= h * 5

??????? for command in ('編號', '畫線', '寫字'):

??????????? if command == '編號':

??????????????? tt.penup()

??????????????? tt.goto(x0-40, y0-h*2)

??????????????? tt.pendown()

??????????????? num = ''.join(['表', str(i+1),':'])

??????????????? tt.write(num,align="center", font=("黑體", 16,"normal"))

??????????? elif command == '畫線':

??????????????? for j in range(5):#畫5條橫線

??????????????????? x, y = x0, y0 - j * h

??????????????????? tt.penup()

??????????????????? tt.goto(x, y)

??????????????????? tt.pendown()

??????????????????? tt.forward(col * w)

??????????????? tt.right(90)

??????????????? for j in range(col+1):#畫col+1條豎線

??????????????????? x, y = x0 + j * w, y0

??????????????????? tt.penup()

??????????????????? tt.goto(x, y)

??????????????????? tt.pendown()

??????????????????? tt.forward(4 * h)

??????????????? tt.right(-90)

??????????? else:

??????????????? for r in range(4):

??????????????????? x, y = x0, y0 - r * h - h /2

??????????????????? for c in range(col):

????????? ??????????????tt.penup()

??????????????????????? tt.goto(x+w/2, y-h*2/5)

??????????????????????? tt.pendown()

???????????????????????tt.write(table[i][r*col+c], align="center", font=("黑體", 12,"normal"))

??????????????????????? x += w


import turtle as tt

tt.TurtleScreen._RUNNING= True? #啟動繪圖,在IDE中運(yùn)行加這句可避免報(bào)錯

tt.speed(0)

tt.ht()#隱藏筆頭

table = [[1, 3, 5,7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45,47, 49, 51, 53, 55, 57, 59, 61, 63],

???????? [2, 3, 6, 7, 10, 11, 14, 15, 18, 19,22, 23, 26, 27, 30, 31, 34, 35, 38, 39, 42, 43, 46, 47, 50, 51, 54, 55, 58, 59,62, 63],

???????? [4, 5, 6, 7, 12, 13, 14, 15, 20, 21,22, 23, 28, 29, 30, 31, 36, 37, 38, 39, 44, 45, 46, 47, 52, 53, 54, 55, 60, 61,62, 63],

???????? [8, 9, 10, 11, 12, 13, 14, 15, 24, 25,26, 27, 28, 29, 30, 31, 40, 41, 42, 43, 44, 45, 46, 47, 56, 57, 58, 59, 60, 61,62, 63],

???????? [16, 17, 18, 19, 20, 21, 22, 23, 24,25, 26, 27, 28, 29, 30, 31, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,61, 62, 63],

????? ???[32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,63]]

x0, y0, h, w = -400, 600, 25, 60 #分別存儲了第一張表格的左上角坐標(biāo)茂装、高度和寬度

draw_table(x0, y0,h, w, table)

tt.done()

古老師:嗯怠蹂,不錯,小美的海龜作圖是畫得越來越溜了少态〕遣啵可美中不足的是這個存儲表格信息的二維列表還是手動生成的,可惜彼妻,可惜跋佑印!

小美:可惜侨歉?不手動生成屋摇,難道還可以自動生成?

阿福:當(dāng)然可以啦幽邓。難道你沒有學(xué)過列表生成式嗎炮温?

小美:列表生成式?什么是列表生成式牵舵?

古老師:列表生成式是Python內(nèi)置的非常簡單卻強(qiáng)大的功能柒啤,它可以用來快速創(chuàng)建一個列表倦挂。例如我們要生成一個列表a = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100],只需寫做a = [x * x for x in range(1, 11)]担巩。寫列表生成式時方援,把要生成的元素x * x放到前面,后面跟for循環(huán)涛癌,就可以把list創(chuàng)建出來犯戏,非常簡單方便。

阿福:for循環(huán)后面還可以加上if判斷拳话,這樣我們就可以篩選出僅奇數(shù)的平方:a = [x * x for x in range(1, 11) if x % 2 == 1]先匪。

小美:哦,原來是這樣假颇。我知道了胚鸯,我們可以生成一個二維列表,該列表的每一個元素都是一個列表笨鸡,我們可以使用列表生成式生成每一個列表元素。例如table[0] = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63]坦冠,它是表1中的數(shù)字形耗,其特征是轉(zhuǎn)化成二進(jìn)制數(shù)后第1位(從右往左數(shù))都是1,我可以使用內(nèi)置函數(shù)bin()把十進(jìn)制數(shù)轉(zhuǎn)換成二進(jìn)制數(shù)辙浑,然后判斷它的第1位是不是1激涤,從而生成table[0]的值。以此類推可以生成所有的table[i]判呕。

阿福:沒錯倦踢,就是這樣。還可以不使用bin()函數(shù)侠草,而是利用按位與運(yùn)算來判斷某個二進(jìn)制數(shù)的第i位是不是1辱挥。

古老師:阿福思維很開闊,我們確實(shí)可以用多種方法來判斷二進(jìn)制數(shù)的某個位是1還是0边涕。這樣吧晤碘,我來分配一下任務(wù),小美用bin()函數(shù)做功蜓,阿福用位運(yùn)算做园爷,最后看看效果是否相同。


知識小貼士:

Python bin() 函數(shù):bin() 返回一個整數(shù)的二進(jìn)制表示式撼,其語法為bin(x)童社,其中x是int或者long int數(shù)字,返回值是一個字符串著隆。例如bin(10)返回'0b1010'扰楼,bin(-6)返回'-0b110'甘改。


代碼2:

n = 6

table = [[x for xin range(2**i, 2**n+1) if x & 2**i != 0] for i in range(n)]

代碼3:

n = 6

table = [[x for xin range(2**i, 2**n+1) if bin(x)[-i-1] == '1'] for i in range(n)]

table2 =[[bin(x)[2:] for x in range(2**i, 2**n+1) if bin(x)[-i-1] == '1'] for i inrange(n)]

古老師:非常好!都抓住了列表生成式的精髓灭抑,其中小美還把十進(jìn)制和二進(jìn)制數(shù)兩個列表都生成了十艾,很有創(chuàng)造性。阿福的位運(yùn)算代碼也很簡潔腾节,值得表揚(yáng)忘嫉!

對了,上次我在公園里看到一個猜姓氏的游戲案腺,界面如下圖所示庆冕。你們看看它背后的原理是什么?

小美:這不就是剛才我們玩的猜年齡游戲嗎劈榨?只不過它把數(shù)字改成了姓氏访递,道理是一樣一樣的。

阿福:沒錯同辣,又是一個二進(jìn)制編碼的游戲拷姿。

古老師:眼睛夠亮的啊旱函!既然你們都看出來了响巢,那就用turtle把它畫出來吧。

這是要用到的百家姓前128種姓氏:李王張劉陳楊趙黃周吳徐孫胡朱高林何郭馬羅梁宋鄭謝韓唐馮于董蕭程曹袁鄧許傅沈曾彭呂蘇盧蔣蔡賈丁魏薛葉閻余潘杜戴夏鐘汪田任姜范方石姚譚廖鄒熊金陸郝孔白崔康毛邱秦江史顧侯邵孟龍萬段漕錢湯尹黎易常武喬賀賴龔文龐樊蘭殷施陶洪翟安顏倪嚴(yán)牛溫蘆季俞章魯葛伍韋申尤畢聶叢焦棒妨。

我還有點(diǎn)事踪古,就先走了,回頭見啊券腔。



彩蛋:

阿福:這個好像可以直接調(diào)用你前面寫的draw_table()函數(shù)伏穆,只要修改一下table列表的值就行了。

小美:那當(dāng)然了纷纫,這就叫做函數(shù)的通用性枕扫。還不錯吧?

阿福:看你嘚瑟的涛酗,這不應(yīng)該是編寫函數(shù)的基本要求嗎铡原?對了,代碼寫好了嗎商叹?

小美:早就寫好了燕刻。因?yàn)榭梢灾苯诱{(diào)用draw_table()函數(shù),所以我只寫了主函數(shù)部分剖笙。


代碼4:

import turtle as tt

tt.TurtleScreen._RUNNING= True? #啟動繪圖卵洗,在IDE中運(yùn)行加這句可避免報(bào)錯

tt.speed(0)

tt.ht()#隱藏筆頭

xing = '李王張劉陳楊趙黃周吳徐孫胡朱高林何郭馬羅梁宋鄭謝韓唐馮于董蕭程曹袁鄧許傅沈曾彭呂蘇盧蔣蔡賈丁魏薛葉閻余潘杜戴夏鐘汪田任姜范方石姚譚廖鄒熊金陸郝孔白崔康毛邱秦江史顧侯邵孟龍萬段漕錢湯尹黎易常武喬賀賴龔文龐樊蘭殷施陶洪翟安顏倪嚴(yán)牛溫蘆季俞章魯葛伍韋申尤畢聶叢焦'

n = 7

table =[[xing[x-1] for x in range(2**i, 2**n+1) if x & 2**i != 0] for i inrange(n)]

x0, y0, h, w = -400, 600, 25, 60 #分別存儲了第一張表格的左上角坐標(biāo)、高度和寬度

draw_table(x0, y0,h, w, table)

num = input('輸入二進(jìn)制編碼:')

print(f'{xing[int(num[::-1],2)-1]}先生/女士,你好过蹂!')

tt.done()

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末十绑,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子酷勺,更是在濱河造成了極大的恐慌本橙,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脆诉,死亡現(xiàn)場離奇詭異甚亭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)击胜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門亏狰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人偶摔,你說我怎么就攤上這事暇唾。” “怎么了辰斋?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵策州,是天一觀的道長。 經(jīng)常有香客問我亡呵,道長抽活,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任锰什,我火速辦了婚禮,結(jié)果婚禮上丁逝,老公的妹妹穿的比我還像新娘汁胆。我一直安慰自己,他們只是感情好霜幼,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布嫩码。 她就那樣靜靜地躺著,像睡著了一般罪既。 火紅的嫁衣襯著肌膚如雪铸题。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天琢感,我揣著相機(jī)與錄音丢间,去河邊找鬼。 笑死驹针,一個胖子當(dāng)著我的面吹牛烘挫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播柬甥,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼饮六,長吁一口氣:“原來是場噩夢啊……” “哼其垄!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起卤橄,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤绿满,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后窟扑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體喇颁,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年辜膝,在試婚紗的時候發(fā)現(xiàn)自己被綠了无牵。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡厂抖,死狀恐怖茎毁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情忱辅,我是刑警寧澤七蜘,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站墙懂,受9級特大地震影響橡卤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜损搬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一碧库、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧巧勤,春花似錦嵌灰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至剩瓶,卻和暖如春驹溃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背延曙。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工豌鹤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人搂鲫。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓傍药,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子拐辽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

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