Alphabet constant in Java? - 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.

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 Hexadecimal to Decimal conversion: Custom Logic

I am trying to figure out how to convert hex into a string and integer so I can manipulate an RGB light on my arduino micro-controller through it's serialport. I found a good example on the java website, but I'm having a difficult time understanding some of the methods and I am getting hung up. I could easily just copy-paste this code and have it work but I want to fully understand it. I will add comments to my understandings and hopefully someone can provide some feedback.
public class HexToDecimalExample3{
public static int getDecimal(String hex){ //this is the function which we will call later and they are declaring string hex here. Can we declare string hex inside the scope..?
String digits = "0123456789ABCDEF"; //declaring string "digits" with all possible inputs in linear order for later indexing
hex = hex.toUpperCase(); //converting string to uppercase, just "in case"
int val = 0; //declaring int val. I don't get this part.
for (int i = 0; i < hex.length(); i++) //hex.length is how long the string is I think, so we don't finish the loop until all letters in string is done. pls validate this
{
char c = hex.charAt(i); //char is completely new to me. Are we taking the characters from the string 'hex' and making an indexed array of a sort? It seems similar to indexOf but non-linear? help me understand this..
int d = digits.indexOf(c); //indexing linearly where 0=1 and A=11 and storing to an integer variable
val = 16*val + d; //How do we multiply 16(bits) by val=0 to get a converted value? I do not get this..
}
return val;
}
public static void main(String args[]){
System.out.println("Decimal of a is: "+getDecimal("a")); //printing the conversions out.
System.out.println("Decimal of f is: "+getDecimal("f"));
System.out.println("Decimal of 121 is: "+getDecimal("121"));
}}
To summerize the comments, it's primarily the char c = hex.charAt(i); AND the val = 16*val + d; parts I don't understand.
Ok, let's go line for line
public static int getDecimal(String hex)
hex is the parameter, it needs to be declared there, so you can pass a String when you call the function.
String digits = "0123456789ABCDEF";
Yes, this declares a string with all characters which can occur in a hexadecimal number.
hex = hex.toUpperCase();
It converts the letters in the hex-String to upper case, so that it is consistent, i.e. you always have F and never f, no matter which is being input.
int val = 0;
This is the variable where the corresponding decimal value will later be in. We will do our calculations with this variable.
for (int i = 0; i < hex.length(); i++)
hex.length() is the number of characters in the hex-String provided. We execute the code inside this for loop once per character.
char c = hex.charAt(i);
Yes, char represents a single character. We retrieve the character from the hex-String at index i, so in the first iteration it is the first character, in the second iteration the second character and so on.
int d = digits.indexOf(c);
We look which index the character has in the digit-String. In that way we determine the decimal representation of this specific digit. Like 0-9 stay 0-9 and F becomes a 15.
val = 16*val + d;
Let's think about what we have to do. We have the decimal value of the digit. But in hexadecimal we have this digit at a specific position with which it gets multiplied. Like the '1' in '100' is actually not a 1, but 100 * 1 because it is at this position.
10 in hexadecimal is 16 in decimal, because we have 1 * 16. Now the approach here is a little bit complicated. val is not uninitialized. val is 0 at the beginning and then contains the cumulated values from the previous iterations. Since the first character in the String is the highest position we don't know directly with what we have to multiply, because we don't know how many digits the number has (actually we do, but this approach doesn't use this). So we just add the digit value to it. In the consecutive iterations it will get multiplied by 16 to scale it up to the corresponding digit base value. Let me show you an example:
Take 25F as hex number. Now the first iteration takes the 2 and converts it to a 2 and adds it to val. The 16 * val resolves to 0 so is not effective in the first time.
The next iteration multiplies the 2 with 16 and takes the 5 (converted to 5) and adds it to val. So now we have (I split it mathematically so you understand it):
2 * 16 + 5
Next we get the F which is decimal 15. We multiply val by 16 and add the 15.
We get 2 * 256 + 5 * 16 + 16 (* 1), which is actually how you calculate the decimal value of this hex value mathematically.
Another possibility to compute val is:
val += Math.pow(16, hex.length() - i - 1) * d;

Getting letter from integer index

I wish to have a java method which gives me, index given, a corresponding letter set excel like, so:
258 => IZ (last index)
30 => AD
120 => DR
56 => BD
First method gives correct output, but it's very dumb and I don't like that.
I tried to build a second method that involves a bit of thinking.
I already saw methods using String Builder or something else like this one
but I tried to build a method myself aka betterGetColumnName.
better 258 => IHGFEDCBAX (not ok)
better 30 => AD (OK, 2nd alphabet round it's ok)
better 120 => DCBAP (not ok)
better 56 => BAD (seems like 3rd alphabet round breaks my logic)
public String getColumnName(int index){
String[] letters = {
"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R",
"S","T","U","V","W","X","Y","Z","AA","AB","AC","AD","AE","AF","AG","AH",
"AI","AJ","AK","AL","AM","AN","AO","AP","AQ","AR","AS","AT","AU","AV",
"AW","AX","AY","AZ","BA","BB","BC","BD","BE","BF","BG","BH","BI","BJ",
"BK","BL","BM","BN","BO","BP","BQ","BR","BS","BT","BU","BV","BW","BX",
"BY","BZ","CA","CB","CC","CD","CE","CG","CH","CI","CJ","CK","CL","CM",
"CN","CO","CP","CQ","CR","CS","CT","CU","CV","CW","CX","CY","CZ","DA",
"DB","DC","DD","DF","DG","DH","DI","DJ","DK","DL","DM","DN","DO","DP",
"DQ","DR","DS","DT","DU","DV","DW","DX","DY","DZ","EA","EB","EC","ED",
"EE","EF","EG","EH","EI","EJ","EK","EL","EM","EN","EO","EP","EQ","ER",
"ES","ET","EU","EV","EW","EX","EY","EZ","FA","FB","FC","FD","FE","FF",
"FG","FH","FI","FJ","FK","FL","FM","FN","FO","FP","FQ","FR","FS","FT",
"FU","FV","FW","FX","FY","FZ","GA","GB","GC","GD","GE","GF","GG","GH",
"GI","GJ","GK","GL","GM","GN","GO","GP","GQ","GR","GS","GT","GU","GV",
"GW","GX","GY","GZ","HA","HB","HC","HD","HE","HF","HG","HH","HI","HJ",
"HK","HL","HM","HN","HO","HP","HQ","HR","HS","HT","HU","HV","HW","HX",
"HY","HZ","IA","IB","IC","ID","IE","IF","IG","IH","II","IJ","IK","IL",
"IM","IN","IO","IP","IQ","IR","IS","IT","IU","IV","IW","IX","IY","IZ"
};
if (index<=letters.length){
return letters[index-1];
}else{
return null;
}
}
I think I should save how many times I made a full alphabet round, I wouldn't use StringBuilder or else, just char, String and integers because at school we can't upgrade java version (1.5.x) also I think it might be useful for me to understand why is my logic so wrong.
public String betterGetColumnName(int index){
int res=0;
String s = "";
char h='0';
while(index>26){
res=index/26;
h=(char)(res+64);
s+=h;
index -=26;
}
h=(char)(index+64);
s+=h;
return s;
}
You are definitely on the right track, though your logic is a bit off. What you are effectively trying to do is to convert a base 10 integer into a base 26 character. But instead of digits, the converted "number" actually consists of the 26 letters of the alphabet.
The algorithm you want here is to determine each letter of the output by taking the remainder of the input number divided by 26. Then, divide the input by 26 and again inspect the "tens" position to see what letter it is. In the code snippet below, I assume that 1 corresponds to A, 26 corresponds to Z, and 27 to AA. You may shift the indices however you feel is best.
int input = 53;
String output = "";
while (input > 0) {
int num = (input - 1) % 26;
char letter = (char)(num+65);
output = letter + output;
input = (input-1) / 26;
}
System.out.println(output);
BA
Demo
Note: A helpful edit was suggested which uses StringBuilder instead of String to do the concatenations. While this might be more optimal than the above code, it might make it harder to see the algorithm.

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

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.

Can I multiply charAt in Java?

When I try to multiply charAt I received "big" number:
String s = "25999993654";
System.out.println(s.charAt(0)+s.charAt(1));
Result : 103
But when I want to receive only one number it's OK .
On the JAVA documentation:
the character at the specified index of this string. The first character is at index 0.
So I need explanation or solution (I think that I should convert string to int , but it seems to me that is unnesessary work)
char is an integral type. The value of s.charAt(0) in your example is the char version of the number 50 (the character code for '2'). s.charAt(1) is (char)53. When you use + on them, they're converted to ints, and you end up with 103 (not 100).
If you're trying to use the numbers 2 and 5, yes, you'll have to parse them. Or if you know they're standard ASCII-style digits (character codes 48 through 57, inclusive), you can just subtract 48 from them (as 48 is the character code for '0'). Or better yet, as Peter Lawrey points out elsewhere, use Character.getNumericValue, which handles a broader range of characters.
Yes - you should parse extracted digit or use ASCII chart feature and substract 48:
public final class Test {
public static void main(String[] a) {
String s = "25999993654";
System.out.println(intAt(s, 0) + intAt(s, 1));
}
public static int intAt(String s, int index) {
return Integer.parseInt(""+s.charAt(index));
//or
//return (int) s.charAt(index) - 48;
}
}

Categories

Resources