新年彩蛋之中大奖

news/2024/7/2 23:36:07
2019年计划通过福利彩票发家致富的,可以好好看一看这篇博客。作为新年彩蛋来送给大家,也希望大家能真的中大奖。

—— 新年快乐,给每个有梦想的程序员

生成随机号

小概率事件也要做的一丝不苟,大家都是程序员,为啥要用别人家写的随机代码。嘎嘎!

双色球蓝号1-12、红号1-33,非常简单,只需保证生成的红号不相互重复就可以,然后就是考虑如何做到真正的随机

还有一个问题就是如何存储一组号码。首先,分成红区和蓝区两部分,最后一个号约定为蓝号。另外,为了方便存储,我们放弃了将每个数字用符号连接的方式,而是自定义了34进制,用于保证每组号码的长度都是7。

var redBall = map[int]rune{1:  '1',2:  '2',3:  '3',//......31: 'V',32: 'W',33: 'X',
}
var redFlip = map[rune]int{'1': 1,'2': 2,'3': 3,//...'V': 31,'W': 32,'X': 33,
}

我们提供一个编解码的方法,用于将字符串转换为一组号码。对应的,将一组号码转换为长度为7的字符串。

随机红号范围控制在1-33,蓝号控制在1-16。所以,我们对当前纳秒进行取余,便可以保证数据的正确。对于去重部分,通过map属性来达到目的,mapkey存储生成的随机号,value存储对应的编码。因为map结构读取数据时本身也是随机的,所以在生成红号和蓝号的时候便多生成一部分,最后再取6个红号,1个蓝号。

