Base 26 as alphabetic using Java's Integer.toString() - java

So I just learned Integer.toString(int x, int radix); and thought it was pretty awesome since it makes base conversions super easy.
However, I'm trying to write with Base-26 phonetically (a - z) and noticed that Integer.toString() follows hexadecimal's example in that it begins numerically and then uses the alphabet (0 - p).
I already know how to do convert to Base-26 by hand, I don't need that code. But I'm wondering if there's a way to take advantage of Integer.toString() since it's pretty much already done all the heavy lifting.
Any ideas?

You can iterate over a char[] to shift the output from Integer.toString into the range you want.
public static String toAlphabeticRadix(int num) {
char[] str = Integer.toString(num, 26).toCharArray();
for (int i = 0; i < str.length; i++) {
str[i] += str[i] > '9' ? 10 : 49;
}
return new String(str);
}
Ideone Demo

No; the way that this method is implemented effectively guarantees that it starts from 0-9, then proceeds through a-f, then carries on should the radix exceed 16.
If you want to do this in your own way, then you will need to perform the offsets yourself.

Related

Is there an approach to finding the ASCII distance between two strings of 5 characters

I am trying to find a way to calculate and print the Ascii distance between a string from user input
Scanner scan = new Scanner(System.in);
System.out.print("Please enter a string of 5 uppercase characters:");
String userString = scan.nextLine();
and a randomly generated string
int leftLimit = 65; // Upper-case 'A'
int rightLimit = 90; // Upper-case 'Z'
int stringLength = 5;
Random random = new Random();
String randString = random.ints(leftLimit, rightLimit + 1)
.filter(i -> (i <= 57 || i >= 65) && (i <= 90 || i >= 97))
.limit(stringLength)
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
Is there a way to calculate the distance without having to separate each individual character from the two strings, comparing them and adding them back together?
Use Edit distance (Levenshtein distance)
You can
Implement your own edit distance based on the algorithm on wikipedia,
you can use an existing source code, for that look at rosetta code.
use an existing library like apache LevenshteinDistance
you can also check
Levenshtein Distance on stackoverflow
Streams are, well, as the name says, streams. They don't work very well unless you can define an operation strictly on the basis of one input: One element from a stream, without knowing its index or referring to the entire collection.
Here, that is a problem; after all, to operate on, say, the 'H' in your input, you need the matching character from your random code.
I'm not sure why you find 'separate each individual character, compare them, and add them back together' is so distasteful to you. Isn't that a pretty clean mapping from the problem description to instructions for your computer to run?
The alternative is more convoluted: You could attempt to create a mixed object that contains both the letter as well as its index, stream over this, and use the index to look up the character in the second string. Alternatively, you could attempt to create a mix object containing both characters (so, for inputs ABCDE and HELLO, an object containing both A and H), but you'd be writing far more code to get that set up, then the simple, no-streams way.
So, let's start with the simple way:
int difference = 0;
for (int i = 0; i < stringLength; i++) {
char a = inString.charAt(i);
char b = randomString.charAt(i);
difference += difference(a, b);
}
You'd have to write the difference method yourself - but it'd be a very very simple one-liner.
Trying to take two collections of some sort, and from them create a single stream where each element in the stream is matching elements from each collection (so, a stream of ["HA", "EB", "LC", "LD", "OE"]) is generally called 'zipping' (no relation to the popular file compression algorithm and product), and java doesn't really support it (yet?). There are some third party libraries that can do it, but given that the above is so simple I don't think zipping is what you're looking for here.
If you absolutely must, I guess i'd look something like:
// a stream of 0,1,2,3,4
IntStream.range(0, stringLength)
// map 0 to "HA", 1 to "EB", etcetera
.mapToObj(idx -> "" + inString.charAt(idx) + randomString.charAt(idx))
// map "HA" to the difference score
.mapToInt(x -> difference(x))
// and sum it.
.sum();
public int difference(String a) {
// exercise for the reader
}
Create an 2D array fill the array with distances - you can index directly into the 2D array to pull out the distance between the characters.
So one expression that sums up a set of array accesses.
Here is my code for this (ASCII distance) in MATLAB
function z = asciidistance(input0)
if nargin ~= 1
error('please enter a string');
end
size0 = size(input0);
if size0(1) ~= 1
error ('please enter a string');
end
length0 = size0(2);
rng('shuffle');
a = 32;
b = 127;
string0 = (b-a).*rand(length0,1) + a;
x = char(floor(string0));
z = (input0 - x);
ascii0 = sum(abs(z),'all');
ascii1 = abs(sum(z,'all'));
disp(ascii0);
disp(ascii1);
disp(ascii0/ascii1/length0);
end
This script also differentiates between the absolute ASCII distance on a per-character basis vs that on a per-string basis, thus resulting in two integers returned for the ASCII distance.
I have also included the limit of these two values, the value of which approaches the inverse of the length of strings being compared. This actually approximates the entropy, E, of every random string generation event when run.
After standard error checking, the script first finds the length of the input string. The rnd function seeds the random number generator. the a and b variables define the ASCII table minus non-printable characters, which ends at 126, inclusively. 127 is actually used as an upper bound so that the next line of code can generate a random string of variables of input length. The following line of code turns the string into the alphanumeric characters provided by the ASCII table. The following line of code subtracts the two strings element-wise and stores the result. The next two lines of code sum up the ASCII distances in the two ways mentioned in the first paragraph. Finally, the values are printed out, as well as providing the entropy, E, of the random string generation event.

