java 彩票走势图算法

一、算法介绍

本博文主要写了彩票走势图中的遗漏值、出现总次数、平均遗漏值、最大遗漏值、最大连出值的计算逻辑。

二、图文简介

[这是XX网双色球的彩票走势图,博主这里是将彩票数据分区展示,以双色球为例,分了五个区域,本博文中的遗漏值是按照期数的降序排列计算的如下图]

这里写图片描述

三、工具类简介(请仔细看完工具类简介)

彩票走势图的工具类**LotteryTrend**中将彩票的名称彩票的id,及其对应的数字域数据域id,每个区域的起始数字,每个区域的长度等数据按照顺序一一对应定义。另一个工具类**MissValue**就是彩票遗漏值的工具类,里面是具体的**彩票遗漏值、出现总次数、平均遗漏值、最大遗漏值、最大连出值**的计算方法,博主将开奖位置的遗漏值置为0,返给前端的。下面是这几个名词的定义:
**彩票遗漏值**:自上期开出到本期间隔的期数。
**出现总次数**:当前选定的彩票期数区间内该球的出现总次数。
**平均遗漏值**:平均遗漏值计算公式:总期数除以出现的总次数,如果总次数为0,该值为0;如果除不尽将计算结果向下取整。
**最大遗漏值**:历史开奖以来该球连续不出现的最大值,即为距离上次出现的间隔数的最大值。
**最大连出值**:**博主写的是选定期数内连续出现的最大值,与右图不符合**.

四、返回给前端的json数据

五、代码块

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;


/**
 * 彩票走势图工具类
 * @author Administrator
 *
 */
public class LotteryTrend {

    //所有彩票名称数组
    public static final String[] titleArray={"超级大乐透","七星彩","排列三","排列五","双色球","福彩3D","江西11选5","11运夺金","广东11选5","上海11选5","浙江11选5","七乐彩","重庆时时彩","胜负彩","安徽快三","湖北快三","吉林快三","江苏快三","江苏11选5","浙江12选5"};

    //彩票的id数组
    public static final String[] lotteryidArray={"19","18","2","13","16","1","9","8","10","24","27","17","3","71","32","33","34","35","28","22"};
    //每种彩票的区域或者数字域
    public static final String[][] headArray={{"红一区","红二区","红三区","后区"},{"第七位","第六位","第五位","第四位","第三位","第二位","第一位"},{"百位","十位","个位"},
            {"万位","千位","百位","十位","个位"},{"红一区","红二区","红三区","篮球"},{"百位","十位","个位"},
            {"万位","千位","百位","十位","个位"},{"万位","千位","百位","十位","个位"},{"万位","千位","百位","十位","个位"},
            {"万位","千位","百位","十位","个位"},{"万位","千位","百位","十位","个位"},{"一区","二区","三区"},
            {"万位","千位","百位","十位","个位"},{"3","1","0"},{"百位","十位","个位"},
            {"百位","十位","个位"},{"百位","十位","个位"},{"百位","十位","个位"},
            {"万位","千位","百位","十位","个位"},{"万位","千位","百位","十位","个位"}};

    //区域或者数字域的id
    public static final String[][] idxArray ={{"area1","area2","area3","back"},{"num_info7","num_info6","num_info5","num_info4","num_info3","num_info2","num_info1"},{"num_info3","num_info2","num_info1"},
            {"num_info5","num_info4","num_info3","num_info2","num_info1"},{"area1","area2","area3","num_info7"},{"num_info3","num_info2","num_info1"},
            {"num_info5","num_info4","num_info3","num_info2","num_info1"},{"num_info5","num_info4","num_info3","num_info2","num_info1"},{"num_info5",
            "num_info4","num_info3","num_info2","num_info1"},{"num_info5","num_info4","num_info3","num_info2","num_info1"},{"num_info5","num_info4","num_info3","num_info2","num_info1"},
            {"area1","area2","area3"},{"num_info5","num_info4","num_info3","num_info2","num_info1"},{"3","1","0"},{"num_info3","num_info2","num_info1"},
            {"num_info3","num_info2","num_info1"},{"num_info3","num_info2","num_info1"},{"num_info3","num_info2","num_info1"}, {"num_info5","num_info4","num_info3","num_info2","num_info1"},
            {"num_info5","num_info4","num_info3","num_info2","num_info1"}};