type TwoColor struct {
}//encode
func (color *TwoColor) Encode(origin []int) string {runes := make([]rune, 0)for _, v := range origin {if elem, ok := redBall[v]; ok {runes = append(runes, elem)}return string(runes)
}//decode
func (color *TwoColor) Decode(origin string) []int {result := make([]int, 0)for _, v := range origin {if elem, ok := redFlip[v]; ok {result = append(result, elem)}}return result
}//generate random numbers
func (color *TwoColor) GenerateRandom() string {redResult := make(map[int]rune, 12)for len(redResult) < 12 {key := time.Now().Nanosecond()%33 + 1redResult[key] = redBall[key]}blueBall := make(map[int]rune, 2)for len(blueBall) < 2 {key := time.Now().Nanosecond()%16 + 1blueBall[key] = redBall[key]}index := 0result := make([]rune, 7)for _, v := range redBall {index++result = append(result, v)if index == 6 {break}}for _, v := range blueBall {result = append(result, v)break}return string(result)
}

批量生成随机数

批量生成不重复的随机数,核心就是解决如何存储的问题。每次都得跟之前生成的记录做比较,保证当前生成的记录是不重复的。

之所以有批量生成的需求,首先是为了使生成的记录更随机。其次,试想一下,如果你内存足够大,生成5000W条记录,官方开奖后,看看这5000W会不会中一注。如果这么多都没有中,那真是一件令人伤心的事情啊。

为了简单方便,我们直接将生成的记录存储到本地内存中,这里使用前面讲到的bigcache。我们将生成的记录作为KeyValue不存储实际的值了。

对于ZSet,我们这里只想体现它的唯一属性。只有当记录不存在时才进行存储。

type DBCenter struct {
}func (db *DBCenter) ZSet(key string) {if db.Exists(key) {return}cache.Set(key, nil)
}func (db *DBCenter) Exists(key string) bool {_, err := cache.Get(key)if err != nil {if _, ok := err.(*bigcache.EntryNotFoundError); ok {return false}}return true
}func (db *DBCenter) Len() int {return cache.Len()
}

批量生成的过程就是一个for循环的过程,并通过Len方法获取当前生成的记录数。

存储开奖号码

将每期的开奖号码作为下一期的参考,是每个迷信中彩人的执着。

我们选择将每期的中奖号码存储到文件中,实在没有必要使用关系型数据库。在使用过程中,我们不会部署到多台服务器上。这个项目就是在个人电脑上运行设计的,单文件存储足够了。

关于write方法,写入的内容包括日期和中奖号码,连接符使用了SeparatorData。在打开文件的模式中,我们指定了O_APPEND,将写入追加到文件末尾。这也导致最新的开奖号码出现在文件的末尾。当读取最近几期的开奖号码时,需要定位开始读取的位置。

const (FilePath      = "/Users/neojos/src/boredom/data/history.txt"SeparatorData = "\t"
)type FileData struct {
}func (f *FileData) GetLatestHistory(limit int64) ([]string, error) {file, err := os.OpenFile(FilePath, os.O_CREATE|os.O_RDONLY, 0755)if err != nil {return nil, err}defer file.Close()info, err := file.Stat()if err != nil {return nil, err}rowLength := 0scan := bufio.NewScanner(file)for scan.Scan() {rowLength = len(scan.Text()) + 1 //'\n'break}if err = scan.Err(); err != nil {return nil, err}result := make([]string, 0)file.Seek((info.Size()/int64(rowLength)-limit)*int64(rowLength), 0)scan = bufio.NewScanner(file)for scan.Scan() {tmp := strings.Split(scan.Text(), SeparatorData)result = append(result, tmp[len(tmp)-1])}if err = scan.Err(); err != nil {return result, err}reverseResult := make([]string, limit)for i, v := range result {reverseResult[int(limit)-i-1] = v}return reverseResult, nil
}func (f *FileData) Write(date, number string) error {file, err := os.OpenFile(FilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0755)if err != nil {return err}defer file.Close()line := fmt.Sprintf("%s\t%s\n", date, number)_, err = file.WriteString(line)return err
}

GetLatestHistory用于获取最近几期的开奖号码。因为每行写入的长度相同,所以通过计算,可以得出当前文件的行数,并将文件的offset定位到指定的位置,从具体的offset开始读取。另外,因为我们写入的模式是APPEND,所以将获取到的slice再做一次顺序反转,便得到最近几期的开奖记录了。

生成图

通过plot来绘制一些简易的图形。将最近的开奖号码作为数据源,来观察数据的走势。虽然确实没啥用处。

这段代码直接运行会panic,因为修改了plot中的部分代码。

type Curve struct {elements [][]int
}func (curve *Curve) SetElem(input [][]int) {curve.elements = input
}func (curve *Curve) GetBaseImg() error {pic, err := plot.New()if err != nil {return err}pic.X.Label.Text = "ball"pic.Y.Label.Text = "number"// Draw a grid behind the datapic.Add(plotter.NewGrid())customTick := commaTicks{CustomTicks: 7,}pic.X.Tick.Marker = customTickcustomTick.CustomTicks = 33pic.Y.Tick.Marker = customTickpicElem := make(map[string]plotter.XYer)for index, element := range curve.elements {points := plotter.XYs{}for k, v := range element {points = append(points, plotter.XY{X: float64(k + 1), Y: float64(v)})}picElem[fmt.Sprintf("%d", index)] = points}plotutil.AddLinePoints(pic, picElem)return pic.Save(vgsvg.DefaultWidth, vgsvg.DefaultWidth, "base.png")
}

生成的图片如下:

pic

总结

项目的代码在boredom,代码非常简单。祝大家早日中大奖!


http://lihuaxi.xjx100.cn/news/268498.html

相关文章

QQ2012 Under Ubuntu

下载地址&#xff1a; QQ2012 Under Ubuntu转载于:https://www.cnblogs.com/ismdeep/archive/2012/08/09/2630067.html

exec

Linux中—exec族函数解析 exec族函数

android基础ui控件,Android基础——基础UI控件

日历&#xff0c;时钟&#xff0c;计时器package com.example.mybaseuii;import androidx.appcompat.app.AppCompatActivity;import android.app.Activity;import android.os.Bundle;import android.os.SystemClock;import android.widget.Chronometer;import android.widget.D…

如何提高模型性能?这四大方法值得尝试 | CSDN 博文精选

作者 | BoCong-Deng编辑 | 屠敏封图 | 自东方 IC出品 | CSDN 博客写在前面在我们进行模型训练时&#xff0c;如果你只是想要让模型具有不错的性能&#xff0c;那么盲目地尝试网络架构足以达到目的。而在本文中&#xff0c; 我们将为你提供一套用于构建最先进深度学习模型的必备…

收藏 | 机器学习防止模型过拟合

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶”重磅干货&#xff0c;第一时间送达目录LP范数L1范数L2范数L1范数和L2范数的区别DropoutBatch Normalization归一化、标准化 & 正则化Reference其实正则化的本质很简单&#xff0c;就是对某一问题加以先…

python模块之imghdr检测图片类型

python模块之imghdr检测图片类型 1. imghdr是什么 imghdr是一个用来检测图片类型的模块&#xff0c;传递给它的可以是一个文件对象&#xff0c;也可以是一个字节流。【仅仅根据文件后缀判断文件类型显然不准&#xff0c;在python有一个内置模块imghdr可以用来判断图片的真实类…

树莓派:人在太空,刚下火箭,诚招小于19岁的代码开发者

点击上方“视学算法”&#xff0c;选择加"星标"或“置顶”重磅干货&#xff0c;第一时间送达博雯 发自 凹非寺 量子位 报道 | 公众号 QbitAI这是一位正在国际空间站执行任务的宇航员。再拉近一点&#xff0c;猜得出他身边这个一直在亮的小东西是什么吗&#xff1f;—…

leetcode002 add_two_numbers

""" 给出两个 非空 的链表用来表示两个非负的整数。其中&#xff0c;它们各自的位数是按照 逆序 的方式存储的&#xff0c;并且它们的每个节点只能存储 一位 数字。如果&#xff0c;我们将这两个数相加起来&#xff0c;则会返回一个新的链表来表示它们的和。您可…