在运势计算中运用BST树

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
简介: 【5月更文挑战第3天】该文介绍了使用树进行简单的运势推算。通过`TaoBstManager`结构体管理运算,包括树的结构、变化节点和爻卦含义。提供了遍历、显示节点的功能以及执行“一变”和“一爻三变”的方法。最终,通过`YaoWithReBuild`生成六爻并形成一卦。代码实现可在给定的GitHub链接中查看。

1 在本小节,我们将使用树做运势推算

从古至今,关于运势和未来的计算都是王公贵族的爱好,我们可以从零开始, 以双向链表实现 运势计算(周易)。

1.0 需要获得每天的运势吗?

本文实现算法 这里做一个简单的汇总,如果有需要参考原文的请自行搜索。

占卜算卦是一个古老的方法,人们无把握又希望应对未来时,经常通过这个方法获得一些确定性的心理效应。

其社会影响深远而广泛,虽然它并不是一种完全准确的科学,但我们可以通过go实现 一个简易的占卜程序,用以了解我们的古人如何处理不确定性的。 并尝试了解其中的变化规则。

1.1 计算步骤初探

  • 1, 产生49个数,为大衍之数为 54,实际参与计算的为 七七四十九

  • 2, 随机 分成 两组(随机的方法非常重要,可以影响甚至决定结果),
    为了可以产生正常的 三变 运算,最小12
    也就是说范围是:天 12 ~ 37, 地 37 ~ 12

  • 3, 从 天,地 随机选择一侧 取出一个 作为 人(一般在实际操作时,可以让寻求运势的人操作,以加强参与感)

  • 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, 解卦象

如果不清楚计算步骤,请查看上文。

question_ans.png

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

目录
相关文章
|
6月前
|
NoSQL 容器 消息中间件
树的直径、最近公共祖先、树的变形
树的直径、最近公共祖先、树的变形
|
5月前
|
算法
数据结构和算法学习记录——层序遍历(层次遍历)、二叉树遍历的应用(输出二叉树中的叶节点、求二叉树的高度、二元运算表达式树及其遍历、由两种遍历序列确定二叉树)
数据结构和算法学习记录——层序遍历(层次遍历)、二叉树遍历的应用(输出二叉树中的叶节点、求二叉树的高度、二元运算表达式树及其遍历、由两种遍历序列确定二叉树)
48 0
|
6月前
|
存储 机器学习/深度学习 人工智能
树和森林 查找
树和森林 查找
36 2
|
6月前
|
人工智能 算法 BI
【图论】【树】 【拓扑排序】2603. 收集树中金币
【图论】【树】 【拓扑排序】2603. 收集树中金币
|
6月前
|
人工智能 算法 BI
【深度优先搜索】【树】【图论】2973. 树中每个节点放置的金币数目
【深度优先搜索】【树】【图论】2973. 树中每个节点放置的金币数目
520礼物(利用权重数组建赫夫曼树)
520礼物(利用权重数组建赫夫曼树)
Leedcode二叉搜索树中的搜索[层序遍历+利用性质]
Leedcode二叉搜索树中的搜索[层序遍历+利用性质]
85 0
Leedcode二叉搜索树中的搜索[层序遍历+利用性质]
每日三题-验证二叉搜索树、二叉树的直径、把二叉搜索树转换为累加树
每日三题-验证二叉搜索树、二叉树的直径、把二叉搜索树转换为累加树验证二叉搜索树验证二叉搜索树v
62 2
每日三题-验证二叉搜索树、二叉树的直径、把二叉搜索树转换为累加树
Day23——修剪二叉搜索树、将有序数组转化为二叉搜索树、把二叉搜索树转化为累加树
Day23——修剪二叉搜索树、将有序数组转化为二叉搜索树、把二叉搜索树转化为累加树
88 0
L2-011 玩转二叉树 (25 分)(树)
L2-011 玩转二叉树 (25 分)(树)
133 0