    //定义每个区域的起始数字
    public static final String[][] beginNum = {{"01","13","25","01"},{"0","0","0","0","0","0","0"},{"0","0","0"},
            {"0","0","0","0","0"},{"01","12","23","01"},{"0","0","0"},
            {"1","1","1","1","1"},{"1","1","1","1","1"},{"1","1","1","1","1"},{"1","1","1","1","1"},
            {"1","1","1","1","1"},{"01","11","21"},{"0","0","0","0","0"},{"1","1","1"},{"1","1","1"},
            {"1","1","1"},{"1","1","1"},{"1","1","1"}, {"1","1","1","1","1"},{"1","1","1","1","1"}};
    //定义每个区域的长度
    public static final int[][] horizontalSpans = {{12,12,11,12},{10,10,10,10,10,10,10},{10,10,10},
        {10,10,10,10,10},{11,11,11,16},{10,10,10},
        {11,11,11,11,11},{11,11,11,11,11},{11,11,11,11,11},{11,11,11,11,11},
        {11,11,11,11,11},{10,10,10},{10,10,10},{14,14,14},{6,6,6},
        {6,6,6},{6,6,6},{6,6,6}, {11,11,11,11,11},{12,12,12,12,12}};
    //是否需要两位,例如01或者1
    public static final String[] isHaveTwoPosition = {"1","0","0","0","1","0","0","0","0","0","0","1","0","0", "0","0","0","0","0","0"};

    //冷热
    public static final  String[][] codeAndHotIdxArray = {{"num_info1","num_info2","num_info3","num_info4","num_info5","num_info6","num_info7"},
            {"num_info1","num_info2","num_info3","num_info4","num_info5","num_info6","num_info7"},{"num_info1","num_info2","num_info3"},
            {"num_info3","num_info2","num_info1"},{"num_info1","num_info2","num_info3","num_info4","num_info5","num_info6","num_info7"},
            {"num_info3","num_info2","num_info1"},{"num_info1","num_info2","num_info3","num_info4","num_info5"},{"num_info1","num_info2","num_info3","num_info4","num_info5"},
            {"num_info1","num_info2","num_info3","num_info4","num_info5"},{"num_info1","num_info2","num_info3","num_info4","num_info5"},
            {"num_info1","num_info2","num_info3","num_info4","num_info5"},{"num_info1","num_info2","num_info3","num_info4","num_info5","num_info6","num_info7"},
            {"num_info3","num_info2","num_info1"},{},{"num_info1","num_info2","num_info3"},{"num_info1","num_info2","num_info3"},{"num_info1","num_info2","num_info3"},
            {"num_info1","num_info2","num_info3"},{"num_info1","num_info2","num_info3","num_info4","num_info5"},{"num_info1","num_info2","num_info3","num_info4","num_info5"}};

