JAVA 中的字母数字增量算法
Alphanumeric increment algorithm in JAVA
我需要实现字母数字增量算法,例如
AAA001 应该变成 AAA002
AAA999应该变成AAB000等等。
所有字母均为大写字母,字母范围为 0-9。
它可以在字母数字字符串的任何位置包含字母或字母。
虽然有一些规则,比如一些 000 或 666 不应该出现在一个系列中。这可以稍后完成,但我需要基本逻辑来实现该算法。
我看到很多人不明白我的问题。
想象一下车辆的车牌号,它只不过是一个字母数字系列,可以包含一些排除字符,如 BB6660 -> 666,中间的三重 6 是不允许的。
它应该支持不同的格式,比如-
@@@##
@#@@##
1@#@@##
@@@@####
##@@#@
@ means alphabet A-Z
# means numbers 0-9
示例:
AFG99 + 1= AFH00
A2GF23 + 1 = A2GF24
1A9AU99 + 1 = 1A9AV00
AAZZ9999 + 1 = ABAA0000
11AA9Z + 1 = 11AB0A
我需要某种数学解决方案,这样我就可以在不使用字符增量的情况下轻松地进行数学运算和增量。
我还需要两个范围之间的计数,例如 AAA003 和 AA010 之间有多少个计数?
AAA010 - AAA003 = 7
非常感谢您的帮助..
这里有 3 个解决方案:前两个有点算术增量,而第三个更多是字符操作。
这 3 个实现都通过了相同的单元测试:
assertEquals("1DDA01A", MyClass.increment("1DDA00Z"));
assertEquals("1A9AV00", MyClass.increment("1A9AU99"));
assertEquals("AFH00", MyClass.increment("AFG99"));
assertEquals("A2GF24", MyClass.increment("A2GF23"));
assertEquals("ABAA0000", MyClass.increment("AAZZ9999"));
assertEquals("11AB0A", MyClass.increment("11AA9Z"));
第一个:
public static String increment(String number) {
Pattern compile = Pattern.compile("^(.*?)([9Z]*)$");
Matcher matcher = compile.matcher(number);
String left="";
String right="";
if(matcher.matches()){
left = matcher.group(1);
right = matcher.group(2);
}
number = !left.isEmpty() ? Long.toString(Long.parseLong(left, 36) + 1,36):"";
number += right.replace("Z", "A").replace("9", "0");
return number.toUpperCase();
}
第二个:
public static String increment(String number) {
Pattern compile = Pattern.compile("^(.*?)([0-9]*|[A-Z]*)$");
Matcher matcher = compile.matcher(number);
String remaining = number;
String currentGroup = "";
String result = "";
boolean continueToNext = true;
while (matcher.matches() && continueToNext) {
remaining = matcher.group(1);
currentGroup = matcher.group(2);
int currentGroupLength = currentGroup.length();
int base = currentGroup.matches("[0-9]*") ? 10 : 36;
currentGroup = Long.toString(Long.parseLong("1" + currentGroup, base) + 1, base); // The "1" if just to ensure that "000" doesn't become 0 (and thus losing the original string length)
currentGroup = currentGroup.substring(currentGroup.length() - currentGroupLength, currentGroup.length());
continueToNext = Long.valueOf(currentGroup, base) == 0;
if (base == 36) {
currentGroup = currentGroup.replace("0", "A");
}
result = currentGroup + result;
matcher = compile.matcher(remaining);
}
result = remaining + result;
return result.toUpperCase();
}
第三:
这适用于您当前的 "reqs"。比起一开始问的how what这个问题,这不只是一个"left-part composed of letter" + "right part composed of digits"。现在,它是"anything goes",字母从A到Z滚动到A,而数字从0到9到0。当一个字母到达Z时,它被重置为A,然后是它左边的digit/letter递增。
如果所有数字都递增,则不会在左侧添加新数字。你没有在你的问题中提到这一点,但我相信你可以从这里弄清楚:
public static String increment(String number) {
char[] cars = number.toUpperCase().toCharArray();
for (int i = cars.length - 1; i >= 0; i--) {
if (cars[i] == 'Z') {
cars[i] = 'A';
} else if (cars[i] == '9') {
cars[i] = '0';
} else {
cars[i]++;
break;
}
}
return String.valueOf(cars);
}
至于"count",你的例子不足以理解逻辑。它只计算数字吗?字母呢?它是否遵循 baseXx?
AA010-AAA003 = 7, 3 A 和 2 A 怎么能不管呢?
我觉得这更需要您了解您的要求(即:家庭作业..)
从技术上讲,这回答了最初提出的问题(在此过程中进行了许多修改)。
[doing] math and increment [alphanumerics] without using character increment
可以分解为更简单的问题:考虑使用混合基数编码的 "alphanumerics" 整数 。这将使从 alphanumeric 到 integer, (math
) 操作的转换(增量,count between: difference/subtraction) 在 整数 上,以及从 整数 到 字母数字 的转换。
对于 整数 ,请查看 LongAdder。对于转换,您需要保留一系列要使用的基数——我建议从 unit/the 小端开始,只使用易于迭代且能够保留(小)整数的东西。从 alphanumeric 到 integer,从零开始。对于每个字符,添加其值。对于一个字母,将不同字母的数量(字母表大小,现在使用的拉丁字母表为 26 个)作为该位置的基数,对于一个数字,则为不同数字的数量(通常为 10 个)。如果后面有另一个字符,则乘以该基数并重复。
从 integer 到 alphanumeric 的转换将是通常的 divide&remainder (使用保留的基数) - 有一个问题:你如何处理从最重要的位置进位?
There are some rules though, like some 000 or 666 should not come in a series. That can be done later on
并且会杀死 math
.
我需要实现字母数字增量算法,例如 AAA001 应该变成 AAA002 AAA999应该变成AAB000等等。
所有字母均为大写字母,字母范围为 0-9。 它可以在字母数字字符串的任何位置包含字母或字母。
虽然有一些规则,比如一些 000 或 666 不应该出现在一个系列中。这可以稍后完成,但我需要基本逻辑来实现该算法。
我看到很多人不明白我的问题。 想象一下车辆的车牌号,它只不过是一个字母数字系列,可以包含一些排除字符,如 BB6660 -> 666,中间的三重 6 是不允许的。
它应该支持不同的格式,比如-
@@@##
@#@@##
1@#@@##
@@@@####
##@@#@
@ means alphabet A-Z
# means numbers 0-9
示例:
AFG99 + 1= AFH00
A2GF23 + 1 = A2GF24
1A9AU99 + 1 = 1A9AV00
AAZZ9999 + 1 = ABAA0000
11AA9Z + 1 = 11AB0A
我需要某种数学解决方案,这样我就可以在不使用字符增量的情况下轻松地进行数学运算和增量。
我还需要两个范围之间的计数,例如 AAA003 和 AA010 之间有多少个计数?
AAA010 - AAA003 = 7
非常感谢您的帮助..
这里有 3 个解决方案:前两个有点算术增量,而第三个更多是字符操作。
这 3 个实现都通过了相同的单元测试:
assertEquals("1DDA01A", MyClass.increment("1DDA00Z"));
assertEquals("1A9AV00", MyClass.increment("1A9AU99"));
assertEquals("AFH00", MyClass.increment("AFG99"));
assertEquals("A2GF24", MyClass.increment("A2GF23"));
assertEquals("ABAA0000", MyClass.increment("AAZZ9999"));
assertEquals("11AB0A", MyClass.increment("11AA9Z"));
第一个:
public static String increment(String number) {
Pattern compile = Pattern.compile("^(.*?)([9Z]*)$");
Matcher matcher = compile.matcher(number);
String left="";
String right="";
if(matcher.matches()){
left = matcher.group(1);
right = matcher.group(2);
}
number = !left.isEmpty() ? Long.toString(Long.parseLong(left, 36) + 1,36):"";
number += right.replace("Z", "A").replace("9", "0");
return number.toUpperCase();
}
第二个:
public static String increment(String number) {
Pattern compile = Pattern.compile("^(.*?)([0-9]*|[A-Z]*)$");
Matcher matcher = compile.matcher(number);
String remaining = number;
String currentGroup = "";
String result = "";
boolean continueToNext = true;
while (matcher.matches() && continueToNext) {
remaining = matcher.group(1);
currentGroup = matcher.group(2);
int currentGroupLength = currentGroup.length();
int base = currentGroup.matches("[0-9]*") ? 10 : 36;
currentGroup = Long.toString(Long.parseLong("1" + currentGroup, base) + 1, base); // The "1" if just to ensure that "000" doesn't become 0 (and thus losing the original string length)
currentGroup = currentGroup.substring(currentGroup.length() - currentGroupLength, currentGroup.length());
continueToNext = Long.valueOf(currentGroup, base) == 0;
if (base == 36) {
currentGroup = currentGroup.replace("0", "A");
}
result = currentGroup + result;
matcher = compile.matcher(remaining);
}
result = remaining + result;
return result.toUpperCase();
}
第三:
这适用于您当前的 "reqs"。比起一开始问的how what这个问题,这不只是一个"left-part composed of letter" + "right part composed of digits"。现在,它是"anything goes",字母从A到Z滚动到A,而数字从0到9到0。当一个字母到达Z时,它被重置为A,然后是它左边的digit/letter递增。
如果所有数字都递增,则不会在左侧添加新数字。你没有在你的问题中提到这一点,但我相信你可以从这里弄清楚:
public static String increment(String number) {
char[] cars = number.toUpperCase().toCharArray();
for (int i = cars.length - 1; i >= 0; i--) {
if (cars[i] == 'Z') {
cars[i] = 'A';
} else if (cars[i] == '9') {
cars[i] = '0';
} else {
cars[i]++;
break;
}
}
return String.valueOf(cars);
}
至于"count",你的例子不足以理解逻辑。它只计算数字吗?字母呢?它是否遵循 baseXx?
AA010-AAA003 = 7, 3 A 和 2 A 怎么能不管呢? 我觉得这更需要您了解您的要求(即:家庭作业..)
从技术上讲,这回答了最初提出的问题(在此过程中进行了许多修改)。
[doing] math and increment [alphanumerics] without using character increment
可以分解为更简单的问题:考虑使用混合基数编码的 "alphanumerics" 整数 。这将使从 alphanumeric 到 integer, (math
) 操作的转换(增量,count between: difference/subtraction) 在 整数 上,以及从 整数 到 字母数字 的转换。
对于 整数 ,请查看 LongAdder。对于转换,您需要保留一系列要使用的基数——我建议从 unit/the 小端开始,只使用易于迭代且能够保留(小)整数的东西。从 alphanumeric 到 integer,从零开始。对于每个字符,添加其值。对于一个字母,将不同字母的数量(字母表大小,现在使用的拉丁字母表为 26 个)作为该位置的基数,对于一个数字,则为不同数字的数量(通常为 10 个)。如果后面有另一个字符,则乘以该基数并重复。
从 integer 到 alphanumeric 的转换将是通常的 divide&remainder (使用保留的基数) - 有一个问题:你如何处理从最重要的位置进位?
There are some rules though, like some 000 or 666 should not come in a series. That can be done later on
并且会杀死 math
.