组合学:使用10个数字与52个字母生成1477万个不重复的4位串码V3完结版本

一.主要思想(进位制思想):

将0-9-A-z,62个字符做为一个进制系统,存入一个数组,既62位数字进制,4位串码前位不够补0。
累加的操作只需要将末位往后移动一位循环移动,逢"Z"数制进一位。好比9进一位到10。

{
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
        , "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
        , "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
}

比如:
已知串码[a][b][c][d]
求下一位串码
将末位[d]往后移一位得到:[e]
故求得下一位串码是[a][b][c][e]  

二.实现思路

输入参数:当前串码

输出:新的串码

三.下面走 java代码实现( CombinationNumberV3 )

/**
 * Copyright (C), 2000-2021, XXX有限公司
 * FileName: CombinationNumberV3
 * Author: wangyetao
 * Date: 21-10-23 08:30:24
 * Description:使用10个数字与52个字母生成n个不重复的n位串码,相当于62位数进制
 * 将0-9-A-z,62个字符做为一个进制系统,存入一个数组,既62位数字进制,4位串码前位不够补0。
 * 累加的操作只需要将末位往后移动一位循环移动,逢"Z"数制进一位。好比9进一位到10。
 * <p>
 * 比如:
 * * 已知串码[a][b][c][d]
 * * 求下一位串码
 * * 将末位[d]往后移一位得到:[e]
 * * 故求得下一位串码是[a][b][c][e]
 * 主要思路:
 * * 补位+进位+递归
 * <p>
 * History:
 * <author> <time> <version> <desc>
 * 作者姓名 修改时间 版本号 版本描述
 * wangyetao,21-10-21 15:29:22,CombinationNumberV2,版本描述
 * wangyetao,21-10-23 08:30:24,CombinationNumberV3,进位逻辑改用[递归]实现
 */
package simple.callback.cryptographyalgorithm;

/**
 * @ClassName: CombinationNumberV3
 * @Description: java类描述
 * @Author: wangyetao
 * @Date: 21-10-23 08:30:24
 */
public class CombinationNumberV3 {

    private static String[] digitalsystemtable = {
            "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
            , "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
            , "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
    };
    private static int DIGITALMETER_LENGTH = digitalsystemtable.length;//数制表长度
    private int defaultDigit = 4;//数位默认长度


    /**
     * 根据当前串码获取下一位串码
     *
     * @param digit          数位长度
     * @param currentCodeStr 当前串码
     * @return 获取下一位串码
     */
    public String generateNextCode(int digit, String currentCodeStr) {
        defaultDigit = digit;
        String[] digitalTempArr = currentCodeStr.split("");
        String[] digitalArr = new String[defaultDigit];

        //串码检测
        boolean isCompliance = filterCharacter(currentCodeStr);
        if (!isCompliance) {
            return "不合规的串码参数";
        }
        //补位检测
        digitalArr = doComplement(digitalTempArr);

        //保存单独位值
        String[] singleDigital = new String[defaultDigit];
        for (int i = 0; i < digitalArr.length; i++)
            singleDigital[i] = digitalArr[i];

        //进位开关
        boolean[] singleCarryup = new boolean[defaultDigit];
        int carryupLength = singleCarryup.length;
        for (int i = 0; i < carryupLength; i++)
            singleCarryup[i] = false;


        //进位思想主要逻辑递归代码
        singleDigital = recursiveNext(singleDigital, singleCarryup, 1);


        //拼接单独位值
        StringBuffer tmpBuff = new StringBuffer();
        for (String tmp : singleDigital)
            tmpBuff.append(tmp);

        return tmpBuff.toString();
    }

    /**
     * 数制运算与递归进位运算
     *
     * @param inSingleDigital 单独位值
     * @param inSingleCarryup 进位开关
     * @param step            步长为1
     */
    private String[] recursiveNext(String[] inSingleDigital, boolean[] inSingleCarryup, int step) {
        String[] singleDigital = inSingleDigital;
        boolean[] singleCarryup = inSingleCarryup;

        //步长控制A处:步长不能超过进位开关数长度;递归出口条件;
        //当步长大于进位开关数长度时,说明此时所有的位值均须进位,此时首位已到达最大值,无须再进位,归为0,进入下一轮。
        if (step <= singleDigital.length) {
            int inBinary62Index = indexOfDigitalsystemtable(singleDigital[defaultDigit - step]);
            inBinary62Index++;//下标后移一位

            if (inBinary62Index > DIGITALMETER_LENGTH - 1) {//进位检测
                singleDigital[defaultDigit - step] = digitalsystemtable[0];//数制进位前,本位归0
                singleCarryup[singleCarryup.length - step] = true;//打开开关,数制进一位

                if (singleCarryup[singleCarryup.length - step]) {

                    step++;
                    recursiveNext(singleDigital, singleCarryup, step);//进位递归
                }
            } else {
                singleDigital[defaultDigit - step] = digitalsystemtable[inBinary62Index];//单独位值取后移一位的值,即"+1"
            }
        }

        return singleDigital;
    }

