Pancake Sorting with a Twist (Java) - java

I am attempting to solve a version of a pancake sorting algorithm. In this problem I am given a string that is composed of any combination of characters A-F and has a maximum length of 6. For instance I may receive the String 'ACFE'. In this problem I am trying to use pancake sorting to fix the string to be in Alphabetical Order. So the above example would become 'ACEF'.
That is pretty simple and straightforward. Here is the catch: the characters in the input string can be Uppercase OR Lowercase. Whenever you flip characters in the string, the flipped characters switch case. So an uppercase A would become 'a'. The goal at the end is to flip the string into order and also have all of the characters in uppercase as well.
I have had no problem putting together the algorithm to solve the sorting part of the algorithm, but it is the part where I am trying to make sure that we aren't done flipping the characters until they are all uppercase that I am having trouble with and can't seem to solve.
To make things easier on myself, I have made a HashMap of Characters to Integers so that it is easier to sort the characters (we can just use an equivalent Integer value). I also break the string apart at the beginning into a char[] and put it in reverse order to make the algorithm easier for myself.
Here is the code I use to do everything:
private static final HashMap<Character, Integer> numericalEquivalent = new HashMap<>();
static {
numericalEquivalent.put('A', 6);
numericalEquivalent.put('B', 5);
numericalEquivalent.put('C', 4);
numericalEquivalent.put('D', 3);
numericalEquivalent.put('E', 2);
numericalEquivalent.put('F', 1);
numericalEquivalent.put('a', 6);
numericalEquivalent.put('b', 5);
numericalEquivalent.put('c', 4);
numericalEquivalent.put('d', 3);
numericalEquivalent.put('e', 2);
numericalEquivalent.put('f', 1);
}
private static int flip(char[] arr, int i, int numFlips) {
char temp;
int start = 0;
if (start < i) {
while (start < i) {
temp = (Character.isUpperCase(arr[start]) ? Character.toLowerCase(arr[start]) : Character.toUpperCase(arr[start]));
arr[start] = (Character.isUpperCase(arr[i]) ? Character.toLowerCase(arr[i]) : Character.toUpperCase(arr[i]));
arr[i] = temp;
start++;
i--;
}
numFlips++;
}
return numFlips;
}
private static int findMax(char[] arr, int n) {
int mi, i;
for (mi = 0, i = 0; i < n; ++i)
if (numericalEquivalent.get(arr[i]) > numericalEquivalent.get(arr[mi]))
mi = i;
return mi;
}
private static int getFlips (char[] pancakes) {
int n = pancakes.length;
int numFlips = 0;
for (int curr_size = n; curr_size > 1; --curr_size) {
int mi = findMax(pancakes, curr_size);
if (mi != curr_size - 1) {
numFlips = flip(pancakes, mi, numFlips);
if (!isSorted(pancakes))
numFlips = flip(pancakes, curr_size - 1, numFlips);
}
}
return numFlips;
}
private static boolean isSorted(char[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
if (numericalEquivalent.get(arr[i]) > numericalEquivalent.get(arr[i + 1]))
return false;
}
return true;
}
public static void main(String[] args) {
while(true) {
String input = scanner.nextLine();
if (input.equals("0")) break;
else System.out.println(getFlips(new StringBuilder(input).reverse().toString().toCharArray()));
}
}
My goal is to get back the minimum number of flips that it will take to flip the characters into order. How can I modify this code, though, to make sure it accounts for characters being lowercase and the need to make sure they all end up in Uppercase?

You can change the stop condition from if (!isSorted(pancakes)) to if (!isSortedAndUppercase(pancakes)) where isSortedAndUppercase(pancakes) is defined as:
private static boolean isSortedAndUppercase(char[] arr){
return isUpperCase(arr) && isSorted(arr);
}
private static boolean isUpperCase(char[] arr) {
String s = String.valueOf(arr);
return s.equals(s.toUpperCase());
}
and stop the search only when the stop condition is met.
Consider using Breadth-First Search for this task.
Side notes:
There is no need to map chars into integers. Try the following:
char[] chars = "ABCDEF".toCharArray();
for (int i = 0; i < chars.length; i++) {
System.out.println(chars[i] +" int value: "+(int)chars[i]);
System.out.println(Character.toLowerCase(chars[i]) +" int value: "+(int)Character.toLowerCase(chars[i]));
}

