Skip to content

Instantly share code, notes, and snippets.

@brchiu
Last active March 10, 2022 16:01
Show Gist options
  • Save brchiu/0ec5f35282944af06ec07e9e1c4ee4f4 to your computer and use it in GitHub Desktop.
Save brchiu/0ec5f35282944af06ec07e9e1c4ee4f4 to your computer and use it in GitHub Desktop.
大衍之數揲卦法的後半段
#!/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))
@brchiu
Copy link
Author

brchiu commented Mar 10, 2022

還好吧,二進位數與十進位數互相轉換是程式入門題目。

術業有專攻,您會的我也不會啊。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment