Converting alphanumeric to ascii and incrementing - java

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

Related

Pancake Sorting with a Twist (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]));
}

Credit card validator , calling method doesn't work

I'm relatively new to java and am trying to break my code down as much as possible. This question is really on how to organize methods to work together
My credit card validator works if checkSum() code is written in the validateCreditCard() method. I think it's weird 'cause it works when called by the checkDigitControl() method
I used these sources for the program's logic:
To Check ~ https://www.creditcardvalidator.org/articles/luhn-algorithm
To Generate ~ https://en.wikipedia.org/wiki/Luhn_mod_N_algorithm
Here's my code(I apologize in advance if it's rather clumsy)
public class CreditCards {
public static void main(String[] args) {
long num;
num = genCreditCard();
boolean bool = validateCreditCard(num);
}
// Validity Check
public static boolean validateCreditCard(long card) {
String number = card+"";
String string=null;
int i;
for(i=0; i<number.length()-1; i++) {//Populate new string, leaving out last digit.
string += number.charAt(i)+"";
}
String checkDigit = number.charAt(i)+"";// Stores check digit.
long sum = checkSum(string);// Program works if this line is swapped for the code below(from checkSum)
//**********************************************************************
// int[] digits = new int[number.length()];
// int lastIndex = digits.length-1;
// int position=2; int mod=10;
// int sum=0;
//
// for(int j=lastIndex; j>=0; j--) {// Populate array in REVERSE
// digits[j] = Integer.parseInt(number.charAt(j)+"");
// digits[j] *= ( (position%2 == 0) ? 2: 1 );// x2 every other digit FROM BEHIND
// position++;
//
// digits[j] = ( (digits[j] > 9) ? (digits[j] / mod)+(digits[j] % mod) : digits[j] );//Sums integers of double-digits
// sum += digits[j];
// }
//**********************************************************************
sum *= 9;
string = sum+"";
string = string.charAt(string.length()-1)+"";// Last digit of result.
return (string.equals(checkDigit));
}
public static long genCreditCard() {
String number = "34";// American Express(15 digits) starts with 34 or 37
for(int i=0; i<12; i++)
number += (int)(Math.random() * 10) + "";// Add 12 random digits 4 base.
number += checkDigitControl(number);// Concat the check digit.
System.out.println(number);
return Long.parseLong(number);
}
// Algorithm to calculate the last/checkSum digit.
public static int checkDigitControl(String number) {
int i;
for(i=0; i<5; i++)
++i;
int sum = checkSum(number);
return 10 - sum%10;// Returns number that makes checkSum a multiple of 10.
}
public static int checkSum(String number) {
int[] digits = new int[number.length()];
int lastIndex = digits.length-1;
int position=2; int mod=10;
int sum=0;
for(int j=lastIndex; j>=0; j--) {// Populate array in REVERSE
digits[j] = Integer.parseInt(number.charAt(j)+"");
digits[j] *= ( (position%2 == 0) ? 2: 1 );// x2 every other digit FROM BEHIND
position++;
digits[j] = ( (digits[j] > 9) ? (digits[j] / mod)+(digits[j] % mod) : digits[j] );//Sums integers of double-digits
sum += digits[j];
}
return sum;
}
}
Thx in advance, sorry if this isn't the right format; it's also my 1st Stackoverflow post ¯\_(ツ)_/¯
You are initializing the variable string with null value:
String string=null;
And in the following for you are adding every char of the card number to this string.
for(i=0; i<number.length()-1; i++) {
string += number.charAt(i)+"";
}
But this will result in the variable string to be null + cardnumbers, because you didn't initialize the String string, and the value null is converted to the string "null" (Concatenating null strings in Java)
This will fix you code:
String string = new String();
Note, this code:
for(i=0; i<number.length()-1; i++) {
string += number.charAt(i)+"";
}
can be easily replace by this line that does the same thing:
number = number.substring(0, number.length() -1);
If you switch to this code just pass number to checkSum method

Java: Adding Digits Of A String