    //封装走势图所有的数据
    /**
    * list  数据库查询到的当前彩种开奖数据集合
    * issueCount  页面传来的指定的查看的总期数
    * totalIssue  当前开奖数据历史以来的总期数
    */
    public static   Map trendInfo(List> list, String lotteryid, String idx,Integer issueCount,Integer totalIssue){
        int m=0,n=0,horizontalSpan=0;//m代表当前彩种在彩票id数组的位置;n代表要展示的区域(如红一区,后区等)或者数字域(百位,十位,各位等);horizontalSpan水平方向的跨度
        Map map = new LinkedHashMap();//封装返回数据的集合,包括alldiffs,average_omission,infolist,max_omission,max_output,placenum,result

        //获取m
        for (int i = 0; i < lotteryidArray.length; i++) {
            if(lotteryidArray[i].equals(lotteryid)){
                m=i;
                break;
            }
        }
        //System.out.println("当前彩种在彩票id数组的位置:"+m);
        //获取n
        for (int i = 0; i < idxArray[m].length; i++) {
            if(idxArray[i].equals(idx)){
                n=i;
                break;
            }
        }
        //System.out.println("要展示走势的当前彩票的区域:"+n);

        //获取水平跨度
        horizontalSpan =horizontalSpans[m][n];

        //封装开奖数据
        List> infolist =new ArrayList<>();
        if(issueCount<=totalIssue){
            for (int j = 0; j < issueCount; j++) {
                //封装每一条开奖数据
                String[] sp = list.get(j).get("result").replaceFirst("\\+", ",").split(",");
                Map ma1  =  new LinkedHashMap();
                //封装期号
                ma1.put("id", list.get(j).get("id"));

                //封装id
                ma1.put("lottery_num", list.get(j).get("termNo"));
                //封装开奖号码
                for (int i = 0; i < codeAndHotIdxArray[m].length; i++) {
                    ma1.put(codeAndHotIdxArray[m][i], sp[i]);
                }
                infolist.add(ma1);
            }
        }else{
            for (int j = 0; j < totalIssue; j++) {
                //封装每一条开奖数据
                String[] sp = list.get(j).get("result").replaceFirst("\\+", ",").split(",");
                Map ma1  =  new LinkedHashMap();
                //封装期号
                ma1.put("id", list.get(j).get("id"));

                //封装id
                ma1.put("lottery_num", list.get(j).get("termNo"));
                //封装开奖号码
                for (int i = 0; i < codeAndHotIdxArray[m].length; i++) {
                    ma1.put(codeAndHotIdxArray[m][i], sp[i]);
                }
                infolist.add(ma1);
            }
        }
        map.put("infolist", infolist);
        //转换数据格式
        List> convertList = MissingValue.convertAwardData(list);

        //获得当前彩种的所有遗漏值数据
        int[][] alldiff_totalIssue = MissingValue.getMissingvalue(convertList,Integer.parseInt(beginNum[m][n]), totalIssue, horizontalSpan);
        //获得当前彩种的指定期的遗漏值数据
        int[][] alldiffs  = null;
        if(issueCount<=totalIssue){
            alldiffs  =  new int[issueCount][horizontalSpan];
            for (int i =0; i for (int j =0;jelse{
            alldiffs  =  new int[totalIssue][horizontalSpan];
            for (int i =0; i for (int j =0;j"alldiffs", alldiffs);

        //出现总次数
        List placenum = MissingValue.getTotal(alldiffs);

        //平均遗漏值
        List average_omission = null;
        if(issueCount<=totalIssue){
            average_omission = MissingValue.getCoverage(placenum, issueCount);
        }else{
            average_omission = MissingValue.getCoverage(placenum, totalIssue);
        }
        //最大遗漏值
        List max_omission = MissingValue.getMax(alldiff_totalIssue);

        //最大连出值
        List max_output = MissingValue.getContinuous(alldiffs);
        map.put("max_output", max_output);
        map.put("placenum", placenum);
        map.put("average_omission", average_omission);
        map.put("max_omission", max_omission);
        return map;
    }

    //封装冷热的数据
    public static   Map  saveColoHot(List> list, String lotteryid, String idx,Integer issueCount,Integer totalIssue){
        int m=0,n=0;//m代表当前彩种在彩票id数组的位置,n代表冷热的区域
        Map map = new LinkedHashMap();//封装返回数据的集合,包括alldiffs,average_omission,infolist,max_omission,max_output,placenum,result

        //获取m
        for (int i = 0; i < lotteryidArray.length; i++) {
            if(lotteryidArray[i].equals(lotteryid)){
                m=i;
                break;
            }
        }

        //获取n
        for (int i = 0; i < codeAndHotIdxArray[m].length; i++) {
            if(codeAndHotIdxArray[i].equals(idx)){
                n=i;
                break;
            }
        }
        //获取开奖数据
        List> infolist =new ArrayList<>();
        if(issueCount<=totalIssue){
            for (int j = 0; j < issueCount; j++) {
                //封装每一条开奖数据
                String[] sp = list.get(j).get("result").replaceFirst("\\+", ",").split(",");
                List li  =  new ArrayList<>();
                //封装开奖号码
                for (int i = 0; i else{
            for (int j = 0; j < totalIssue; j++) {
                //封装每一条开奖数据
                String[] sp = list.get(j).get("result").replaceFirst("\\+", ",").split(",");
                List li  =  new ArrayList<>();
                //封装开奖号码
                for (int i = 0; i > placenum = getColdHot(infolist, idx, n);
        map.put("placenum", placenum);
        map.put("result", "success");
        return map;
    }


    //获得冷热的数据
    public static List> getColdHot(List> infolist,String idx,Integer n){
        List> list= new ArrayList<>();

        //对出现的次数做降序排列
        Map map =  new HashMap<>();
        for (int i = 0; i < infolist.size(); i++) {
            if(map.containsKey(infolist.get(i).get(n))){
                map.put(infolist.get(i).get(n), map.get(infolist.get(i).get(n))+1);
            }else{
                map.put(infolist.get(i).get(n), 1);
            }
        }
        List> sortMap = sortMap(map);

        //封装冷热图的数据
        for(Entry entry :sortMap){
            String key = entry.getKey();   
            Integer value = entry.getValue();
            BigDecimal b1 = new BigDecimal(Double.toString(value*100));   
            BigDecimal b2 = new BigDecimal(Double.toString(infolist.size())); 
            double countunm = b1.divide(b2,2,BigDecimal.ROUND_HALF_UP).doubleValue();
            LinkedHashMap lhm =  new LinkedHashMap<>();
            lhm.put(idx, key);
            lhm.put("countid", value+"");
            String countunm1 =String.valueOf(countunm);
            if((countunm1.split("\\.")[1]).length()==1){//此情况代表countunm是整数,小数点后面只有一个0,为满足数据(数据格式:xx.yy00)封装要求,要添加三个0
                lhm.put("countunm", countunm1+"000");
            }else{
                lhm.put("countunm", countunm1+"00");
            }
            list.add(lhm);
        }

        return list;
    }

    //对map集合value实现降序排列
    public static List> sortMap(Map map){
        //获取entrySet
        Set> mapEntries = map.entrySet();

        //使用链表来对集合进行排序,使用LinkedList,利于插入元素
        List> result = new LinkedList<>(mapEntries);
        //自定义比较器来比较链表中的元素
        Collections.sort(result, new Comparator>() {
            //基于entry的值(Entry.getValue()),来排序链表
            @Override
            public int compare(Entry o1,
                    Entry o2) {

                return o2.getValue().compareTo(o1.getValue()) ;
            }

        });

        //将排好序的存入到LinkedHashMap(可保持顺序)中,需要存储键和值信息对到新的映射中。
        Map linkMap = new LinkedHashMap<>();
        for(Entry newEntry :result){
            linkMap.put(newEntry.getKey(), newEntry.getValue());            
        }
        /*//根据entrySet()方法遍历linkMap
        for(Map.Entry mapEntry : linkMap.entrySet()){
            System.out.println("key:"+mapEntry.getKey()+"  value:"+mapEntry.getValue());
        }*/

        return result;
    }
}

====================华丽丽里的分割线=========================

import java.util.ArrayList;
import java.util.List;
import java.util.Map;




/**
 * @admistrator 
 * 计算遗漏值的工具类
 * 
 */
public class MissingValue {
    /**
     * 获取整个区域的遗漏值
     * lis 开奖数据的集合(从数据查询到的开奖数据集合)
     * row 行数
     * column 列数
     */
    public static int[][] getMissingvalue(List> lis,Integer beginNum ,Integer row ,Integer horizontalSpan){
        int[][] arr = new int[row][horizontalSpan];

        //获取整个区域的遗漏值
        for (int k =1 ; k <=horizontalSpan ; k++) {

            //获取每期开奖数据在当前列的位置
            List countList= new ArrayList();
            for (int i = 0; i <=lis.size()-1; i++) {
                for (int j = 0; j if(lis.get(i).get(j)>beginNum+horizontalSpan-1){
                        break;
                    }
                    if(lis.get(i).get(j)==k){
                        countList.add(i);//记录当前列的开奖号码的行号
                    }
                }
            }

            if(countList.size()!=0 && countList!=null){
                int[] arrj=getOthers(countList,arr.length);
                for (int j = 0; j < arrj.length; j++) {
                    arr[j][k-1]=arrj[j];
                }
            }else{
                for (int j = arr.length-1; j >=0; j--) {
                    arr[j][k-1]=arr.length-j;
                }
            }
        }

        return arr;
    }


    //获取每列的遗漏值数据
    public static  int[]  getOthers(List list,int row){
        int[] array=new int[row];
        int n =0;
        while(true){
            if(list.size()==1){
                if(list.get(n)==0){//中奖号码只有一个且在顶部
                    array[n]=0;
                    for (int i = array.length-1; i >0; i--) {
                        array[i]=array.length-i;
                    }
                }else if(list.get(n)==row-1){//中奖号码只有一个且在底部
                    for (int i = list.get(n); i >=0; i--) {
                        array[i]=list.get(n)-i;
                    }
                }else if(list.get(n)>0 && list.get(n)1){//中奖号码只有一个且在中间
                    for (int i = array.length-1; i >list.get(n); i--) {
                        array[i]=array.length-i;
                    }
                    for (int i = list.get(n); i >=0; i--) {
                        array[i]=list.get(n)-i;
                    }
                }
            }else if(list.size()>1){
                if(n==0){//第1个开奖号码
                    if(list.get(n)==0){//当前中奖号码在顶部
                        array[n]=0;
                    }else if(list.get(n)1){//当前号码在中间
                        for (int i = list.get(n); i >=0; i--) {
                            array[i]=list.get(n)-i;
                        }
                    }
                }else if(n+10){//当前为第n+1个开奖号码,而且不是最后一个,那么当前号码一定在中间
                    if(list.get(n)-list.get(n-1)-1!=0){//开奖号码有间隔
                        for (int i = list.get(n); i >list.get(n-1); i--) {
                            array[i]=list.get(n)-i;
                        }
                    }else{//开奖号码没有间隔
                        array[list.get(n)]=0;
                    }
                }else if(n+1==list.size() && n>0){//当前开奖号码为这一列的最后一个开奖号码
                    if(list.get(n)-list.get(n-1)-1>0){//开奖号码有间隔
                        if(list.get(n)==row-1){//当前中奖号码在底部
                            for (int i = list.get(n); i >list.get(n-1); i--) {
                                array[i]=list.get(n)-i;
                            }
                        }else if(list.get(n)1){//当前号码在中间
                            for (int i = list.get(n); i >list.get(n-1); i--) {
                                array[i]=list.get(n)-i;
                            }
                            for (int i = array.length-1; i >=list.get(n)+1; i--) {
                                array[i]=array.length-i;
                            }
                        }
                    }else if(list.get(n)-list.get(n-1)-1==0){//开奖号码没有间隔
                        if(list.get(n)==row-1){//当前中奖号码在底部
                                array[list.get(n)]=0;
                        }else if(list.get(n)1){//当前号码在中间
                            array[list.get(n)]=0;
                            for (int i = array.length-1; i >list.get(n); i--) {
                                array[i]=array.length-i;
                            }
                        }
                    }

                    break;
                }

            }

            if(n==list.size()-1){
                break;
            }
            n++;
        }
        return array;
    }

    /**
     * 处理开奖数据的方法
     * 实现的功能:将每一期在当前区域的开奖数据获取出来,并转换为int 类型
     * lis 开奖数据的集合
     */
    public static List> convertAwardData(List> lis){
        List> list = new ArrayList<>();
        for (int i = 0; i < lis.size(); i++) {
            List lii = new ArrayList<>();
            String[] sp = lis.get(i).get("result").replaceFirst("\\+", ",").split(",");
            for (int j = 0; j < sp.length; j++) {
                lii.add(Integer.parseInt(sp[j]));
            }
            list.add(lii);
        }
        return list;
    }

    /**
     * 计算每列开奖的总次数(即:出现总次数)
     *
     * arr 遗漏值数据的数组
     */
    public static List getTotal(int[][] arr){
        List list = new ArrayList<>();
        for (int i = 0; i < arr[0].length; i++) {
            int count = 0;
            for (int j = 0; j < arr.length; j++) {
                if(arr[j][i]==0){
                    count++;
                }
            }
            list.add(count);
        }
        return list;
    }

    /**
     * 计算平均遗漏值
     *
     * lis 出现总次数集合
     * row  总行数
     */
    public static List getCoverage(List lis ,Integer row){
        List list = new ArrayList<>();
        for (int i = 0; i < lis.size(); i++) {
            if(lis.get(i)!=0){
                list.add(row/lis.get(i));
            }else{
                list.add(0);
            }
        }
        return list;
    }

    /**
     * 计算最大遗漏值
     *
     * arr 遗漏值的集合
     * 
     */
    public static List getMax(int[][] arr){
        List ll =  new ArrayList();
        for (int i = 0; i < arr[0].length; i++) {
            int max=arr[0][i];
            for (int j = 0; j < arr.length; j++) {
                if(arr[j][i]>max)
                    max=arr[j][i];
            }
            ll.add(max);
        }
        return ll;
    }


    /**
     * 计算最大连出值
     *
     * arr 遗漏值的集合
     */
    public static List getContinuous(int[][] arr){
        List list = new ArrayList<>();
        for (int i = 0; i < arr[0].length; i++) {
            StringBuilder sb = new StringBuilder();
            for (int j = 0; j < arr.length; j++) {
                sb.append(arr[j][i]);
            }
            list.add(max(sb.toString()));
        }
        return list;
    }

    //统计相同字符连续出现的最大子序列的长度
    public static int max(String s){  
        int max=0,tmp_m=1;
        for(int i=1;iif(s.charAt(i)==s.charAt(i-1)){  
                tmp_m++;  
            }else{  
                max=max>tmp_m?max:tmp_m;  
                tmp_m=1;  
            }  
        }  
        max=max>tmp_m?max:tmp_m;//最后的连续数与最大连续的比较  
        return max;
    }  
}

**
声明:欢迎一起交流学习,如果转载请注明出处!!!
**

你可能感兴趣的:(java)