[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中很容易被呈现。

 

 

。。。未完待续。。。

posted @ 2022-02-07 21:44  veli  阅读(1165)  评论(0编辑  收藏  举报