I have the correct code, I found an answer long ago, however I still don't understand why it works.
class Main {
public static void main(String[] args) {
System.out.println(D5PSum(10));
}
private static int D5PSum(int number) {
String n = Integer.toString(number);
int sum = 0;
for (int i = 0; i < n.length(); i++) {
// (1) WHY DOES THIS NOT WORK
//sum += Integer.parseInt(number.charAt(i));
// (2) MORE IMPORTANTLY WHY DOES THIS WORK
char c = n.charAt(i);
sum += (c-'0');
// (3) WHAT IN THE WORLD IS c-'0'
}
return sum;
}
}
// (1) WHY DOES THIS NOT WORK
because Integer.parseInt(...); is expecting a string as parameter not a char
// (2) MORE IMPORTANTLY WHY DOES THIS WORK
char c = n.charAt(i);
any char is nothing else as an integer mapped to a table of symbols...(ASCII table for example) so this (c - '0') is just another valid mathematical operation
charAt is not a valid method of the primitive type int.
'0' is the character 0, and the character encoding set that Java uses has 0 to 9 in a consecutive block. Therefore c - '0' yields the position of c in that consecutive block which is therefore the value of the digit. (Actually this sort of thing is idiomatic C - goes right back to the 1960s).
You should first convert String to Int.. Please check the below code:
class MainClass {
public static void main(String[] args) {
System.out.println(D5PSum(11));
}
private static int D5PSum(int number) {
String n = Integer.toString(number);
System.out.println(n);
int sum = 0;
for (int i = 0; i < n.length(); i++) {
// (1) WHY DOES THIS NOT WORK
String str = String.valueOf(n.charAt(i));
sum += Integer.parseInt(str);
// (2) MORE IMPORTANTLY WHY DOES THIS WORK
// char c = n.charAt(i);
// sum += (c-'0');
// (3) WHAT IN THE WORLD IS c-'0'
}
return sum;
}
}
1
It doesnt work because Integer.parseInt takes a String and String.charAt returns a char(actar). Integer.parseInt (Character.toString(n.charAt(i))) would Work.
2/3
A char represents a number between 0 and 65535. EACH digit-characters (0-9) has a number in that range which depends on the charset. All digits are typically in a row, for example the character 0 has the value 48, 1 49 and 9 57. So ich you want to know the digit value of a char you simply subtract the character value of 0 from your character. That is the Line c-'0'
// (1) WHY DOES THIS NOT WORK
//sum += Integer.parseInt(number.charAt(i));
number is a variable of primitive data type "int" so number.charAt(i) won't work.
// (2) MORE IMPORTANTLY WHY DOES THIS WORK
char c = n.charAt(i);
n is an instance of String and we are getting the character at i th position in the n string
sum += (c-'0');
// (3) WHAT IN THE WORLD IS c-'0'
for every character there is an ascii code assigned. '0' = 48, 'c' = 99. That's the reason why it works here. when 'c'-'0' is executed, it's equivalent to 99-48
Why convert to a string in the first place? The simplest and fastest way to solve this is without deviation to strings:
private static int D5PSum(int number) {
int v = number, sum = 0;
while (v != 0) {
sum += v % 10;
v /= 10;
}
return sum;
}
If you want your code (the part which does not works to work then do this).
class Main {
public static void main(String[] args) {
System.out.println(D5PSum(10));
}
private static int D5PSum(int number) {
String n = Integer.toString(number);
int sum = 0;
for (int i = 0; i < n.length(); i++) {
sum += Integer.parseInt(n.charAt(i)+"");
}
return sum;
}
}
To get sum of the digits of a string str:
int sum = str.chars().map(Character::getNumericValue).sum();

Getting a list of binary numbers composing a number