Related

How to swap digits in number?

I need to write function that gets 3 params(int num, int k, int nDigit).
The function get number and replace the digit inside the number in k index by nDigit.
for example:
int num = 5498
int k = 2
int nDigit= 3
the result is num = 5398
My question is how can I implement it?I undastand that the best way to convert the num to string and then just replace char on specific index by nDigit char.
But is there any way to implement it?Without
public int changeDigit(int num, int k, int nDigit){
k = pow(10,k);
double saved = num%k; // Save digits after
num = num - (num%(k*10)); //Get what's before k
return ((int) (num + (nDigit*k) + saved));
}
I won't do your homework for you, but here's some hints:
Convert integer to string:
String s = Integer.toString(1234);
Enumerating a string:
for (i = 0; i < s.length; i++)
{
char c = s.charAt(i);
}
String building (a little less efficient without the StringBuilder class)
char c = '1';
String s = "3";
String j = "";
j = j + c;
j = j + s; // j is now equal to "13"
String back to integer:
int val = Integer.parseInt("42");
You can use a StringBuilder. It's easier to see what you're doing and you don't need to perform mathematics, only adjust the characters in their positions. Then convert it back to int.
public class Main {
static int swapParams(int num, int k, int nDigit) {
StringBuilder myName = new StringBuilder(Integer.toString(num));
myName.setCharAt(k-1, Integer.toString(nDigit).charAt(0));
return Integer.parseInt(myName.toString());
}
public static void main(String[] args) {
System.out.println(swapParams(5498, 2, 3));
}
}
http://ideone.com/e4MF6m
You can do it like this:
public int func(int num, int k, int nDigit) {
String number = String.valueOf(num);
return Integer.parseInt(number.substring(0, k - 1) + nDigit + number.substring(k, number.length()));
}
This function takes the first characters of the number without the k'th number and adds the nDigit to it. Then it adds the last part of the number and returns it as an integer number.
This is my javascript solution.
const solution = numbers => { //declare a variable that will hold
the array el that is not strictly ascending let flawedIndex;
//declare a boolean variable to actually check if there is a flawed array el in the given array let flawed = false;
//iterate through the given array for(let i=0; i<numbers.length; i++) {
//check if current array el is greater than the next
if(numbers[i] > numbers[i+1])
{
//check if we already set flawed to true once.
//if flawed==true, then return that this array cannot be sorted
//strictly ascending even if we swap one elements digits
if(flawed) {
return false;
}
//if flawed is false, then set it to true and store the index of the flawed array el
else {
flawed = true;
flawedIndex = i;
}
}
}
//if flawed is still false after the end of the for loop, return true //where true = the array is sctrictly ascending if(flawed ==
false) return true;
//if flawed==true, that is there is an array el that is flawed if(flawed){
//store the result of calling the swap function on the digits of the flawed array el
let swapResult = swap(flawedIndex,numbers);
//if the swapresult is true, then return that it is ascending
if (swapResult == true) return true; }
//else return that its false return false; }
const swap = (flawIndex, numbers) => {
let num = numbers[flawIndex];
//convert the given array el to a string, and split the string based on '' let numToString = num.toString().split('');
//iterate through every digit from index 0 for(let i=0;
i<numToString.length; i++) {
//iterate from every digit from index 1
for(let j=i+1; j<numToString.length; j++) {
//swap the first index digit with every other index digit
let temp = numToString[i];
numToString[i] = numToString[j]
numToString[j] = temp;
console.log(numToString)
//check if the swapped number is lesser than the next number in the main array
//AND if it is greater than the previous el in the array. if yes, return true
let swappedNum = Number(numToString.join(''));
if(swappedNum < numbers[flawIndex + 1] && swappedNum > numbers[flawIndex-])
{
return true;
}
} } //else return false return false; }
console.log("the solution is ",solution([1, 3, 900, 10]))

Pair Palindrome