    /**
     * 补位,前位不够补0
     *
     * @param inDigitalTempArr
     * @return targetArr
     */
    private String[] doComplement(String[] inDigitalTempArr) {
        String[] inTempArr = inDigitalTempArr;//[1][2][3]
        String[] targetArr = new String[defaultDigit];//[][][][]
        int differ = targetArr.length - inTempArr.length;

        //补位,前位不够补0
        if (inTempArr.length < targetArr.length) {
            //1)保存已有的值到目标数组
            for (int i = 0; i < inTempArr.length; i++)
                targetArr[i + differ] = inTempArr[i];

            //2)补位
            for (int i = 0; i < differ; i++)
                targetArr[i] = "0";

        } else {

            for (int i = 0; i < defaultDigit; i++)
                targetArr[i] = inTempArr[i];
        }
        return targetArr;
    }

    /**
     * 根据当前串码获取下一位串码
     *
     * @param digit          数位长度
     * @param currentCodeStr 当前串码
     * @return 获取下一位串码
     */
    private String next(int digit, String currentCodeStr) {
        return generateNextCode(digit, currentCodeStr);
    }

    /**
     * 检索值在数组中的下标
     *
     * @param binaryValue
     * @return 下标
     */
    private int indexOfDigitalsystemtable(String binaryValue) {
        int sourceIndex = -1;

        for (int i = 0; i < DIGITALMETER_LENGTH; i++) {
            if (binaryValue.equals(digitalsystemtable[i])) {
                sourceIndex = i;
                break;
            }
        }
        return sourceIndex;
    }

    /**
     * 判断是否是合规串码
     *
     * @param currentCodeStr 串码
     * @return
     */
    private boolean filterCharacter(String currentCodeStr) {
        boolean isCompliance = true;
        String[] digitalTempArr = currentCodeStr.split("");
        for (int i = 0; i < digitalTempArr.length; i++) {
            if (indexOfDigitalsystemtable(digitalTempArr[i]) < 0) {
                isCompliance = false;
                break;
            }
        }
        return isCompliance;
    }


    /**
     * 测试用例
     *
     * @param args
     */
    public static void main(String[] args) throws InterruptedException {
        CombinationNumberV3 combinationNumber = new CombinationNumberV3();

        //DEMO_TEST1
        /*String initStr = "0000";
        int count = 0;
        count++;
        long startTime = System.currentTimeMillis();
        System.out.println(initStr);
        while (!initStr.equals("ZZZZ")) {
            initStr = combinationNumber.generateNextCode(4, initStr);
            count++;
            System.out.println(initStr);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("count=" + count + ",耗时" + (endTime - startTime) + "ms");*/


        //DEMO_TEST2
        /*System.out.println(combinationNumber.generateNextCode(5, "0000"));
        System.out.println(combinationNumber.generateNextCode(5, "ahzz"));
        System.out.println(combinationNumber.generateNextCode(5, "YYYY"));
        System.out.println(combinationNumber.generateNextCode(5, "ZZYZ"));
        System.out.println(combinationNumber.generateNextCode(5, "ZZZY"));
        System.out.println(combinationNumber.generateNextCode(5, "ZZZZ"));
        System.out.println(combinationNumber.generateNextCode(5, "ZZZZZZZZZZ"));*/

        //DEMO_TEST3
        /*System.out.println(combinationNumber.generateNextCode(10, "000"));
        System.out.println(combinationNumber.generateNextCode(10, "00"));
        System.out.println(combinationNumber.generateNextCode(10, "0"));
        System.out.println(combinationNumber.generateNextCode(10, ""));
        System.out.println(combinationNumber.generateNextCode(10, "000-"));
        System.out.println(combinationNumber.generateNextCode(10, "-00-"));
        System.out.println(combinationNumber.generateNextCode(10, "0-0-"));
        System.out.println(combinationNumber.generateNextCode(10, "--0-"));
        System.out.println(combinationNumber.generateNextCode(10, "----"));
        System.out.println(combinationNumber.generateNextCode(10, "ZZHZAA"));*/

        //DEMO_TEST4
        String initStr = "0000";
        int count = 0;
        count++;
        long startTime = System.currentTimeMillis();
        System.out.println(initStr);
        while (!initStr.equals("ZZZZZZZZZZ")) {
            initStr = combinationNumber.generateNextCode(10, initStr);
            count++;
            System.out.println(initStr);
            Thread.sleep(100);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("count=" + count + ",耗时" + (endTime - startTime) + "ms");

        /*//DEMO_TEST5
        FileOutputStream fos = new FileOutputStream("/home/wangyetao/Documents/CombinationNumberV2Test_DEMO_TEST5.log");

        String initStr = "0000";
        int count = 0;
        count++;
        long startTime = System.currentTimeMillis();
        System.out.println(combinationNumber.generateNextCode(10, initStr));
        fos.write((initStr + "\n").getBytes());
        while (!initStr.equals("ZZZZ")) {
            initStr = combinationNumber.generateNextCode(10, initStr);
            count++;
            System.out.println(initStr);
            fos.write((initStr + "\n").getBytes());
        }
        fos.close();

        long endTime = System.currentTimeMillis();
        System.out.println("count=" + count + ",耗时" + (endTime - startTime) + "ms");*/
    }

}

CombinationNUmberV3_TEST4与输出(CombinationNUmberV3_TEST4run.gif):

CombinationNUmberV3_TEST4_2run.gif:

在此记录与总结,2021年 10月 23日 星期六 11:08:59 CST。 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dnbug Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值