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;
}
}