I have this code to find all pairs of string to form a palindrome. e.g) D: { AB, DEEDBA } => AB + DEEDBA -> YES and will be returned. Another example, { NONE, XENON } => NONE + XENON = > YES.
What would be running time of this ?
public static List<List<String>> pairPalindrome(List<String> D) {
List<List<String>> pairs = new LinkedList<>();
Set<String> set = new HashSet<>();
for (String s : D) {
set.add(s);
}
for (String s : D) {
String r = reverse(s);
for (int i = 0; i <= r.length(); i++) {
String prefix = r.substring(0, i);
if (set.contains(prefix)) {
String suffix = r.substring(i);
if (isPalindrom(suffix)) {
pairs.add(Arrays.asList(s, prefix));
}
}
}
}
return pairs;
}
private static boolean isPalindrom(String s) {
int i = 0;
int j = s.length() - 1;
char[] c = s.toCharArray();
while (i < j) {
if (c[i] != c[j]) {
return false;
}
i++;
j--;
}
return true;
}
private static String reverse(String s) {
char[] c = s.toCharArray();
int i = 0;
int j = c.length - 1;
while (i < j) {
char temp = c[i];
c[i] = c[j];
c[j] = temp;
i++;
j--;
}
return new String(c);
}
I'm going to take a few guesses here as I don't have much experience with Java.
First, isPalindrome is O(N) with the size of suffix string. Add operation to 'pairs' would probably be O(1).
Then, we have the for loop, it's O(N) with the length of r. Getting a substring I'd think is O(M) with the size of the substring. Checking if a hashmap contains a certain key, with a perfect hash function would be (IIRC) O(1), in your case we can assume O(lgN) (possibly). So, first for loop has O(NMlgK), where K is your hash table size, N is r's length and M is substring's length.
Finally we have the outmost for loop, it runs for each string in the string list, so that's O(N). Then, we reverse each of them. So for each of these strings we have another O(N) operation inside, with the other loop being O(NMlgK). So, overall complexity is O(L(N + NMlgK)), where L is the amount of strings you have. But, it'd reduce to O(LNMlgK). I'd like if someone verified or corrected my mistakes.
EDIT: Actually, substring length will at most be N, as the length of the entire string, so M is actually N. Now I'd probably say it's O(LNlgK).

Find all substrings that are palindromes

