1 在本小节,我们将使用树做运势推算
从古至今,关于运势和未来的计算都是王公贵族的爱好,我们可以从零开始, 以双向链表实现 运势计算(周易)。
1.0 需要获得每天的运势吗?
本文实现算法 这里做一个简单的汇总,如果有需要参考原文的请自行搜索。
占卜算卦是一个古老的方法,人们无把握又希望应对未来时,经常通过这个方法获得一些确定性的心理效应。
其社会影响深远而广泛,虽然它并不是一种完全准确的科学,但我们可以通过go实现 一个简易的占卜程序,用以了解我们的古人如何处理不确定性的。 并尝试了解其中的变化规则。
1.1 计算步骤初探
1, 产生49个数,为大衍之数为 54,实际参与计算的为 七七四十九
2, 随机 分成 两组(随机的方法非常重要,可以影响甚至决定结果),
为了可以产生正常的 三变 运算,最小12
也就是说范围是:天 12 ~ 37, 地 37 ~ 123, 从 天,地 随机选择一侧 取出一个 作为 人(一般在实际操作时,可以让寻求运势的人操作,以加强参与感)
4, 一变 把象征天的那组棋子数数有多少颗,数清楚之后把这个数字除以4(4象征一年四季),余数是几。
任何数字除以4,余数都只有四种可能:1、2、3、整除。如果遇到整除的情况,我们就当做余数是4。好了,现在把余数拿开。
把象征地的那组棋子照猫画虎,和“3”的做法一致。
把“2”里用来象征人的那一颗棋子,加上“3”中作为余数被拿掉的棋子,还有“4”里同样作为余数被拿掉的棋子归在一起。
得出的数字只有两种可能:不是9就是5。如果错了,你就从头再来吧。 好了,从1-5完成动作,叫做“一变”。
5, 二变,重复 2~4 步
6, 三变,重复 2~4 步,最后剩下的卡 除以 4 得出 第一爻
7, 重复 1~6 步,6次,产生 6个爻 即为 一卦
8, 解卦象
如果不清楚计算步骤,请查看上文。
2 使用go实现运势计算的管理
好了,现在我们知道如何计算,但是怎样管理这些计算呢?
这就需要 运势推算管理器,以此我们可以用来知晓树的结构,哪些节点经过了变化,爻卦中的含义也可以放入其中,方便运势计算时获取。
type TaoBstManager struct {
*BinarySearchTree
Bains []int //有哪些变化
Indent int //格式化显示
DefMean map[int]string //解释方式
Coordinates map[int]string
}
func MakeNewTreeManager() *TaoBstManager {
return &TaoBstManager{
BinarySearchTree: &BinarySearchTree{},
Indent: 8,
DefMean: defMean,
Coordinates: Coordinates,
}
}
func (bsts *TaoBstManager) Trees() *BinarySearchTree {
return bsts.BinarySearchTree
}
// 遍历树所有节点 到channel
func (bsts *TaoBstManager) IterListNodes() *dlist {
ccHan := bsts.IterCache()
return IterNodes(ccHan)
}
// 显示所有节点
func (bsts *TaoBstManager) Display() {
n := 0
cChans := bsts.IterCache()
for i := 0; i < cChans.Size; i++ { //, m := cMaps.Size {
Tnode := cChans.GetNode() // bsts.CacheGets(cChans)
n += 1
if Tnode == nil {
continue
}
}
}
我们知道一爻需要 女大18变,因此需要方法做一变
// 做一变
func (newTree *TaoBstManager) DoOneBian() (*TaoBstManager, int) {
//一变
lys := newTree.LeftSize % 4
if lys == 0 {
lys = 4
}
ldelRst, leftNodeDel := newTree.YaoDel(0, lys) //当左侧长度 除以4的 余数为3时,从左侧删除3个节点
rys := newTree.RightSize % 4
if rys == 0 {
rys = 4
}
rdelRst, rightNodeDel := newTree.YaoDel(1, rys+1) //从右节点多删除一个,当作人材的归档,当左侧长度 除以4的 余数为3时,从左侧删除3个节点
return newTree, len(leftNodeDel) + len(rightNodeDel)
}
然后我们需要以此做一爻
// 为一爻做一变
func (newManager *TaoBstManager) DoOneBianForYao(env string) *TaoBstManager {
// 计算随机数,必须在大于4 ~ Max-4 范围内,否则一变失败
tm, _ := newManager.DoOneBian()
newTree := tm.Trees()
mi := newTree.Root.FindMin() //最小
mx := newTree.Root.FindMax() //最大
//st := newTree.Size //总数
//新的根节点 和以此生成的新的树 作为二变基础
two := DoRange(mi.Key, mx.Key, env)
keyNodesTwo := newTree.Searcher(two)
Logg.Printf("new tree mi:%v mx:%v root:%v node:%v\n", mi, mx, two, keyNodesTwo)
newTreeTwo := newTree.Rebuild(keyNodesTwo)
nms := &TaoBstManager{BinarySearchTree: newTreeTwo}
return nms
}
// 做一爻 三变
func (newManager *TaoBstManager) DoOneYao(env string) int {
// 计算随机数,必须在大于4 ~ Max-4 范围内,否则一变失败
newMan := newManager.DoOneBianForYao(env)
newTwoMan := newMan.DoOneBianForYao(env)
newThreeMan := newTwoMan.DoOneBianForYao(env)
return newThreeMan.Size / 4
}
以此,我们创建了一爻, 连续6次得到一卦
// 初始化树管理器 并创建六爻
func (bstNew *TaoBstManager) YaoWithReBuild(t int, env string) ([]int, *TaoBstManager) {
if t <= 0 {
t = 49
}
for i := 0; i < t; i++ {
bstNew.Puts(i, fmt.Sprintf("suanzi_%v", i))
Logg.Printf("bstNew :%v, root:%v len:%v\n \n", bstNew, bstNew.Root, bstNew.Size)
}
var yaoOnes []int
//得一卦象
for len(yaoOnes) < 6 {
// 以人为本 分天地人 查找某个节点 并以此旋转 再平衡
rootKey := DoRand(t)
keyNodes := bstNew.Searcher(rootKey)
newTree := bstNew.Rebuild(keyNodes)
caches := newTree.IterCache()
if bstNew.Size != newTree.Size {
msg := fmt.Sprintf("size error with new tree:%v\n", newTree.Size)
panic(msg)
}
treeManager := &TaoBstManager{BinarySearchTree: newTree}
yaoOne := treeManager.DoOneYao(env)
yaoOnes = append(yaoOnes, yaoOne)
}
return yaoOnes, bstNew
}
// # 6爻卦象 显示原始卦象, 返回卦值 和 第几卦
func (dt *TaoBstManager) KanGuaOrigin(env string) ([]int, int) {
fmt.Printf("%v", start)
guas, bstm := dt.YaoWithReBuild(49, env)
fmt.Println("卦象已出:")
yaos, postionChanges := dt.AnysisYaos(guas)
fmt.Printf("yaos: postionChanges:, %v, %v, bstree:%v\n", yaos, postionChanges, bstm.Size)
anysis, numb := ICApp.CommonText(yaos)
fmt.Printf("第%v 卦, \n %v", numb, anysis)
return yaos, numb
}
3 小结
好了,到现在为止,我们已经得到了一卦,是不是很简单?
我们5000年的 “核心计算科技” 被计算机很简单的解决了。
在下一小节,我们将根据计算的爻 组成卦象,并解释其中“深义”。
本文代码地址
https://github.com/TFrankly/amz_golang/tree/main/39_tao_ex/1.1_taomi