首页 > 其他分享 >运势计算:以双向链表实现: 计算爻卦

运势计算:以双向链表实现: 计算爻卦

时间:2023-07-24 14:04:54浏览次数:38  
标签:tian di int 运势 链表 sn lis dt 爻卦

1.0 准备开始

我们先制定一个计算结构体,一切开始于此。

我们首先需要知道参与计算的 算子有多少,我们就按最常用的数49来制定。

type DataTao struct {
        DefMean    map[int]string // 卦象坐标名称
        DefValue   map[int]string // 卦象坐标值 4个
        GuaData    []int          // 卦象的 6爻初始值
        Indent     int            // 格式化输出间隔
        Env        int            // 影响偏差,Env 把一年分为 3个部分,每个部分4个月,这个值可以影响天地分开的比例,自己随意
        Total      int            // 大衍之数 个数
        PrintLevel int            // 计算过程显示控制,如果为 1 则显示
        Coordinate map[int]string //卦象坐标的 爻,古称
    }

制作该计算对象的构造函数

/*
      @param env 环境参数
      @param indent 格式化输出的缩进
      @param total 天地 大衍数 49
      */
      func MakeNewDataTao(env string, indent, total int) *DataTao {
          envNum := map[string]int{"A": 1, "B": 0, "C": 2}
          guaCoor := map[int]string{6: "六", 7: "七", 8: "八", 9: "九"}

        var envLevel = 0

        if indent <= 0 {
            indent = 8
        }

        if env != "" {
            envLevel = envNum[env]
        }

        if total < 49 {
            total = 49
        }

        newData := &DataTao{
            DefMean:    defMean,
            DefValue:   guaCoor,
            GuaData:    []int{},
            Indent:     indent,
            Env:        envLevel,
            Total:      total,
            PrintLevel: envNum["A"],
            Coordinate: Coordinates,
        }
        return newData
    }

1.1 开天辟地,创建爻变

创建天地大衍之数,创建一个新的天地列表 大衍之数,使用49

func (dt *DataTao) NewCircle() []int {
    var newCir []int
    for i := 0; i < dt.Total; i++ {
        newCir = append(newCir, i)
    }
    return newCir
}

由于每一变 除以4的余数可能为 0,此时需要拿走4个算子,所以,3变最多需要12个算子,而分天地,


运势计算:以双向链表实现: 计算爻卦_格式化输出


默认随机算法 计算后 将其值 限定为下限 12,上限 37,为什么要如此限定,就在于变爻的初始算子数量。

func (dt *DataTao) SplitNum(topNum int) int {
    /*
        Seed 使用提供的种子值将生成器初始化为确定性状态。
        Seed 不应与任何其他 Rand 方法同时调用。
    */
    rand.Seed(time.Now().UnixNano())
    top := topNum - 4
    sn := rand.Intn(top) + 4 // A random int in [4, 45]

    if dt.Env != 0 {
        if dt.Env == 1 {
            sn = sn + (dt.Env * 3)
        } else {
            sn = sn + (dt.Env * 2)
        }

    }
    if sn < 4 {
        sn = 4
    }

    if sn > topNum - 4 {
        sn = topNum - 4
    }

    logger.Printf("outcome sn:%v with topNum:%v\n", sn, topNum)
    return sn
}

1.1.1 创建爻变,得天地人三才

从天,地随机选择一方,拿出一个算子 作为天地人的 人才 // 分三才 从选定的一方 得一人

func (dt *DataTao) RandLis(lis []int) ([]int, int) {

    rand.Seed(time.Now().UnixNano())
    if len(lis) < 2 {
        return lis, 0
    }
    t := rand.Intn(len(lis) - 1)
    ren := lis[t]
    lis = append(lis[:t], lis[t+1:]...)
    return lis, ren

}

推算的主要过程就是爻变的操作,每一爻都需要有3次爻变,最后得出一爻,我们先实现一变 //做一变

/*
@param: lis, 天地混沌,需要分开的算子集合
@param: sn, 从算子集合的哪一个位置执行分开
// 做一变,为得一爻
*/
func (dt *DataTao) DoOneYao(lis []int, sn int) []int {

    //分天地
    tian := lis[:sn]
    di := lis[sn:]

    var ran int
    //从天地 取一人
    rand.Seed(time.Now().UnixNano())
    r := rand.Intn(2)
    if r == 0 {
        tian, ran = dt.RandLis(tian)
    } else {
        di, ran = dt.RandLis(di)
    }

    //一变
    var tia, d, newOrigin []int
    xt := len(tian) % 4
    if xt == 0 {
        //取 4个
        tia = tian[:4]
        tian = tian[4:]
    } else {
        tia = tian[:xt]
        tian = tian[xt:]
    }

    dtv := len(di) % 4
    if dtv == 0 {
        d = di[:4]
        di = di[4:]
    } else {
        d = di[:dtv]
        di = di[dtv:]
    }

    //返回一变
    newOrigin = append(tia, d...)
    newOrigin = append(newOrigin, ran)

    if dt.Env == dt.PrintLevel {
        SixYao = append(SixYao, newOrigin)
        logger.Println("余天:", tian, "\n余地:", di, "\n变数:", newOrigin, "人才:", ran, "\n新天地:", len(tian)+len(di))
        logger.Println("已变总数:", len(SixYao))
    }
    newDT := append(tian, di...)
    return newDT
}

每一个爻都需要对 天地大衍之数做三变,最后剩下的算子数 除以4 就是 一爻,算6次爻 那么就是一卦。 // 连续三变 得一爻,返回新天地

