[Python学习笔记-012] 古巴比伦人的乘法表
问题:我们知道,古巴比伦人采用的六十进制。那么,如果为古巴比伦人绘制一张59x59的乘法表,该如何实现呢?通过Python实现并不复杂,但关键步骤有二:
- 01 - 将十进制数转换为六十进制数
- 02 - 将六十进制数翻译成古巴比伦人的符号数字
在实现上述关键步骤之前,我们先看看古巴比伦人的符号数字。
在上述符号系统中,一把小钥匙表示1,一个鱼骨头表示10。
- 1
- 10
接下来,我们将任何一个十进制数转换为六十进制数。
1. 将十进制数转换为六十进制数
1 def dec2basen(n, basen=2): 2 """ Convert decimal number to base-N number """ 3 m = n 4 k = 0 5 while True: 6 cnt = m // basen 7 if cnt == 0: 8 break 9 m = cnt 10 k += 1 11 12 m = n 13 out = [] 14 i = k 15 while i >= 0: 16 x = m // (basen ** i) 17 out.append(x) 18 19 m -= x * (basen ** i) 20 i -= 1 21 22 return out 23 24 25 def dectobase60(n): 26 """ Convert decimal number to base-60 number """ 27 return dec2basen(n, 60)
2. 创建古巴比伦人的数字符号表
如果用字母B代表一个鱼骨头(10),字母K代表一把小钥匙(1),那么我们可以通过如下函数创建古巴比伦人的数字符号表。
1 BABYLON_NS_KEY = 'K' 2 BABYLON_NS_FISH_BONE = 'B' 3 4 5 def create_ancient_babylonian_num_sym_tbl(): 6 sym_table = [] 7 for i in range(1, 60, 1): 8 n = i 9 na = n // 10 # get the number of keys while key = 1 10 nb = n % 10 # get the number of fish bones while fish bone = 10 11 sym = BABYLON_NS_FISH_BONE * na + BABYLON_NS_KEY * nb 12 sym_table.append({'b10': n, 'b60': sym}) 13 return sym_table
通过上述函数生成的数字符号表如下所示:
{'b60': 'K', 'b10': 1} {'b60': 'KK', 'b10': 2} {'b60': 'KKK', 'b10': 3} {'b60': 'KKKK', 'b10': 4} {'b60': 'KKKKK', 'b10': 5} {'b60': 'KKKKKK', 'b10': 6} {'b60': 'KKKKKKK', 'b10': 7} {'b60': 'KKKKKKKK', 'b10': 8} {'b60': 'KKKKKKKKK', 'b10': 9} {'b60': 'B', 'b10': 10} ...<snip>............................. {'b60': 'BBBBB', 'b10': 50} {'b60': 'BBBBBK', 'b10': 51} {'b60': 'BBBBBKK', 'b10': 52} {'b60': 'BBBBBKKK', 'b10': 53} {'b60': 'BBBBBKKKK', 'b10': 54} {'b60': 'BBBBBKKKKK', 'b10': 55} {'b60': 'BBBBBKKKKKK', 'b10': 56} {'b60': 'BBBBBKKKKKKK', 'b10': 57} {'b60': 'BBBBBKKKKKKKK', 'b10': 58} {'b60': 'BBBBBKKKKKKKKK', 'b10': 59}
3. 将六十进制数翻译成古巴比伦人的数字符号
由于古巴比伦人的数字系统中没有零,于是我们用字母Z代表零(0)。
1 BABYLON_NS_ZERO = 'Z' 2 3 4 def get_sym_bydec(dec, sym_tbl): 5 for sym in sym_tbl: 6 if dec == sym['b10']: 7 return sym['b60'] 8 return BABYLON_NS_ZERO 9 10 11 def get_sym_byb60(l60n, sym_tbl): 12 out = [] 13 for dec in l60n: 14 out.append(get_sym_bydec(dec, sym_tbl)) 15 return ','.join(out)
通过上述函数,如将一个十进制数转化成六十进制数后,翻译成古巴比伦人的数字符号,示例如下:
0 : [0] ==> Z 1 : [1] ==> K 10 : [10] ==> B 11 : [11] ==> BK 59 : [59] ==> BBBBBKKKKKKKKK 60 : [1, 0] ==> K,Z 61 : [1, 1] ==> K,K 81 : [1, 21] ==> K,BBK 3601 : [1, 0, 1] ==> K,Z,K 3481 : [58, 1] ==> BBBBBKKKKKKKK,K
4. 构造59x59的乘法表
对每一项采用字典进行存储,存储结构如下:
{ "a": { "desc": "multiplicand", "b10": "TYPE is int", "s60": "TYPE is string", "l60": "TYPE is list" }, "b": { "desc": "multiplier", "b10": "TYPE is int", "s60": "TYPE is string", "l60": "TYPE is list" }, "c": { "desc": "product", "b10": "TYPE is int", "s60": "TYPE is string", "l60": "TYPE is list" } }
例如:9 * 9 = 81 被存储为:
{ "a": { "desc": "multiplicand = a", "b10": 9, "s60": "KKKKKKKKK", "l60": [ 9 ] }, "b": { "desc": "multiplier = b", "b10": 9, "s60": "KKKKKKKKK", "l60": [ 9 ] }, "c": { "desc": "product = a x b = c", "b10": 81, "s60": "K,BBK", "l60": [ 1, 21 ] } }
基于上述存储结构,实现代码如下:
1 def create_mul_tbl(sym_tbl, n=59): 2 mul_tbl = [] 3 for i in range(n): 4 a = i + 1 5 col = [] 6 for j in range(n): 7 b = j + 1 8 if b < a: 9 continue 10 # 11 # MULTIPLICAND x MULTIPLIER = PRODUCT 12 # a x b = c 13 # 14 c = a * b 15 la60 = dectobase60(a) 16 lb60 = dectobase60(b) 17 lc60 = dectobase60(c) 18 d_cell = {} 19 d_cell['a'] = {} 20 d_cell['b'] = {} 21 d_cell['c'] = {} 22 d_cell['a']['desc'] = 'multiplicand = a' 23 d_cell['a']['b10'] = a 24 d_cell['a']['s60'] = get_sym_byb60(la60, sym_tbl) 25 d_cell['a']['l60'] = la60 26 d_cell['b']['desc'] = 'multiplier = b' 27 d_cell['b']['b10'] = b 28 d_cell['b']['s60'] = get_sym_byb60(lb60, sym_tbl) 29 d_cell['b']['l60'] = lb60 30 d_cell['c']['desc'] = 'product = a x b = c' 31 d_cell['c']['b10'] = c 32 d_cell['c']['s60'] = get_sym_byb60(lc60, sym_tbl) 33 d_cell['c']['l60'] = lc60 34 col.append(d_cell) 35 mul_tbl.append(col) 36 return mul_tbl
5. 纯文本输出59x59的乘法表
基于纯文本输出,很容易实现,实现的函数如下:
1 def output_text(mul_tbl, verbose=False): 2 for col in mul_tbl: 3 for row in col: 4 if verbose: 5 if len(row['c']['l60']) == 2: 6 x1 = row['c']['l60'][0] 7 x2 = row['c']['l60'][1] 8 else: 9 x1 = 0 10 x2 = row['c']['l60'][0] 11 print('#\t%2d x %2d = %d = %2d x 60 + %2d' % 12 (row['a']['b10'], row['b']['b10'], row['c']['b10'], 13 x1, x2)) 14 print('%s\tx\t%s\t= %s' % 15 (row['a']['s60'], row['b']['s60'], row['c']['s60'])) 16 print()
输出效果如下:
K x K = K K x KK = KK K x KKK = KKK K x KKKK = KKKK K x KKKKK = KKKKK K x KKKKKK = KKKKKK K x KKKKKKK = KKKKKKK K x KKKKKKKK = KKKKKKKK K x KKKKKKKKK = KKKKKKKKK ...<snip>... BBBBBKKKKKKKK x BBBBBKKKKKKKK = BBBBBKKKKKK,KKKK BBBBBKKKKKKKK x BBBBBKKKKKKKKK = BBBBBKKKKKKK,KK BBBBBKKKKKKKKK x BBBBBKKKKKKKKK = BBBBBKKKKKKKK,K
6. 富文本输出59x59的乘法表
为了真实再现古巴比伦人的数字符号,我们必须采用富文本输出,这里利用MarkDown实现,因为图片在MarkDown中很容易被呈现。
。。。未完待续。。。