If the input is 'abba' then the possible palindromes are a, b, b, a, bb, abba.
I understand that determining if string is palindrome is easy. It would be like:
public static boolean isPalindrome(String str) {
int len = str.length();
for(int i=0; i<len/2; i++) {
if(str.charAt(i)!=str.charAt(len-i-1) {
return false;
}
return true;
}
But what is the efficient way of finding palindrome substrings?
This can be done in O(n), using Manacher's algorithm.
The main idea is a combination of dynamic programming and (as others have said already) computing maximum length of palindrome with center in a given letter.
What we really want to calculate is radius of the longest palindrome, not the length.
The radius is simply length/2 or (length - 1)/2 (for odd-length palindromes).
After computing palindrome radius pr at given position i we use already computed radiuses to find palindromes in range [i - pr ; i]. This lets us (because palindromes are, well, palindromes) skip further computation of radiuses for range [i ; i + pr].
While we search in range [i - pr ; i], there are four basic cases for each position i - k (where k is in 1,2,... pr):
no palindrome (radius = 0) at i - k
(this means radius = 0 at i + k, too)
inner palindrome, which means it fits in range
(this means radius at i + k is the same as at i - k)
outer palindrome, which means it doesn't fit in range
(this means radius at i + k is cut down to fit in range, i.e because i + k + radius > i + pr we reduce radius to pr - k)
sticky palindrome, which means i + k + radius = i + pr
(in that case we need to search for potentially bigger radius at i + k)
Full, detailed explanation would be rather long. What about some code samples? :)
I've found C++ implementation of this algorithm by Polish teacher, mgr Jerzy WaƂaszek.
I've translated comments to english, added some other comments and simplified it a bit to be easier to catch the main part.
Take a look here.
Note: in case of problems understanding why this is O(n), try to look this way:
after finding radius (let's call it r) at some position, we need to iterate over r elements back, but as a result we can skip computation for r elements forward. Therefore, total number of iterated elements stays the same.
Perhaps you could iterate across potential middle character (odd length palindromes) and middle points between characters (even length palindromes) and extend each until you cannot get any further (next left and right characters don't match).
That would save a lot of computation when there are no many palidromes in the string. In such case the cost would be O(n) for sparse palidrome strings.
For palindrome dense inputs it would be O(n^2) as each position cannot be extended more than the length of the array / 2. Obviously this is even less towards the ends of the array.
public Set<String> palindromes(final String input) {
final Set<String> result = new HashSet<>();
for (int i = 0; i < input.length(); i++) {
// expanding even length palindromes:
expandPalindromes(result,input,i,i+1);
// expanding odd length palindromes:
expandPalindromes(result,input,i,i);
}
return result;
}
public void expandPalindromes(final Set<String> result, final String s, int i, int j) {
while (i >= 0 && j < s.length() && s.charAt(i) == s.charAt(j)) {
result.add(s.substring(i,j+1));
i--; j++;
}
}
So, each distinct letter is already a palindrome - so you already have N + 1 palindromes, where N is the number of distinct letters (plus empty string). You can do that in single run - O(N).
Now, for non-trivial palindromes, you can test each point of your string to be a center of potential palindrome - grow in both directions - something that Valentin Ruano suggested.
This solution will take O(N^2) since each test is O(N) and number of possible "centers" is also O(N) - the center is either a letter or space between two letters, again as in Valentin's solution.
Note, there is also O(N) solution to your problem, based on Manacher's algoritm (article describes "longest palindrome", but algorithm could be used to count all of them)
I just came up with my own logic which helps to solve this problem.
Happy coding.. :-)
System.out.println("Finding all palindromes in a given string : ");
subPal("abcacbbbca");
private static void subPal(String str) {
String s1 = "";
int N = str.length(), count = 0;
Set<String> palindromeArray = new HashSet<String>();
System.out.println("Given string : " + str);
System.out.println("******** Ignoring single character as substring palindrome");
for (int i = 2; i <= N; i++) {
for (int j = 0; j <= N; j++) {
int k = i + j - 1;
if (k >= N)
continue;
s1 = str.substring(j, i + j);
if (s1.equals(new StringBuilder(s1).reverse().toString())) {
palindromeArray.add(s1);
}
}
}
System.out.println(palindromeArray);
for (String s : palindromeArray)
System.out.println(s + " - is a palindrome string.");
System.out.println("The no.of substring that are palindrome : "
+ palindromeArray.size());
}
Output:-
Finding all palindromes in a given string :
Given string : abcacbbbca
******** Ignoring single character as substring palindrome ********
[cac, acbbbca, cbbbc, bb, bcacb, bbb]
cac - is a palindrome string.
acbbbca - is a palindrome string.
cbbbc - is a palindrome string.
bb - is a palindrome string.
bcacb - is a palindrome string.
bbb - is a palindrome string.
The no.of substring that are palindrome : 6
I suggest building up from a base case and expanding until you have all of the palindomes.
There are two types of palindromes: even numbered and odd-numbered. I haven't figured out how to handle both in the same way so I'll break it up.
1) Add all single letters
2) With this list you have all of the starting points for your palindromes. Run each both of these for each index in the string (or 1 -> length-1 because you need at least 2 length):
findAllEvenFrom(int index){
int i=0;
while(true) {
//check if index-i and index+i+1 is within string bounds
if(str.charAt(index-i) != str.charAt(index+i+1))
return; // Here we found out that this index isn't a center for palindromes of >=i size, so we can give up
outputList.add(str.substring(index-i, index+i+1));
i++;
}
}
//Odd looks about the same, but with a change in the bounds.
findAllOddFrom(int index){
int i=0;
while(true) {
//check if index-i and index+i+1 is within string bounds
if(str.charAt(index-i-1) != str.charAt(index+i+1))
return;
outputList.add(str.substring(index-i-1, index+i+1));
i++;
}
}
I'm not sure if this helps the Big-O for your runtime, but it should be much more efficient than trying each substring. Worst case would be a string of all the same letter which may be worse than the "find every substring" plan, but with most inputs it will cut out most substrings because you can stop looking at one once you realize it's not the center of a palindrome.
I tried the following code and its working well for the cases
Also it handles individual characters too
Few of the cases which passed:
abaaa --> [aba, aaa, b, a, aa]
geek --> [g, e, ee, k]
abbaca --> [b, c, a, abba, bb, aca]
abaaba -->[aba, b, abaaba, a, baab, aa]
abababa -->[aba, babab, b, a, ababa, abababa, bab]
forgeeksskeegfor --> [f, g, e, ee, s, r, eksske, geeksskeeg,
o, eeksskee, ss, k, kssk]
Code
static Set<String> set = new HashSet<String>();
static String DIV = "|";
public static void main(String[] args) {
String str = "abababa";
String ext = getExtendedString(str);
// will check for even length palindromes
for(int i=2; i<ext.length()-1; i+=2) {
addPalindromes(i, 1, ext);
}
// will check for odd length palindromes including individual characters
for(int i=1; i<=ext.length()-2; i+=2) {
addPalindromes(i, 0, ext);
}
System.out.println(set);
}
/*
* Generates extended string, with dividors applied
* eg: input = abca
* output = |a|b|c|a|
*/
static String getExtendedString(String str) {
StringBuilder builder = new StringBuilder();
builder.append(DIV);
for(int i=0; i< str.length(); i++) {
builder.append(str.charAt(i));
builder.append(DIV);
}
String ext = builder.toString();
return ext;
}
/*
* Recursive matcher
* If match is found for palindrome ie char[mid-offset] = char[mid+ offset]
* Calculate further with offset+=2
*
*
*/
static void addPalindromes(int mid, int offset, String ext) {
// boundary checks
if(mid - offset <0 || mid + offset > ext.length()-1) {
return;
}
if (ext.charAt(mid-offset) == ext.charAt(mid+offset)) {
set.add(ext.substring(mid-offset, mid+offset+1).replace(DIV, ""));
addPalindromes(mid, offset+2, ext);
}
}
Hope its fine
public class PolindromeMyLogic {
static int polindromeCount = 0;
private static HashMap<Character, List<Integer>> findCharAndOccurance(
char[] charArray) {
HashMap<Character, List<Integer>> map = new HashMap<Character, List<Integer>>();
for (int i = 0; i < charArray.length; i++) {
char c = charArray[i];
if (map.containsKey(c)) {
List list = map.get(c);
list.add(i);
} else {
List list = new ArrayList<Integer>();
list.add(i);
map.put(c, list);
}
}
return map;
}
private static void countPolindromeByPositions(char[] charArray,
HashMap<Character, List<Integer>> map) {
map.forEach((character, list) -> {
int n = list.size();
if (n > 1) {
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
if (list.get(i) + 1 == list.get(j)
|| list.get(i) + 2 == list.get(j)) {
polindromeCount++;
} else {
char[] temp = new char[(list.get(j) - list.get(i))
+ 1];
int jj = 0;
for (int ii = list.get(i); ii <= list
.get(j); ii++) {
temp[jj] = charArray[ii];
jj++;
}
if (isPolindrome(temp))
polindromeCount++;
}
}
}
}
});
}
private static boolean isPolindrome(char[] charArray) {
int n = charArray.length;
char[] temp = new char[n];
int j = 0;
for (int i = (n - 1); i >= 0; i--) {
temp[j] = charArray[i];
j++;
}
if (Arrays.equals(charArray, temp))
return true;
else
return false;
}
public static void main(String[] args) {
String str = "MADAM";
char[] charArray = str.toCharArray();
countPolindromeByPositions(charArray, findCharAndOccurance(charArray));
System.out.println(polindromeCount);
}
}
Try out this. Its my own solution.
// Maintain an Set of palindromes so that we get distinct elements at the end
// Add each char to set. Also treat that char as middle point and traverse through string to check equality of left and right char
static int palindrome(String str) {
Set<String> distinctPln = new HashSet<String>();
for (int i=0; i<str.length();i++) {
distinctPln.add(String.valueOf(str.charAt(i)));
for (int j=i-1, k=i+1; j>=0 && k<str.length(); j--, k++) {
// String of lenght 2 as palindrome
if ( (new Character(str.charAt(i))).equals(new Character(str.charAt(j)))) {
distinctPln.add(str.substring(j,i+1));
}
// String of lenght 2 as palindrome
if ( (new Character(str.charAt(i))).equals(new Character(str.charAt(k)))) {
distinctPln.add(str.substring(i,k+1));
}
if ( (new Character(str.charAt(j))).equals(new Character(str.charAt(k)))) {
distinctPln.add(str.substring(j,k+1));
} else {
continue;
}
}
}
Iterator<String> distinctPlnItr = distinctPln.iterator();
while ( distinctPlnItr.hasNext()) {
System.out.print(distinctPlnItr.next()+ ",");
}
return distinctPln.size();
}
Code is to find all distinct substrings which are palindrome.
Here is the code I tried. It is working fine.
import java.util.HashSet;
import java.util.Set;
public class SubstringPalindrome {
public static void main(String[] args) {
String s = "abba";
checkPalindrome(s);
}
public static int checkPalindrome(String s) {
int L = s.length();
int counter =0;
long startTime = System.currentTimeMillis();
Set<String> hs = new HashSet<String>();
// add elements to the hash set
System.out.println("Possible substrings: ");
for (int i = 0; i < L; ++i) {
for (int j = 0; j < (L - i); ++j) {
String subs = s.substring(j, i + j + 1);
counter++;
System.out.println(subs);
if(isPalindrome(subs))
hs.add(subs);
}
}
System.out.println("Total possible substrings are "+counter);
System.out.println("Total palindromic substrings are "+hs.size());
System.out.println("Possible palindromic substrings: "+hs.toString());
long endTime = System.currentTimeMillis();
System.out.println("It took " + (endTime - startTime) + " milliseconds");
return hs.size();
}
public static boolean isPalindrome(String s) {
if(s.length() == 0 || s.length() ==1)
return true;
if(s.charAt(0) == s.charAt(s.length()-1))
return isPalindrome(s.substring(1, s.length()-1));
return false;
}
}
OUTPUT:
Possible substrings:
a
b
b
a
ab
bb
ba
abb
bba
abba
Total possible substrings are 10
Total palindromic substrings are 4
Possible palindromic substrings: [bb, a, b, abba]
It took 1 milliseconds

