shikeying
2024-01-11 3b67e947e36133e2a40eb2737b15ea375e157ea0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package com.walker.etaa.util;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
 
public class AlgorithmUtils {
 
    private static final Logger logger = LoggerFactory.getLogger(AlgorithmUtils.class);
    private static final Random random = new Random();
 
    /**
     * 返回给定数据的 HashCode 值集合。
     * @param prefix 字符串前缀,如:math
     * @param indexList 数据记录索引集合,如:[1,3,5,7,...]
     * @return
     * @date 2023-03-08
     */
    public static final List<Integer> getHashCode(String prefix, int[] indexList){
        if(indexList == null || indexList.length == 0){
            return null;
        }
        List<Integer> resultList = new ArrayList<>(indexList.length + 8);
        String s = null;
        for(int i=0; i<indexList.length; i++){
            s = prefix + indexList[i];
            resultList.add(s.hashCode());
        }
        return resultList;
    }
 
    /**
     * 返回给定范围可用的(随机)数据索引编号集合,如:
     * <pre>
     *     [1,8,5,12,33,...]
     * </pre>
     * @param existTotal
     * @param requiredTotal
     * @return
     */
    public static final int[] getRandomIndexArray(int existTotal, int requiredTotal){
        int span = existTotal / requiredTotal;
        int offset = 1;
        if(span > 1){
            offset = Math.abs(random.nextInt(span));
        } else {
            offset = Math.abs(random.nextInt(requiredTotal-1));
        }
        if(offset >= existTotal || offset <= 0){
            offset = 1;
        }
        int count = 0;
        List<Integer> data = new ArrayList<>();
        while (count < requiredTotal){
            if(offset >= existTotal || offset <= 0){
                offset = Math.abs(random.nextInt(requiredTotal-1));
//                logger.debug("------> offset = {}", offset);
            }
            if(!data.contains(offset)){
//                logger.debug(".......... offset = {}", offset);
                data.add(offset);
//                offset = random.nextInt(requiredTotal-1) + span;
                offset = Math.abs(random.nextInt(existTotal-1)) + span;
                count ++;
                logger.debug("count = {}, offset = {}", count, offset);
            } else {
                // 已有重复了,
//                offset = count + 1;
                offset = Math.abs(random.nextInt(existTotal-1));
                logger.debug("重复了,offset = {}", offset);
            }
        }
        if(data.size() > 0){
            int[] resultList = new int[data.size()];
            for(int i=0; i<data.size(); i++){
                resultList[i] = data.get(i);
            }
            return resultList;
        }
        return null;
    }
 
    /**
     * 返回给定范围可用的(平均分布)数据索引编号集合,如:
     * <pre>
     *     [1,3,5,7,9,...]
     * </pre>
     * @param existTotal
     * @param requiredTotal
     * @return
     */
    public static final int[] getAverageIndexArray(int existTotal, int requiredTotal){
        int[] result = new int[requiredTotal];
        int span = existTotal / requiredTotal;
        int offset = Math.abs(random.nextInt(10));
        logger.debug("offset = " + offset);
        if(span == 1){
            for(int i=0; i<requiredTotal; i++){
//                System.out.println("get " + (i+1));
                result[i] = i+1;
            }
        } else if(span > 1){
            int current = offset;
            if(current == 0){
                current = 1;
            }
 
            int last = AlgorithmUtils.getAverageLastIndex(current, span, requiredTotal);
            while(last > existTotal){
                logger.debug("最后元素超过了'existTotal',last = " + last);
                if(span > 1){
                    span --;
                } else if(offset > 1){
                    offset --;
                } else {
                    logger.warn("已经无法降低抽取间隔了,退出循环");
                    break;
                }
                last = AlgorithmUtils.getAverageLastIndex(current, span, requiredTotal);
            }
 
            for(int i=0; i<requiredTotal; i++){
                if(i > 0){
                    current += span;
                }
//                System.out.println("get " + (current));
                result[i] = current;
            }
        }
        return result;
    }
 
    /**
     * 返回平均分布方式抽取时,计算最后元素的索引值(计数值,是否超过题库最大值)
     * @param first 第一个元素索引,从
     * @param span
     * @param requiredTotal
     * @return
     */
    public static final int getAverageLastIndex(int first, int span, int requiredTotal){
        int current = first;
        for(int i=0; i<requiredTotal; i++){
            if(i > 0){
                current += span;
            }
//            System.out.println("get " + (current));
        }
        return current;
    }
}