func (dt *DataTao) TianDiYao(lis []int) ([]int, int) {
    /*
            分天地 进行 变一
                :param lis:
                :param sn:
                :return:  最后的 天,地,归档人列表, 和 爻 值
    */
    finalTiandi := lis
    for _, k := range []int{1, 2, 3} {
        if dt.Env == dt.PrintLevel {
            logger.Println("第", k, "变")
        }
        finalTiandi = dt.DoOneYao(finalTiandi, dt.SplitNum(len(finalTiandi)))
    }

    yao := len(finalTiandi) / 4
    if dt.Total > 49 {
        db := dt.Total / 49
        yao := yao / db
        if dt.Env == dt.PrintLevel {
            logger.Println("大衍之数:", dt.Total, "三变后的爻:", yao, "距离 倍数 db:", db, "新天地:", len(finalTiandi))
        }

    }
    if dt.Env == dt.PrintLevel {
        logger.Println("三变后的爻:", yao)
    }
    return finalTiandi, yao
}

1.1.2 创建爻变, 得到6爻 即一卦

计算6个爻 则需要 3变 6次,并使用上一节的双向链表保存结果。 // 推演函数,开天辟地,并计算6爻

func (dt *DataTao) SuanGua() *dlist {
    // gua := []int{}
    logger.Printf("开始占卜运势...")
    for i := 1; i < 7; i++ {
        nc := dt.NewCircle()
        if dt.Env == dt.PrintLevel {
            logger.Println(len(nc), nc, dt.SplitNum(len(nc)))
        }
        ///分天地人
        ft, y := dt.TianDi(nc)
        if dt.Env == dt.PrintLevel {
            logger.Println("新天地:", ft)
            logger.Println(dt.Coordinate[i]+dt.DefValue[y], "\n第", i, "爻", y, dt.DefMean[y])
        }
        time.Sleep(time.Millisecond * 100)
        // gua = append(gua, y)
        ResultNodes.append(&node{number: y})
    }
    return ResultNodes
}

小结

本小节 我们实现了推演运势的过程,在下一小节,我们将实现对链表的数据读取 和 爻象的解读,然后以直观的方式给用户展示。

标签:tian,di,int,运势,链表,sn,lis,dt,爻卦
From: https://blog.51cto.com/u_16190327/6834523

相关文章

  • 代码随想录-链表-C++总结
    代码随想录(programmercarl.com)这次复习的主要目的还是熟练c++的基本语法知识,顺带过一下链表的典型题目印象深刻直接没做出来的有7.链表相交,没有想到先过一遍求出两条链表的长度,然后通过长度差的信息来get交点做的时候写出bug的有3.设计链表,涉及的基础思想还是比较多的,需......
  • 单链表的实现
    #include<stdio.h>#include<stdlib.h>//创建一个单链表structLNode//结点{intdata;//数据structLNode*next;//指向下个结点的指针};voidList_Print(structLNode*p)//自定义列表打印函数{while(p){......
  • 双向链表的实现
    //带头节点的双链表#include<stdio.h>#include<stdlib.h>typedefstructDNode{intdata;structDNode*prior;structDNode*next;}DNode;//初始化头结点DNode*Init_DLinkList(){DNode*L;L=(DNode*)malloc(sizeof(DNode));L->......
  • 剑指 Offer 35. 复杂链表的复制
    题目:/*//DefinitionforaNode.classNode{public:intval;Node*next;Node*random;Node(int_val){val=_val;next=NULL;random=NULL;}};*/classSolution{public:Node*copyRandomList(N......
  • go 循环链表
    packagemainimport("fmt")typeNodestruct{DataintNext*Node}typeCircularLinkedListstruct{Head*NodeTail*Node}funcNewCircularLinkedList()*CircularLinkedList{return&CircularLinkedList{}}func(l......
  • HJ48 从单向链表中删除指定值的节点
    1.题目读题 HJ48 从单向链表中删除指定值的节点 考查点 这道题的考查点是单向链表的删除操作,主要是考察你能否掌握以下几个方面:如何遍历链表,找到要删除的节点或其前驱节点。如何修改节点的指针域,使其跳过要删除的节点。如何释放要删除的节点的内存空间,防止内存泄......
  • 剑指 Offer 18. 删除链表的节点
    题目:(有改动和陷阱,不可以使用delete否则报错!!)classSolution{public:ListNode*deleteNode(ListNode*head,intval){ListNode*fhead=newListNode(0);#设置虚拟头节点fhead->next=head;ListNode*cur=fhead;while(cur-......
  • 剑指 Offer 24. 反转链表
    题目:/***Definitionforsingly-linkedlist.*structListNode{*intval;*ListNode*next;*ListNode(intx):val(x),next(NULL){}*};*/classSolution{public:ListNode*reverseList(ListNode*head){ListNode*temp......
  • 剑指 Offer 06. 从尾到头打印链表
    题目:/***Definitionforsingly-linkedlist.*structListNode{*intval;*ListNode*next;*ListNode(intx):val(x),next(NULL){}*};*/classSolution{public:vector<int>reversePrint(ListNode*head){vecto......
  • 上班摸鱼刷算法-Java-hot100-[160]相交链表
    publicclassSolution{publicListNodegetIntersectionNode(ListNodeheadA,ListNodeheadB){if(headA==null||headB==null){returnnull;}ListNodepA=headA;ListNodepB=headB;while(pA......