In Java, having a number like 0b1010, I would like to get a list of numbers "composing" this one: 0b1000 and 0b0010 in this example: one number for each bit set.
I'm not sure about the best solution to get it. Do you have any clue ?
Use a BitSet!
long x = 0b101011;
BitSet bs = BitSet.valueOf(new long[]{x});
for (int i = bs.nextSetBit(0); i >=0 ; i = bs.nextSetBit(i+1)) {
System.out.println(1 << i);
}
Output:
1
2
8
32
If you really want them printed out as binary strings, here's a little hack on the above method:
long x = 0b101011;
char[] cs = new char[bs.length()];
Arrays.fill(cs, '0');
BitSet bs = BitSet.valueOf(new long[]{x});
for (int i = bs.nextSetBit(0); i >=0 ; i = bs.nextSetBit(i+1)) {
cs[bs.length()-i-1] = '1';
System.out.println(new String(cs)); // or whatever you want to do with this String
cs[bs.length()-i-1] = '0';
}
Output:
000001
000010
001000
100000
Scan through the bits one by one using an AND operation. This will tell you if a bit at one position is set or not. (https://en.wikipedia.org/wiki/Bitwise_operation#AND). Once you have determined that some ith-Bit is set, make up a string and print it. PSEUDOCODE:
public static void PrintAllSubbitstrings(int number)
{
for(int i=0; i < 32; i++) //32 bits maximum for an int
{
if( number & (1 << i) != 0) //the i'th bit is set.
{
//Make up a bitstring with (i-1) zeroes to the right, then one 1 on the left
String bitString = "1";
for(int j=0; j < (i-1); j++) bitString += "0";
System.out.println(bitString);
}
}
}
Here is a little test that works for me
public static void main(String[] args) {
int num = 0b1010;
int testNum = 0b1;
while(testNum < num) {
if((testNum & num) >0) {
System.out.println(testNum + " Passes");
}
testNum *= 2;
}
}

Decimal to Binary without using in-built functions (like parseInt, Math.pow), etc

I need to create a program to take an input and convert it into binary output. I cannot use in-built functions such as (parseInt, Math.pow, etc.) to do this. I am stuck and need help. This is what I have so far, spread out across 2 java files.
Driver class:
import java.util.*;
public class Driver {
public Driver(){
}
public static void main(String[] args) {
Driver drive = new Driver();
// scanner to read in data from the user
Scanner scanner = new Scanner(System.in);
// instance of the solver class
Solver mySolver = new Solver();
// read in the first number
System.out.print("Enter a number to convert to binary: ");
char [] val1 = scanner.nextLine().toCharArray();
// call solver class method to obtain the number of bits
int numBits = mySolver.howManyBits(val1);
// use the number of bits and the input to get the binary representation
char [] binaryVal1 = mySolver.stringToBinary(val1, numBits);
// print the results
System.out.println(new String(binaryVal1));
// read in the arithmetic expression
System.out.print("Enter an arithmetic expression to convert to binary: ");
char [] val2 = scanner.nextLine().toCharArray();
// call the solver class to solve the expression
char [] result2 = mySolver.solveExpression(val2);
// print the results
System.out.println(new String(result2));
scanner.close();
}
}
Solver class:
import java.util.*;
public class Solver{
private int[] powersOf2;
public Solver() {
// Constructor method
int numPowersOf2 = 16;
powersOf2 = new int[numPowersOf2];
int exponent=1;
for(int count = 1; count <= numPowersOf2; count++){
exponent *= 2;
powersOf2[count] = exponent;
}
}
public static void main(String[] args) {
// Main method for Solver class
Solver solve = new Solver();
}
public int howManyBits(char[] val1) {
// howManyBits method
int decimal = Integer.parseInt(new String(val1));
int logValue = (int) (Math.log(decimal)/Math.log(2));
int numBits = 0;
// Condition block to return number of bits.
if (logValue <= 3) {
numBits = 4;
}
else if (logValue <=7 && logValue > 3) {
numBits = 8;
}
else if (logValue <=15 && logValue > 7) {
numBits = 16;
}
System.out.println("Bits: " + numBits);
return numBits;
}
public char[] stringToBinary(char[] val1, int numBits) {
// stringToBinary method
int decimalNumber = Integer.parseInt(new String(val1));
char[] binaryVal1 = new char[numBits];
int remainder = 0;
for (int count = 0; decimalNumber > 0; count++) {
remainder = decimalNumber % 2;
decimalNumber /= 2;
char[] place = String.valueOf(remainder).toCharArray();
binaryVal1[count] = place[count];
System.out.println(binaryVal1[count]);
}
return binaryVal1;
}
public char[] twosComplement(char[] val1){
return val1;
}
public char[] solveExpression(char[] val2) {
// solveExpression method
return null;
}
}
Now I am quite confused about what do you mean by "built-in functions". In that case, is println one of them? or Scanner.nextInt? I think the word "built-in function" is not very clear. I think it maybe means the functions that has the word int.
My idea is that you continuously divide the decimal number by 2 and store the remainder. And then you display the remainders in reverse order. That means you are probably going to use a Stack. This is the best method I can think of:
Stack<Integer> remainders = new Stack<> ();
Scanner s = new Scanner (System.in);
int decimalNumber = s.nextInt();
while (decimalNumber >= 2) {
remainders.push(decimalNumber % 2);
decimalNumber /= 2;
}
remainders.push(decimalNumber);
StringBuilder builder = new StringBuilder ();
int size = remainders.size();
for (int i = 0 ; i < size ; i++) {
builder.append(remainders.pop());
}
System.out.println(builder);
P.S. Technically, functions are routines that are not in ny classes. Methods must be in one class. Which means in this case you can just use Integer.toBinaryString!
Just kidding, I know what you mean.
If you have learned about bit manipulation yet, then you can find the rightmost bit by doing a binary AND with 1 (x & 1), then right-shift the value using the unsigned right-shift operator (x >>> 1), and keep doing it until number is 0.
See The Oracle Java Tutorials Bitwise and Bit Shift Operators or the Wikipedia Bitwise operation.
Depending on whether you're allowed to use the StringBuilder class, here are two versions:
// Using StringBuilder
public static String toBinary(int number) {
StringBuilder buf = new StringBuilder();
do {
buf.append((number & 1) == 0 ? '0' : '1');
number >>>= 1;
} while (number != 0);
return buf.reverse().toString();
}
// Using character array
public static String toBinary(int number) {
char[] buf = new char[32];
int i = buf.length;
do {
buf[--i] = (number & 1) == 0 ? '0' : '1';
number >>>= 1;
} while (number != 0);
return new String(buf, i, buf.length - i);
}
Of course, you'll first have to parse a string to an integer, which is simple enough:
public static int toInt(String text) {
if (text.isEmpty())
throw new IllegalArgumentException();
int num = 0;
for (char c : text.toCharArray()) {
if (c < '0' || c > '9')
throw new IllegalArgumentException();
num = num * 10 + c - '0';
}
return num;
}
You can then combine them:
public static String toBinary(String text) {
return toBinary(toInt(text));
}

Categories