Split string into array by K?

I am trying to figure out how to split a string into an 2d array based on k.
I know how to split it into individual strings or by regex.
How do you go about splitting it like this;
String text = "thisismyp";
// Result (where k = 3):
char[][] = {
{'t','h','i'},
{'s','i','s'},
{'m','y','p'}
};
.{k} should work where you have to compose the regex yourself inserting the value of k into it.
The regex is:
(.{3})
Nice and simple. You can add case insensitivity, newline handling, etc, according to your use case.
I haven't tested it, so maybe you need to change a little bit, but I think that this will work:
public String[] split(String str, int k)
{
String[] a = new String[Math.ceil((double)str.length() / (double)k)];
for (int i = 0; i < str.length(); i += k)
{
a[i / k] = str.substring(i, Math.min(i + k, str.length()));
}
return a;
}
If you want it really as a char matrix, use something like this:
public char[][] split(String str, int k)
{
char[][] a = new char[Math.ceil((double)str.length() / (double)k)][0];
for (int i = 0; i < str.length(); i += k)
{
String part = str.substring(i, Math.min(i + k, str.length()));
a[i / k] = part.toCharArray();
}
return a;
}
If you don't want to use a regex you can brute-force it. Brute force is faster but in your case I wouldn't worry about performance. Still if anyone lands on this page and is not using a language with easy regex support; here is the fast Java implementation, embedded within a complete application you can compile and run.
import java.util.Arrays;
public class Split {
private static int K = 3;
/**
* Splits a string into a 2-D array of chars. An array or list of strings would
* be better, but <strong>the OP asked for an array of array of chars!!!
*/
public static char[][] split(String s) {
char[][] result = new char[(s.length() + (K-1)) / K][K];
int row = 0, col = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
result[row][col] = c;
if (col == K - 1) {row++; col = 0;} else col++;
}
return result;
}
// Sorry about the hideous copy/paste
public static void main(String[] args) {
System.out.println(Arrays.deepToString(split("")));
System.out.println(Arrays.deepToString(split("1")));
System.out.println(Arrays.deepToString(split("12")));
System.out.println(Arrays.deepToString(split("123")));
System.out.println(Arrays.deepToString(split("1234")));
System.out.println(Arrays.deepToString(split("12345")));
System.out.println(Arrays.deepToString(split("123456")));
System.out.println(Arrays.deepToString(split("1234567")));
System.out.println(Arrays.deepToString(split("12345678")));
System.out.println(Arrays.deepToString(split("123456789")));
System.out.println(Arrays.deepToString(split("1234567890")));
}
}

Converting alphanumeric to ascii and incrementing

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);
}
}

Categories