Last active
March 10, 2022 16:01
-
-
Save brchiu/0ec5f35282944af06ec07e9e1c4ee4f4 to your computer and use it in GitHub Desktop.
大衍之數揲卦法的後半段
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# -*- coding: utf-8 -*- | |
import random | |
# import numpy as np | |
# fmt: off | |
# from 易經 | |
# 六十四卦中的第幾卦, 0 到 63 | |
yi = [ | |
"乾", "坤", "屯", "蒙", "需", "訟", "師", | |
"比", "小畜", "履", "泰", "否", | |
"同人", "大有", "謙", "豫", "隨", | |
"蠱", "臨", "觀", "噬嗑", "賁", | |
"剝", "復", "無妄", "大畜", "頤", | |
"大過", "坎", "離", | |
"咸", "恆", "遯", "大壯", | |
"晉", "明夷", "家人", "睽", | |
"蹇", "解", "損", "益", "夬", "姤", "萃", | |
"升", "困", "井", "革", "鼎", "震", | |
"艮", "漸", "歸妹", "豐", "旅", "巽", | |
"兌", "渙", "節", "中孚", | |
"小過", "既濟", "未濟", | |
] | |
# from wiki 易經條目 | |
# 乾卦:六個 1,數字是 63 | |
# 屯卦:[1, 0, 0, 0, 1, 0] => 17 | |
yi_order = [63, 0, 17, 34, 23, 58, 2, 16, 55, 59, 7, 56, 61, 47, 4, 8, 25, 38, 3, 48, 41, \ | |
37, 32, 1, 57, 39, 33, 30, 18, 45, 28, 14, 60, 15, 40, 5, 53, 43, 20, 10, 35, 49, \ | |
31, 62, 24, 6, 26, 22, 29, 46, 9, 36, 52, 11, 13, 44, 54, 27, 50, 19, 51, 12, 21, 42] | |
# fmt: on | |
# 將卦的六爻,以 0 代表陰爻,1 代表陽爻,轉換為 0 to 63 的數字, | |
# 第一爻在最底下,第六爻在最上面,與揲卦順序一致 | |
# 例如:[0, 0, 0, 0, 0, 0] => 0,[0, 0, 0, 1, 0, 1] => 40 | |
def binary_to_int(l): | |
assert type(l) is list and len(l) in [6, 7] | |
x = 0 | |
for n in range(len(l)): | |
if l[n] == 1: | |
x = x + (2**n) | |
return x | |
# 找出 list 裡符合某個內容的元素的 index + 1 | |
# 是用來找 本卦 vs 之卦 改變的是哪幾爻 | |
# find_index([0, 1, 0, 1, 0, 0], 1) => [2, 4] | |
# find_index([0, 1, 0, 1, 0, 0], 0) => [1, 3, 5, 6] | |
def find_index(l, v): | |
return [(n + 1) for n in range(len(l)) if (l[n] == v)] | |
# 一個卦有卦辭,加上六個爻辭,可以用 kua * 7 + yo 來找到卦辭與爻辭。 | |
# 用九與用六,放在最後,位址在 64*7+0=448 與 64*7+1=449 | |
# yo = 0,傳回卦辭 | |
# yo = 1..6,傳回爻辭 | |
def lookup_yi(kua, yo): | |
assert type(kua) is list and type(yo) is int | |
assert (len(kua) == 6 and yo in [0, 1, 2, 3, 4, 5, 6]) or ( | |
len(kua) == 7 and yo in [0, 1] | |
) | |
n = binary_to_int(kua) | |
assert n * 7 + yo < 450 | |
if False: | |
return yi[n * 7 + yo] | |
else: | |
# 測試用,忽略卦辭爻辭的內容 | |
nn = ["", "一", "二", "三", "四", "五", "六"] | |
final_result = n * 7 + yo | |
if final_result == 448: | |
return "用九" | |
elif final_result == 449: | |
return "用六" | |
else: | |
if yo == 0: | |
return yi[yi_order.index(n)] + "卦" | |
else: | |
return yi[yi_order.index(n)] + "卦第" + nn[yo] + "爻" | |
# 輸入揲蓍法所得的六個數,得到對應的卦辭或爻辭 | |
def post_pu_kua(kua): | |
assert type(kua) == list and len(kua) == 6 | |
# 將老陰 (6) 少陽 (7) 少陰 (8) 老陽 (9) 對應到陰爻與陽爻,得到本卦 | |
aa = [0 if x in (6, 8) else 1 for x in kua] # 本卦 | |
# 因為變卦的邏輯是 遇六 變 陽,遇九 變 陰,所以在之卦中 數字 6, 7 是陽爻,8, 9 是陰爻 | |
bb = [1 if x in (6, 7) else 0 for x in kua] # 變卦 | |
# 找出本卦之卦兩者不同的爻,1 代表爻陰陽不同,0 代表相同, | |
# sum(cc) 算出有幾個變爻 | |
# find_index(cc, 1) 找出變爻的位置 | |
# find_index(cc, 0) 找出不變爻的位置 | |
cc = [1 if aa[n] != bb[n] else 0 for n in range(6)] | |
if sum(cc) == 0: # 零個變爻 | |
return (lookup_yi(aa, 0),) # 本卦的卦辭 | |
elif sum(cc) == 1: # 一個變爻 | |
pos = find_index(cc, 1) | |
return (lookup_yi(aa, pos[0]),) # 本卦變爻的爻辭 | |
elif sum(cc) == 2: # 兩個變爻 | |
pos = find_index(cc, 1) | |
return (lookup_yi(aa, pos[1]), lookup_yi(aa, pos[0])) # 以本卦的兩個變爻解卦,上爻為主 | |
elif sum(cc) == 3: # 三個變爻 | |
return (lookup_yi(bb, 0), lookup_yi(aa, 0)) # 以兩卦卦義解卦,變卦為主 | |
elif sum(cc) == 4: # 四個變爻 | |
pos = find_index(cc, 0) | |
return (lookup_yi(bb, pos[0]), lookup_yi(bb, pos[1])) # 以變卦未變的兩爻解卦,下爻為主 | |
elif sum(cc) == 5: # 五個變爻 | |
pos = find_index(cc, 0) | |
return (lookup_yi(bb, pos[0]),) # 變卦未變的爻辭 | |
elif sum(cc) == 6: # 六個變爻 | |
if aa == [1, 1, 1, 1, 1, 1]: | |
return (lookup_yi([0, 0, 0, 0, 0, 0, 1], 0),) # 用九 | |
elif aa == [0, 0, 0, 0, 0, 0]: | |
return (lookup_yi([0, 0, 0, 0, 0, 0, 1], 1),) # 用六 | |
else: | |
return (lookup_yi(bb, 0),) # 變卦卦辭 | |
else: | |
raise | |
# 「四營」(「分二、掛一、揲四、歸奇」) | |
# 跑出來的結果,6 非常少,不確定是否正常 | |
def yin(n): | |
# 分而為二以象兩:隨機將這 n 個分為兩堆,亂數從 2 開始,是為了接著掛一以象三的步驟,不至於把左邊或右邊一堆拿光 | |
s = random.randint(2, n - 2) | |
# s = np.random.binomial(n - 2, 0.5) + 1 | |
left = n - s | |
right = s | |
# 掛一以象三:再從其中任何一堆隨機取出一個 | |
l_r = random.randint(0, 1) | |
if l_r == 0: | |
left = left - 1 | |
else: | |
right = right - 1 | |
# 揲之以四以象四時:現在兩堆分別以四個四個計算,從右手邊開始,剩下的竹籤(餘數=1至4)夾於無名指和中指間,以象徵閏;再算左手邊的竹籤,剩餘的夾在中指和食指間。 | |
if right % 4: | |
right = right - right % 4 | |
else: | |
right = right - 4 | |
if left % 4: | |
left = left - left % 4 | |
else: | |
left = left - 4 | |
return left + right | |
# 三變成一爻 | |
def make_yo(): | |
n = yin(yin(yin(49))) | |
return n // 4 | |
if __name__ == "__main__": | |
kua = [random.randint(6, 9) for n in range(6)] | |
# kua = [make_yo() for n in range(6)] | |
print(kua) | |
print(post_pu_kua(kua)) |
靠,這頭腦怎麼長的,居然能想到這麼精妙的法子...
還好吧,二進位數與十進位數互相轉換是程式入門題目。
術業有專攻,您會的我也不會啊。
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
簡言之,是輸入卦象的零與一的陣列,計算它代表的二進位數字,
乾卦是六個一,換算是 63,艮卦是 [0, 0, 1, 0, 0, 1] 換算是 36。
TL;DR;
l (L 小寫) 是一個卦的六爻,以 0 代表陰爻,1 代表陽爻,由下向上,乾卦就是 [1, 1, 1, 1, 1, 1],艮卦就是 [0, 0, 1, 0, 0, 1]。
然後要把這個 list 轉換成數字,list 中的每個 0 或 1 代表一個二進位位元,l[0] 是整數數字第一個位元,l[1] 是整數數字第二個位元,l[2] 是整數數字第三個位元,以此類推。
六個位元各自代表是 [1, 2, 4, 8, 16, 32]
十進位數字轉換成二進位,
**
的符號是次方的意思,要注意一般此時第一個位元在最右邊,跟印出 list 的順序相反這個函式就是 loop 把 list l 裡內容是 1 的位元,算出
2**n
,再加總起來,得到它的十進位數字。