Java - flipping an integer using String manipulation occasionally returning an error

This is part of a longer coding challenge - one part involves "flipping" the digits of an input number (i.e. 1234 becomes 4321) and removing leading zeros as applicable.
Below, I have written the method flipOpp that accomplishes this. Most of the time, it works perfectly. But sometimes, I'm getting an error because the last digit becomes a dash ("-") and obviously, the Integer.parseInt() method won't work if one of the digits is a dash!
Any ideas what might be causing this? Also, is there an easier way to flip the digits of an int? The method I'm using right now doesn't seem very efficient - turning an int to a String, then to a character array, manipulating the characters of this array, turning it back into a String, and finally back to an int.
Thanks! Code for this method is below:
// third operation: reverse the digits and remove leading zeros
public static int flipOpp(int num){
char temp;
// change int to a String
String stringNum = Integer.toString(num);
// change String to a char array of digits
char[] charNum = stringNum.toCharArray();
// flip each character and store using a char temp variable
for (int i=0;i<charNum.length/2;i++){
temp = charNum[i];
charNum[i]=charNum[charNum.length-i-1];
charNum[charNum.length-i-1]=temp;
}
// turn flipped char array back to String, then to an int
// this process removes leading zeros by default
String flipString = new String(charNum);
if (flipString.length()<7){
int flipInt = Integer.parseInt(flipString);
return flipInt;
}
else return 0;
}
Any ideas what might be causing this?
Definitely sounds like negative numbers
is there an easier way to flip the digits of an int? The method I'm using right now doesn't seem very efficient
Keep it as an integer. Don't worry about the negative
public static int flipOpp(int num) {
int reversed = 0;
while (num!=0) {
reversed = reversed*10 + num%10;
num /= 10;
}
return reversed;
}
For example, -50,
0*10+0=0
-50/10=-5
- -
0*10+(-5)=-5
-5/10=0
- -
END, output -5

What is the maximum char value in a java program in Netbeans IDE/ what is wrong with my program?

What is the maximum Unicode value of a char in Java (in particular in the Netbeans IDE, if that makes any difference) I've been trying to write a program that, as part of the program, multiplies a char by a random number. According to what I've heard, based on the maximum Unicode value I should be able to multiply the highest value char I'm using (the tilde) by at least 8000 without causing overflow, however overflow does occur in my program. Is there a difference between the maximum Unicode char value and the maximum that is available in Netbeans? In case that isn't the case I have included my code below:
EDIT What I want to do with this portion of the program is "encrypt" the password by multiplying the char with a random number, and then I included a separate section meant to "decrypt" said code, however testing with smaller numbers I found that that part worked.
public static void main(String[] args) {
String pass = "Password";
String pwE = "";
int key [] = new int[pass.length()];
for (int i = 0; i < pass.length(); i++)
{
key[i] = (int)(Math.random()*8000+1); /*EDIT changed the placeholder to the actual function I'm using */
System.out.println(key[i]);
}
for (int i = 0; i < pass.length(); i++)
{
pwE += (char)(pass.charAt(i)*key[i]);
}
System.out.println(pwE);
pass = "";
for (int i = 0; i < pwE.length(); i++)
{
pass += (char)(pwE.charAt(i)/key[i]);
}
System.out.println(pass);
}
"Is there a difference between the maximum Unicode char value and the maximum that is available in Netbeans [sic]?"
No, of course not. NetBeans doesn't have its own private, non-compliant version of Java. The maximum value of a char is always Character.MAX_VALUE, as documented.
http://docs.oracle.com/javase/8/docs/api/java/lang/Character.html#MAX_VALUE
Your problem is very likely caused by your use of String to drive "encryption" and "decryption". You don't bother to control the string encoding, and that could conceivably create strangeness with respect to surrogate pairs and the like. You're mixing the numeric nature of char with String's use of the type to represent characters.
Since you didn't bother to share inputs, expected outputs, and actual outputs with us, we can only guess. Perhaps if you were to share sufficient information ...
A char is a 16 bit unsigned type in Java.
Its maximum value is 65535.
Your multiplication of a char by an element of key looks suspect to me. Your casting this result (which will be an int type) back to char causes wraparound modulo 65536.
Your suspecting Netbeans is a red herring.
Very crudely, if your string only uses ASCII characters, then a maximumum multiplication of 512 would work.

