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<String, Object> trendInfo(List<Map<String, String>> list, String lotteryid, String idx, Integer issueCount, Integer totalIssue) {
    int m = 0, n = 0, horizontalSpan = 0;//m代表当前彩种在彩票id数组的位置;n代表要展示的区域(如红一区,后区等)或者数字域(百位,十位,各位等);horizontalSpan水平方向的跨度
    Map<String, Object> map = new LinkedHashMap<String, Object>();//封装返回数据的集合,包括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<Map<String, String>> infolist = new ArrayList<>();
    if (issueCount <= totalIssue) {
        for (int j = 0; j < issueCount; j++) {
            //封装每一条开奖数据
            String[] sp = list.get(j).get("result").replaceFirst("\\+", ",").split(",");
            Map<String, String> ma1 = new LinkedHashMap<String, String>();
            //封装期号
            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<String, String> ma1 = new LinkedHashMap<String, String>();
            //封装期号
            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<List<Integer>> 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 < alldiffs.length; i++) {
            for (int j = 0; j < horizontalSpan; j++) {
                alldiffs[i][j] = alldiff_totalIssue[i][j];
            }
        }
    } else {
        alldiffs = new int[totalIssue][horizontalSpan];
        for (int i = 0; i < alldiffs.length; i++) {
            for (int j = 0; j < horizontalSpan; j++) {
                alldiffs[i][j] = alldiff_totalIssue[i][j];
            }
        }
    }
    map.put("alldiffs", alldiffs);

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

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

    //最大连出值
    List<Integer> 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<String, Object> saveColoHot(List<Map<String, String>> list, String lotteryid, String idx, Integer issueCount, Integer totalIssue) {
    int m = 0, n = 0;//m代表当前彩种在彩票id数组的位置,n代表冷热的区域
    Map<String, Object> map = new LinkedHashMap<String, Object>();//封装返回数据的集合,包括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<List<String>> infolist = new ArrayList<>();
    if (issueCount <= totalIssue) {
        for (int j = 0; j < issueCount; j++) {
            //封装每一条开奖数据
            String[] sp = list.get(j).get("result").replaceFirst("\\+", ",").split(",");
            List<String> li = new ArrayList<>();
            //封装开奖号码
            for (int i = 0; i < sp.length; i++) {
                li.add(sp[i]);
            }
            infolist.add(li);
        }
    } else {
        for (int j = 0; j < totalIssue; j++) {
            //封装每一条开奖数据
            String[] sp = list.get(j).get("result").replaceFirst("\\+", ",").split(",");
            List<String> li = new ArrayList<>();
            //封装开奖号码
            for (int i = 0; i < sp.length; i++) {
                li.add(sp[i]);
            }
            infolist.add(li);
        }
    }

    List<LinkedHashMap<String, String>> placenum = getColdHot(infolist, idx, n);
    map.put("placenum", placenum);
    map.put("result", "success");
    return map;
}


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

    //对出现的次数做降序排列
    Map<String, Integer> 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<Entry<String, Integer>> sortMap = sortMap(map);

    //封装冷热图的数据
    for (Entry<String, Integer> 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<String, String> 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<Map.Entry<String, Integer>> sortMap(Map<String, Integer> map) {
    //获取entrySet
    Set<Map.Entry<String, Integer>> mapEntries = map.entrySet();

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

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

    });

    //将排好序的存入到LinkedHashMap(可保持顺序)中,需要存储键和值信息对到新的映射中。
    Map<String, Integer> linkMap = new LinkedHashMap<>();
    for (Entry<String, Integer> newEntry : result) {
        linkMap.put(newEntry.getKey(), newEntry.getValue());
    }
    /*//根据entrySet()方法遍历linkMap
    for(Map.Entry<String, Integer> 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<List<Integer>> lis, Integer beginNum, Integer row, Integer horizontalSpan) {
        int[][] arr = new int[row][horizontalSpan];

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

            //获取每期开奖数据在当前列的位置
            List<Integer> countList = new ArrayList<Integer>();
            for (int i = 0; i <= lis.size() - 1; i++) {
                for (int j = 0; j < lis.get(i).size(); 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<Integer> 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) < row - 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) < row - 1) {//当前号码在中间
                        for (int i = list.get(n); i >= 0; i--) {
                            array[i] = list.get(n) - i;
                        }
                    }
                } else if (n + 1 < list.size() && n > 0) {//当前为第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) < row - 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) < row - 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<List<Integer>> convertAwardData(List<Map<String, String>> lis) {
        List<List<Integer>> list = new ArrayList<>();
        for (int i = 0; i < lis.size(); i++) {
            List<Integer> 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;
    }

    /**
     * 计算每列开奖的总次数(即:出现总次数)
     * <p>
     * arr 遗漏值数据的数组
     */
    public static List<Integer> getTotal(int[][] arr) {
        List<Integer> 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;
    }

    /**
     * 计算平均遗漏值
     * <p>
     * lis 出现总次数集合
     * row  总行数
     */
    public static List<Integer> getCoverage(List<Integer> lis, Integer row) {
        List<Integer> 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;
    }

    /**
     * 计算最大遗漏值
     * <p>
     * arr 遗漏值的集合
     */
    public static List<Integer> getMax(int[][] arr) {
        List<Integer> ll = new ArrayList<Integer>();
        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;
    }


    /**
     * 计算最大连出值
     * <p>
     * arr 遗漏值的集合
     */
    public static List<Integer> getContinuous(int[][] arr) {
        List<Integer> 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; i < s.length(); i++) {
            if (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;
    }

}

猜你喜欢

转载自blog.csdn.net/qq_30442585/article/details/82824437