I didn't start too long ago with programming, and currently I need a method to produce an array, containing a character which is comes after the previous character. It should start with an 'A' at 0, then a B at '1' etc.. The hard part is making it so that after the 'Z' comes 'AA'.
What I came up with:
public static String[] charArray(int length)
{
String[] res = new String[length];
for(int i = 0; i < length; i++)
{
String name = "";
int colNumber = i;
while(colNumber > 0)
{
char c = (char) ('A' + (colNumber % 26));
name = c + name;
colNumber = colNumber / 26;
}
res[i] = name;
}
return res;
}
This works fine for the first 26 letters of the alphabet, but it produces "... Y, Z, BA, BB, BC..." instead of "... Y, Z, AA, AB, AC..."
What's wrong? Or are there any more efficient or easier ways to do this?
Thanks in advance!
You had a nice start. Instead of running through the while loop this example basically calculates the value of C based on the number % 26
Then the letter is added (concatenated) to the value within the array at the position: (index / 26) - 1 which ensures it's keeping up with the changes over time.
When iterating through on the first go, you'll have only one letter in each slot in the array A B C etc.
Once you've run through the alphabet, you'll then have an index that looks backwards and adds the current letter to that value.
You'll eventually get into AAA AAB AAC etc. or even more.
public static String[] colArray(int length) {
String[] result = new String[length];
String colName = "";
for(int i = 0; i < length; i++) {
char c = (char)('A' + (i % 26));
colName = c + "";
if(i > 25){
colName = result[(i / 26) - 1] + "" + c;
}
result[i] = colName;
}
return result;
}
Try like this:
public static String[] charArray(int length)
{
String[] res = new String[length];
int counter = 0;
for(int i = 0; counter < length; i++)
{
String name = "";
int colNumber = i;
while(colNumber > 0 && colNumber % 27 != 0)
{
char c = (char) ('A' + ((colNumber) % 27) - 1);
name = c + name;
colNumber = colNumber / 27;
}
res[counter] = name;
if (i % 27 != 0) {
counter++;
}
}
return res;
}
Basically your algorithm skipped all elements starting with an A (A, AA, AB, ...) (because an A is created when colNumber is 0, but this never happens because your while terminates in that case). Taking modulo of 27 and then actually subtracting 1 after from the char fixes this issue. Then we use counter as index as otherwise we would end up with some empty elements in the array (the ones where i would be i % 27 == 0).
This solution works for me. Having 26 vocabulary letters and knowing that 65 is the char 'A' in ASCII table, we can get the incrementing with this recursive method...
private fun indexLetters(index: Int, prefix: String = "") : String {
val indexSuffix:Int = index.rem(26)
val suffix = (65 + indexSuffix).toChar().toString().plus(".")
val newPrefix = suffix.plus(prefix)
val indexPrefix: Int = index / 26
return if (indexPrefix > 0) {
indexLetters(indexPrefix - 1, newPrefix)
} else {
newPrefix
}
}
You can call this kotlin method like
indexLetters(0) //To get an 'A'
indexLetters(25) //To get a 'Z'
indexLetters(26) //To get an 'A.A'
etcetera...
from an array iteration, depending of your requirements
Related
This is my code for the problem
Assume that the value of a = 1, b = 2, c = 3, ... , z = 26. You are
given a numeric string S. Write a program to return the list of all
possible codes that can be generated from the given string.
import java.util.*;
public class solution {
// Return a string array that contains all possible codes
public static String[] getCode(String input){
// Write your code here
List<String> arrStr = new ArrayList<>();
printAllPossibleCodes(input, "", arrStr);
// for(String name: arrStr) {
// System.out.println(name);
// }
String[] arr = new String[arrStr.size()];
for(int j =0; j < arrStr.size(); j++){
arr[j] = arrStr.get(j);
}
return arr;
}
public static char getChar(int n){
return (char) (n+96);
}
public static void printAllPossibleCodes(String input, String ans, List<String> arrStr){
if(input.length() == 0){
//System.out.println(ans);
arrStr.add(ans);
return;
}
int firstDigit = input.charAt(0) - '0';
printAllPossibleCodes(input.substring(1), ans + getChar(firstDigit), arrStr);
if(input.length() > 1){
int firstTwoDigits = (input.charAt(0) - '0') * 10 + (input.charAt(1) - '0');
if(firstTwoDigits >= 10 && firstTwoDigits <= 20){
printAllPossibleCodes(input.substring(2), ans + getChar(firstTwoDigits), arrStr);
}
}
}
}
I'm failing test cases for inputs "123" and "1123" while I'm passing the test for "35411". Where is my code going wrong?
You are requiring 10 <= firstTwoDigits <= 20 in order to call printAllPossibleCodes recursively in the two-digit case. However, as there are 26 letters in the English alphabet, the requirement should be 10 <= firstTwoDigits <= 26. Your first two test cases fail because they contain "23" as a substring, which is not between 10 and 20. However, the third test case contains no two-digit substring larger than 20 but less than 27 and thus does not have this issue.
I am trying to find frequency of a longest substring in a huge string.
'Huge string' can be up to 2M characters long, only a-z
'Substring' may be between 100k to 2M characters long
'Substring' is always same or smaller size than 'Huge string'
currently, I am using following method which I created:
public static int[] countSubstringOccurence(String input, int substringLength) {
// input = from 100 000 to 2 000 000 alphanumeric characters long string;
// substringLength = from 100 000 to 2 000 000, always smaller than input
LinkedHashMap < String, Integer > substringOccurence = new LinkedHashMap < > ();
int l;
for (int i = 0; i < (input.length() - substringLength) + 1; i++) {
String substring = input.substring(i, i + substringLength);
if (substringOccurence.containsKey(substring)) {
l = substringOccurence.get(substring);
substringOccurence.put(substring, ++l);
} else {
substringOccurence.put(substring, 1);
}
}
List < Integer > substringOccurenceList = new ArrayList < > (substringOccurence.values());
int numberOfUniqueSubstrings = substringOccurenceList.size();
int numberOfOccurenciesOfMostCommonSubstrings = 0;
int numberOfSubstringsOfMostCommonSubstring = 0;
for (int i: substringOccurenceList) {
if (i > numberOfOccurenciesOfMostCommonSubstrings) {
numberOfOccurenciesOfMostCommonSubstrings = i;
numberOfSubstringsOfMostCommonSubstring = 1;
} else if (i == numberOfOccurenciesOfMostCommonSubstrings) {
numberOfSubstringsOfMostCommonSubstring++;
}
}
return new int[] {
numberOfUniqueSubstrings,
numberOfOccurenciesOfMostCommonSubstrings,
numberOfSubstringsOfMostCommonSubstring
};
}
later I am converting this to ArrayList and I iterate through whole list to find how many substrings and how many times these substrings are represented.
But after around 4 000 to 8 000 iterations I get java.lang.OutOfMemoryError Exception (which I expect since the process of this code takes over 2GB of memory at this point (I know, storing this amount of strings in memory can take up to 2TB in edge cases)). I tried using SHA1 hash as a key, which works, but it takes way more time, there are possible collisions and I think that there might be a better way to do this, but I can't think of any "better" optimization.
Thank you for any kind of help.
EDIT
There is some example input => output:
f("abcabc", 3) => 3 2 1
f("abcdefghijklmnopqrstuvwqyzab", 3) => 26 1 26
f("abcdefghijklmnopqrstuvwqyzab", 2) => 26 2 1
Ive changed the code to this:
public static int[] countSubstringOccurence(String text, int substringLength) {
int textLength = text.length();
int numberOfUniqueSubstrings = 0;
List<Integer> substrIndexes = new ArrayList<>();
for (int i = 0; i < (textLength - substringLength) + 1; i++) {
boolean doesNotExists = true;
for (int j = i + 1; j < (textLength - substringLength) + 1; j++) {
String actualSubstr = text.substring(i, i + substringLength);
String indexSubstr = text.substring(j, j + substringLength);
if (actualSubstr.equals(indexSubstr)) {
doesNotExists = false;
substrIndexes.add(j);
}
}
if (doesNotExists) {
numberOfUniqueSubstrings++;
substrIndexes.add(i);
}
}
LinkedHashMap<Integer, Integer> substrCountMap = new LinkedHashMap<>();
for (int i : substrIndexes) {
String substr = text.substring(i, i + substringLength);
int lastIndex = 0;
int count = 0;
while (lastIndex != -1) {
lastIndex = text.indexOf(substr, lastIndex);
if (lastIndex != -1) {
count++;
lastIndex += substr.length();
}
}
substrCountMap.put(i, count);
}
List<Integer> substrCountList = new ArrayList<>(substrCountMap.values());
int numberOfOccurenciesOfMostCommonSubstrings = 0;
int numberOfSubstringsOfMostCommonSubstring = 0;
for (int count : substrCountList) {
if (count > numberOfOccurenciesOfMostCommonSubstrings) {
numberOfOccurenciesOfMostCommonSubstrings = count;
numberOfSubstringsOfMostCommonSubstring = 1;
} else if (count == numberOfOccurenciesOfMostCommonSubstrings) {
numberOfSubstringsOfMostCommonSubstring++;
}
}
return new int[] {
numberOfUniqueSubstrings,
numberOfOccurenciesOfMostCommonSubstrings,
numberOfSubstringsOfMostCommonSubstring
};
}
this code does not crash, its just really, really slow (I guess its at least O(2n^2)). Can anyone think of a faster way?
It would be great if it could fit under 1GB RAM and under 15 minutes on a CPU equal to i3-3xxx. I am done for today.
Run it on Java 6. Not kidding!
Java 6 substring does NOT copy the characters, but only the reference, the index and the length.
just use StrinsgTokenizer class and extract each word.Then store each word in an array of String type of size given by the method <object name>.countTokens();
then you can easily calculate the frequencies of the given word
I had a coding interview over the phone and was asked this question:
Given a String (for example):
"aksdbaalaskdhfbblajdfhacccc aoudgalsaa bblisdfhcccc"
and an expression (for example):
"a+b+c-"
where:
+: means the char before it is repeated 2 times
-: means the char before it is repeated 4 times
Find the number of times the given expression appears in the string with the operands occurring non continuously and continuously.
The above expression occurs 4 times:
1) aksdbaalaskdhfbblajdfhacccc aoudgalsaa bblisdfhcccc
^^ ^^ ^^^^
aa bb cccc
2) aksdbaalaskdhfbblajdfhacccc aoudgalsaa bblisdfhcccc
^^ ^^ ^^^^
aa bb cccc
3) aksdbaalaskdhfbblajdfhacccc aoudgalsaa bblisdfhcccc
^^ ^^ ^^^^
aa bb cccc
4) aksdbaalaskdhfbblajdfhacccc aoudgalsaa bblisdfhcccc
^^ ^^ ^^^^
aa bb cccc
I had no idea how to do it. I started doing an iterative brute force method with lots of marking of indices but realized how messy and hard that would to code half way through:
import java.util.*;
public class Main {
public static int count(String expression, String input) {
int count = 0;
ArrayList<char[]> list = new ArrayList<char[]>();
// Create an ArrayList of chars to iterate through the expression and match to string
for(int i = 1; i<expression.length(); i=i+2) {
StringBuilder exp = new StringBuilder();
char curr = expression.charAt(i-1);
if(expression.charAt(i) == '+') {
exp.append(curr).append(curr);
list.add(exp.toString().toCharArray());
}
else { // character is '-'
exp.append(curr).append(curr).append(curr).append(curr);
list.add(exp.toString().toCharArray());
}
}
char[] inputArray = input.toCharArray();
int i = 0; // outside pointer
int j = 0; // inside pointer
while(i <= inputArray.length) {
while(j <= inputArray.length) {
for(int k = 0; k< list.size(); k++) {
/* loop through
* all possible combinations in array list
* with multiple loops
*/
}
j++;
}
i++;
j=i;
}
return count;
}
public static void main(String[] args) {
String expression = "a+b+c-";
String input = "aaksdbaalaskdhfbblajdfhacccc aoudgalsaa bblisdfhcccc";
System.out.println("The expression occurs: "+count(expression, input)+" times");
}
}
After spending a lot of time doing it iteratively he mentioned recursion and I still couldn't see a clear way doing it recursively and I wasn't able to solve the question. I am trying to solve it now post-interview and am still not sure how to go about this question. How should I go about solving this problem? Is the solution obvious? I thought this was a really hard question for a coding phone interview.
Non-recursion algorithm that requires O(m) space and operates in O(n*m), where m is number of tokens in query:
#Test
public void subequences() {
String input = "aabbccaacccccbbd";
String query = "a+b+";
// here to store tokens of a query: e.g. {a, +}, {b, +}
char[][] q = new char[query.length() / 2][];
// here to store counts of subsequences ending by j-th token found so far
int[] c = new int[query.length() / 2]; // main
int[] cc = new int[query.length() / 2]; // aux
// tokenize
for (int i = 0; i < query.length(); i += 2)
q[i / 2] = new char[] {query.charAt(i), query.charAt(i + 1)};
// init
char[] sub2 = {0, 0}; // accumulator capturing last 2 chars
char[] sub4 = {0, 0, 0, 0}; // accumulator capturing last 4 chars
// main loop
for (int i = 0; i < input.length(); i++) {
shift(sub2, input.charAt(i));
shift(sub4, input.charAt(i));
boolean all2 = sub2[1] != 0 && sub2[0] == sub2[1]; // true if all sub2 chars are same
boolean all4 = sub4[3] != 0 && sub4[0] == sub4[1] // true if all sub4 chars are same
&& sub4[0] == sub4[2] && sub4[0] == sub4[3];
// iterate tokens
for (int j = 0; j < c.length; j++) {
if (all2 && q[j][1] == '+' && q[j][0] == sub2[0]) // found match for "+" token
cc[j] = j == 0 // filling up aux array
? c[j] + 1 // first token, increment counter by 1
: c[j] + c[j - 1]; // add value of preceding token counter
if (all4 && q[j][1] == '-' && q[j][0] == sub4[0]) // found match for "-" token
cc[j] = j == 0
? c[j] + 1
: c[j] + c[j - 1];
}
if (all2) sub2[1] = 0; // clear, to make "aa" occur in "aaaa" 2, not 3 times
if (all4) sub4[3] = 0;
copy(cc, c); // copy aux array to main
}
}
System.out.println(c[c.length - 1]);
}
// shifts array 1 char left and puts c at the end
void shift(char[] cc, char c) {
for (int i = 1; i < cc.length; i++)
cc[i - 1] = cc[i];
cc[cc.length - 1] = c;
}
// copies array contents
void copy(int[] from, int[] to) {
for (int i = 0; i < from.length; i++)
to[i] = from[i];
}
The main idea is to catch chars from the input one by one, holding them in 2- and 4-char accumulators and check if any of them match some tokens of the query, remembering how many matches have we got for sub-queries ending by these tokens so far.
Query (a+b+c-) is splitted into tokens (a+, b+, c-). Then we collect chars in accumulators and check if they match some tokens. If we find match for first token, we increment its counter by 1. If we find match for another j-th token, we can create as many additional subsequences matching subquery composed of tokens [0...j], as many of them now exist for subquery composed of tokens [0... j-1], because this match can be appended to every of them.
For example, we have:
a+ : 3 (3 matches for a+)
b+ : 2 (2 matches for a+b+)
c- : 1 (1 match for a+b+c-)
when cccc arrives. Then c- counter should be increased by b+ counter value, because so far we have 2 a+b+ subsequences and cccc can be appended to both of them.
Let's call the length of the string n, and the length of the query expression (in terms of the number of "units", like a+ or b-) m.
It's not clear exactly what you mean by "continuously" and "non-continuously", but if "continuously" means that there can't be any gaps between query string units, then you can just use the KMP algorithm to find all instances in O(m+n) time.
We can solve the "non-continuous" version in O(nm) time and space with dynamic programming. Basically, what we want to compute is a function:
f(i, j) = the number of occurrences of the subquery consisting of the first i units
of the query expression, in the first j characters of the string.
So with your example, f(2, 41) = 2, since there are 2 separate occurrences of the subpattern a+b+ in the first 41 characters of your example string.
The final answer will then be f(n, m).
We can compute this recursively as follows:
f(0, j) = 0
f(i, 0) = 0
f(i > 0, j > 0) = f(i, j-1) + isMatch(i, j) * f(i-1, j-len(i))
where len(i) is the length of the ith unit in the expression (always 2 or 4) and isMatch(i, j) is a function that returns 1 if the ith unit in the expression matches the text ending at position j, and 0 otherwise. For example, isMatch(15, 2) = 1 in your example, because s[14..15] = bb. This function takes just constant time to run, because it never needs to check more than 4 characters.
The above recursion will already work as-is, but we can save time by making sure that we only solve each subproblem once. Because the function f() depends only on its 2 parameters i and j, which range between 0 and m, and between 0 and n, respectively, we can just compute all n*m possible answers and store them in a table.
[EDIT: As Sasha Salauyou points out, the space requirement can in fact be reduced to O(m). We never need to access values of f(i, k) with k < j-1, so instead of storing m columns in the table we can just store 2, and alternate between them by always accessing column m % 2.]
Wanted to try it for myself and figured I could then share my solution as well. The parse method obviously has issues when there is indeed a char 0 in the expression (although that would probably be the bigger issue itself), the find method will fail for an empty needles array and I wasn't sure if ab+c- should be considered a valid pattern (I treat it as such). Note that this covers only the non-continous part so far.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Matcher {
public static void main(String[] args) {
String haystack = "aksdbaalaskdhfbblajdfhacccc aoudgalsaa bblisdfhcccc";
String[] needles = parse("a+b+c-");
System.out.println("Needles: " + Arrays.toString(needles));
System.out.println("Found: " + find(haystack, needles, 0));
needles = parse("ab+c-");
System.out.println("Needles: " + Arrays.toString(needles));
System.out.println("Found: " + find(haystack, needles, 0));
}
private static int find(String haystack, String[] needles, int i) {
String currentNeedle = needles[i];
int pos = haystack.indexOf(currentNeedle);
if (pos < 0) {
// Abort: Current needle not found
return 0;
}
// Current needle found (also means that pos + currentNeedle.length() will always
// be <= haystack.length()
String remainingHaystack = haystack.substring(pos + currentNeedle.length());
// Last needle?
if (i == needles.length - 1) {
// +1: We found one match for all needles
// Try to find more matches of current needle in remaining haystack
return 1 + find(remainingHaystack, needles, i);
}
// Try to find more matches of current needle in remaining haystack
// Try to find next needle in remaining haystack
return find(remainingHaystack, needles, i) + find(remainingHaystack, needles, i + 1);
}
private static String[] parse(String expression) {
List<String> searchTokens = new ArrayList<String>();
char lastChar = 0;
for (int i = 0; i < expression.length(); i++) {
char c = expression.charAt(i);
char[] chars;
switch (c) {
case '+':
// last char is repeated 2 times
chars = new char[2];
Arrays.fill(chars, lastChar);
searchTokens.add(String.valueOf(chars));
lastChar = 0;
break;
case '-':
// last char is repeated 4 times
chars = new char[4];
Arrays.fill(chars, lastChar);
searchTokens.add(String.valueOf(chars));
lastChar = 0;
break;
default:
if (lastChar != 0) {
searchTokens.add(String.valueOf(lastChar));
}
lastChar = c;
}
}
return searchTokens.toArray(new String[searchTokens.size()]);
}
}
Output:
Needles: [aa, bb, cccc]
Found: 4
Needles: [a, bb, cccc]
Found: 18
How about preprocessing aksdbaalaskdhfbblajdfhacccc aoudgalsaa bblisdfhcccc?
This become a1k1s1d1b1a2l1a1s1k1d1h1f1b2l1a1j1d1f1h1a1c4a1o1u1d1g1a1l1s1a2b2l1i1s1d1f1h1c4
Now find occurrences of a2, b2, c4.
Tried it code below but right now it gives only first possible match based of depth first.
Need to be changed to do all possible combination instead of just first
import java.util.ArrayList;
import java.util.List;
public class Parsing {
public static void main(String[] args) {
String input = "aksdbaalaskdhfbblajdfhacccc aoudgalsaa bblisdfhcccc";
System.out.println(input);
for (int i = 0; i < input.length(); i++) {
System.out.print(i/10);
}
System.out.println();
for (int i = 0; i < input.length(); i++) {
System.out.print(i%10);
}
System.out.println();
List<String> tokenisedSearch = parseExp("a+b+c-");
System.out.println(tokenisedSearch);
parse(input, 0, tokenisedSearch, 0);
}
public static boolean parse(String input, int searchFromIndex, List<String> tokensToSeach, int currentTokenIndex) {
if(currentTokenIndex >= tokensToSeach.size())
return true;
String token = tokensToSeach.get(currentTokenIndex);
int found = input.indexOf(token, searchFromIndex);
if(found >= 0) {
System.out.println("Found at Index "+found+ " Token " +token);
return parse(input, searchFromIndex+1, tokensToSeach, currentTokenIndex+1);
}
return false;
}
public static List<String> parseExp(String exp) {
List<String> list = new ArrayList<String>();
String runningToken = "";
for (int i = 0; i < exp.length(); i++) {
char at = exp.charAt(i);
switch (at) {
case '+' :
runningToken += runningToken;
list.add(runningToken);
runningToken = "";
break;
case '-' :
runningToken += runningToken;
runningToken += runningToken;
list.add(runningToken);
runningToken = "";
break;
default :
runningToken += at;
}
}
return list;
}
}
Recursion may be the following (pseudocode):
int search(String s, String expression) {
if expression consists of only one token t /* e. g. "a+" */ {
search for t in s
return number of occurrences
} else {
int result = 0
divide expression into first token t and rest expression
// e. g. "a+a+b-" -> t = "a+", rest = "a+b-"
search for t in s
for each occurrence {
s1 = substring of s from the position of occurrence to the end
result += search(s1, rest) // search for rest of expression in rest of string
}
return result
}
}
Applying this to entire string, you'll get number of non-continuous occurrences. To get continuous occurrences, you don't need recursion at all--just transform expression into string and search by iteration.
If you convert the search string first with a simple parser/compiler so a+ becomes aa etc. then you can simply take this string and run a regular expression match against your hay stack. (Sorry, I'm no Java coder so can't deliver any real code but it is not really difficult)
I'm not to sure how to use character math. In my program, i have a character array and i have to change the elements of the array, so that its the opposite of the character entered by the user. Example 'a' to 'z'. i guess i can change each element in the array, but that would take forever and would be a waste of time. So far i have tried nothing, i just don't know where to start.
import java.util.*;
public class SecretCodeMachine
{
public static void main(String[]args)
{
SecretCodeMachine a = new SecretCodeMachine();
Scanner in = new Scanner (System.in);
String input = in.nextLine();
String print = a.encodeMessage(input);
System.out.println(print);
}
public String encodeMessage(String pass)
{
char[] j = pass.toCharArray();
String b = new String(j);
return b;
}
}
I have written the encodingMessage() method where all that code would be, im just not sure how i would approach this. Would i most likely use some type of loop?
The simplest solution would be to create a lookup table of valid input characters and what the output character should be. This can be done with either a map or array, that is up to you. Then for each character, you would look it up in the table and place the output character into the new string.
But if you really need to use character math, which I can only assume meaning, converting the character to its corresponding ASCII int value, then doing some math to result in the correct int value of the resulting character. This will be much more complex, but it can be done.
You can condition on whether it is in the first half of the alphabet or the second half, and do arithmetic with characters directly.
import java.util.*;
public class SecretCodeMachine
{
public static void main(String[]args)
{
SecretCodeMachine a = new SecretCodeMachine();
Scanner in = new Scanner (System.in);
String input = in.nextLine();
String print = a.encodeMessage(input);
System.out.println(print);
}
public String encodeMessage(String pass)
{
char[] j = pass.toCharArray();
for (int i = 0; i < j.length; i++) {
// Lower case
if (j[i] >= 'a' && j[i] <= 'z') {
if (j[i] - 'a' <= 13) j[i] = (char) ('z' - (j[i] - 'a'));
else j[i] = (char) ('a' + ('z' - j[i]));
}
// Upper Case
else {
if (j[i] - 'A' <= 13) j[i] = (char) ('Z' - (j[i] - 'A'));
else j[i] = (char) ('A' + ('Z' - j[i]));
}
}
String b = new String(j);
return b;
}
}
this will work for all lowercase and here is a link to the ASCII Table for your reference
for(int i = 0; i < j.length ; i ++){
int f = j[i];
int g = f - 97;
int h = 25 - g * 2;
j[i] += h;
}
I'm stumped on how to convert 3 letters and 3 numbers to ascii and increment them by one...it's the old next-license-plate problem. Can anyone give me a nudge in the right direction?
This problem actually have real applications. I wrote an account number generator that works just like this. I modified it to your format. Here you go,
public class LicenseNumber {
int numericSum;
int letterSum;
public LicenseNumber() {
numericSum = letterSum = 0;
}
public LicenseNumber(String number) {
if (!number.matches("^[A-Za-z]{3}[0-9]{3}$"))
throw new IllegalArgumentException("Number doesn't match license format");
numericSum = Integer.valueOf(number.substring(3));
letterSum = value(number, 0) * 26 * 26 + value(number, 1) * 26 +
value(number, 2);
}
public void increment() {
increment(1);
}
public void increment(int inc) {
numericSum += inc;
if (numericSum >= 1000) {
letterSum += numericSum/1000;
numericSum %= 1000;
}
}
public String toString() {
char[] letters = new char[3];
int n = letterSum;
for (int i = 0; i < 3; i++) {
letters[2-i] = (char)('A' + (n%26));
n /= 26;
}
return new String(letters) + String.format("%03d", numericSum);
}
private int value(String s, int index) {
return Character.toUpperCase(s.charAt(index)) - 'A';
}
/**
* Example
*/
public static void main(String[] args) {
LicenseNumber lic = new LicenseNumber("ABC999");
for (int i=0; i < 100; i++) {
lic.increment(500);
System.out.println(lic);
}
}
}
String str = "abc123"
String newstr = "";
for(int i=0; i<str.length(); i++) {
newstr += (char) (str.charAt(i) + 1);
}
// newstr now is "bcd234"
Note that this does not handle the characters 'z','Z' or '9' the way you would want. But it should give you a start.
Also note that using StringBuilder to create newstr would be more efficient.
I guess,
char c='A';
int no=97;
System.out.println( (++c) + " " + (char)++no);
You can do this by converting your String of letters and numbers to a char[]. Once you have done that you can iterate over the array and ++ each.
You're making strings like this: "AAA000", "AAA001", ..., "AAA999", "AAB000", ..., "ZZZ999", right?
Think of it like a number system where the different columns don't use the same number of digits. So where our numbers are 10-10-10-10, your numbers are 26-26-26-10-10-10. Use an underlying integer which you increment, then convert to letters and digits by dividing and taking the modulo successively by 10, 10, 10, 26, 26, 26.
To convert a license plate to its underlying integer, multiply out the letter position (A == 0, B == 1, etc) by the proper power of 26, and the digits by the proper power of 10, and add them all together.
An easy way to generate plate numbers would be to have an integer variable which gets incremented and three integer variables corresponding to the letters, something like this, please modify where appropriate. One trick is to use String.format which seamlessly converts between an integer and its char counterpart (you can also use casts.)
class plateGenerator {
int minLetter = "A".charAt(0);
int maxLetter = "Z".charAt(0);
int curLetter1 = minLetter;
int curLetter2 = minLetter;
int curLetter3 = minLetter;
int number = 0;
public String generatePlate() {
String plate = String.format("%c%c%c-%03d",curLetter1,
curLetter2,curLetter3,number);
increment();
return plate;
}
private void increment() {
number++;
if (number == 1000) {
number = 0;
curLetter1++;
}
if (curLetter1 > maxLetter) {
curLetter1 = minLetter;
curLetter2++;
}
if (curLetter2 > maxLetter) {
curLetter2 = minLetter;
curLetter3++;
}
if (curLetter3 > maxLetter) {
curLetter3 = minLetter;
number++;
}
}
public static void main(String[] args) {
plateGenerator pg = new plateGenerator();
for (int i = 0; i < 50000; i++) {
System.out.println(pg.generatePlate());
}
}
}
I haven't seen any code samples for general solutions for incrementing alphanumeric strings so I though I'd post mine.
This takes a string of any length with any ordering of alpha numeric characters, converts them to upper case and increments it by one (as if it were base 26). It also throws an exception if the numbers wrap. Its really up to you if wrapping makes sense...
private static string IncrementAlphaNumericString(string alphaNumericString)
{
char[] an = alphaNumericString.ToCharArray();
int i = an.Length - 1;
while (true)
{
if (i <= 0)
throw new Exception("Maxed out number!!!");
an[i]++;
if (an[i] - 1 == '9')
{
an[i] = 'A';
}
if (an[i] - 1 == 'Z')
{
an[i] = '0';
i--;
continue;
}
return new string(an);
}
}