Alphabet constant in Java?

I have a situation where I need to find a letter's index in the alphabet. In Python I could use string.ascii_lowercase or string.ascii_uppercase. Is there something similar in Java?
Obviously I could do:
private static char[] alphabet = "abcdefghijklmnopqrstuvwxyz".toCharArray();
But after so much Python, it makes me wonder if this is built in somewhere.
You can get the index like this:
char lowercaseLetter = ...
int index = lowercaseLetter - 'a';
Although I would prefer ColinD's approach whenever it fits I just want to mention that Java actually has some sort of API for this. It allows you to parse numbers with a radix of up to 36 which use the 10 digits from '0'-'9' and the letters 'a'-'z' for the rest of the range (in either case).
char letter = ...
int index = Character.digit( letter, 36 ) - 10;
and back
int index = ...
char ch = Character.forDigit( index + 10, 36 );
In case you actually want to use this to create or parse radix 36 numbers, you can use the Integer.parseInt and Integer.toString static method implementations that take a radix parameter.

Checking if value of int[] can be long

I have an array of ints ie. [1,2,3,4,5] . Each row corresponds to decimal value, so 5 is 1's, 4 is 10's, 3 is 100's which gives value of 12345 that I calculate and store as long.
This is the function :
public long valueOf(int[]x) {
int multiplier = 1;
value = 0;
for (int i=x.length-1; i >=0; i--) {
value += x[i]*multiplier;
multiplier *= 10;
}
return value;
}
Now I would like to check if value of other int[] does not exceed long before I will calculate its value with valueOf(). How to check it ?
Should I use table.length or maybe convert it to String and send to
public Long(String s) ?
Or maybe just add exception to throw in the valueOf() function ?
I hope you know that this is a horrible way to store large integers: just use BigInteger.
But if you really want to check for exceeding some value, just make sure the length of the array is less than or equal to 19. Then you could compare each cell individually with the value in Long.MAX_VALUE. Or you could just use BigInteger.
Short answer: All longs fit in 18 digits. So if you know that there are no leading zeros, then just check x.length<=18. If you might have leading zeros, you'll have to loop through the array to count how many and adjust accordingly.
A flaw to this is that some 19-digit numbers are valid longs, namely those less than, I believe it comes to, 9223372036854775807. So if you wanted to be truly precise, you'd have to say length>19 is bad, length<19 is good, length==19 you'd have to check digit-by-digit. Depending on what you're up to, rejecting a subset of numbers that would really work might be acceptable.
As others have implied, the bigger question is: Why are you doing this? If this is some sort of data conversion where you're getting numbers as a string of digits from some external source and need to convert this to a long, cool. If you're trying to create a class to handle numbers bigger than will fit in a long, what you're doing is both inefficient and unnecessary. Inefficient because you could pack much more than one decimal digit into an int, and doing so would give all sorts of storage and performance improvements. Unnecessary because BigInteger already does this. Why not just use BigInteger?
Of course if it's a homework problem, that's a different story.
Are you guaranteed that every value of x will be nonnegative?
If so, you could do this:
public long valueOf(int[]x) {
int multiplier = 1;
long value = 0; // Note that you need the type here, which you did not have
for (int i=x.length-1; i >=0; i--) {
next_val = x[i]*multiplier;
if (Long.MAX_LONG - next_val < value) {
// Error-handling code here, however you
// want to handle this case.
} else {
value += next_val
}
multiplier *= 10;
}
return value;
}
Of course, BigInteger would make this much simpler. But I don't know what your problem specs are.

Categories

Resources