本帖最後由 rabbit82047 於 2016-7-11 19:18 編輯
為左重複發明輪子, 所以將自己既諗法實作左- // Example usage:
- // HashSequenceGenerator generator = new HashSequenceGenerator("0123456789", 5);
- // System.out.println(generator.nextKey());
- import java.util.Random;
- public class HashSequenceGenerator {
- private long seed, total;
- private char[] availableChars;
- // Character mapper for each character place, this will make the result key looks like random.
- private char[][] chars;
- private int length, seq;
- public HashSequenceGenerator(String availableChars, int length) {
- this(availableChars.toCharArray(), length, new Random().nextLong());
- }
- public HashSequenceGenerator(String availableChars, int length, long seed) {
- this(availableChars.toCharArray(), length, seed);
- }
- public HashSequenceGenerator(char[] availableChars, int length) {
- this(availableChars, length, new Random().nextLong());
- }
- public HashSequenceGenerator(char[] availableChars, int length, long seed) {
- this(availableChars, length, 0, seed);
- }
- public HashSequenceGenerator(char[] availableChars, int length, int seq, long seed) {
- this.seed = seed;
- this.availableChars = availableChars;
- initializeChars(availableChars, length, seed);
- this.total = (long)(Math.pow(availableChars.length, length));
- this.length = length;
- this.seq = seq;
- }
- // Result will be determined by seed
- private void initializeChars(char[] availableChars, int length, long seed) {
- Random random = new Random(seed);
- this.chars = new char[length][availableChars.length];
- for (char[] aChar : chars) {
- System.arraycopy(availableChars, 0, aChar, 0, aChar.length);
- shuffle(aChar, random);
- }
- }
- private int randomInteger(int min, int max, Random randomGenerator) {
- if (min == max) {
- return min;
- }
- return (int)((randomGenerator.nextDouble() * (max - min + 1)) + min);
- }
- private void shuffle(char[] chars, Random random) {
- for (int i = 0; i < chars.length; i++) {
- int idx = randomInteger(0, chars.length-1, random);
- if (i != idx) {
- char c = chars[i];
- chars[i] = chars[idx];
- chars[idx] = c;
- }
- }
- }
- public String nextKey() {
- return encodeKeyNum(generateKeyNum(length, incrementSeq(), availableChars.length), chars);
- }
- private int incrementSeq() {
- int oldSeq = seq++;
- // Overflow, reset sequence number
- if (seq > total) {
- seq = 0;
- }
- return oldSeq;
- }
- // Sequence number mapper to make the end result looks random
- // Original remap formula: total / partition * (seq % partition) + (int) Math.floor(seq / partition)
- // will generate many repetitive character pattern for a range of sequence numbers which is not ideal.
- public int remap(int num, int length, int base) {
- int v = num;
- int[] vals = new int[length];
- for (int i = 0; i < vals.length; i++) {
- vals[i] = v % base;
- v = (v - vals[i]) / base;
- if (i > 0) {
- vals[i] = (vals[0] + vals[i] + i) % base;
- }
- }
- // Key can be generated directly from here.
- int result = 0;
- for (int i = 0; i < vals.length; i++) {
- result += vals[i] * Math.pow(base, i);
- }
- return result;
- }
- private String encodeKeyNum(int keyNum, char[][] chars) {
- char[] keyChars = new char[length];
- for (int i = 0; i < keyChars.length; i++) {
- keyChars[keyChars.length - i - 1] =
- chars[i][keyNum / ((int) Math.pow(chars[i].length, i)) % chars[keyChars.length-1].length];
- }
- return new String(keyChars);
- }
- private int generateKeyNum(int l, int s, int base) {
- return remap(s, l, base);
- }
- }
複製代碼 又多個 utility class 用  |