What does Character.isDigit return? - java

I found this example online. peek contains one character read from the buffered reader with readch(br). The following cycle must continue until the read character is a number
while(Character.isDigit(peek)
&& !Character.isLetter(peek) && peek != '_') {
int n = (int) peek - 48;
sum = sum*10 + n;
readch(br);
}
Isn't it enough to just say Character.isDigit?

Yes, it's redundant. Character.isDigit returns true if the character type (from Character.getType) is DECIMAL_DIGIT_NUMBER, and Character.isLetter returns true if the same type is one of several categories (DECIMAL_DIGIT_NUMBER is not one of the categories listed).
getType returns a single value, so there are no characters that have multiple types according to Java. Thus, there is no character for which isDigit and isLetter both return true. Likewise, _ is CONNECTOR_PUNCTUATION (easy to see this with a quick sample Java program), which is neither a digit nor a letter.
So this is code by someone who was being overly defensive. isDigit suffices.

The sample is doing the job only halve.
It assumes that Character::isDigit returns true only for the characters '0' to '9', but that is wrong. This also means that the calculation (int) peek - 48 is not reliable to get the numeric value of the digit.
When the code should really work on any kind of digits, it needs to look like this:
final var radix = 10;
var value = 0;
while( Character.isDigit( peek) && ((value = Character.digit( peek, radix )) != -1) )
{
sum = sum * radix + value;
readch( br );
}
To cover also the hex digits from 'A' to 'F' or their lowercase equivalents, just remove the Character::isDigit check (and change radix accordingly).
Using Character::getNumericValue would also get the Roman numbers, but this will not work properly for the calculation of sum.

Related

string a to i problem on leetcode my solution fails incase of 2 consecutive signs

problem link: https://leetcode.com/problems/string-to-integer-atoi/
i have implemented my solution but it fails for testcase like "-+42"since 2 consecutive signs appear in string. what changes do i need to do in my code, and where am i wrong? help would be appreciated
my code:
class Solution {
public int myAtoi(String s) {
s=s.trim();
char sign='+';
if (s.length()==0) return 0;
String digit="";
for(int i=0;i<s.length();i++)
{
//checking for sign
if(s.charAt(i)=='-'||s.charAt(i)=='+')
sign=s.charAt(i);
//checking for all non digit characters
else if((s.charAt(i)>='a'&& s.charAt(i)<='z')||(s.charAt(i)>='A' && s.charAt(i)<='Z')||(s.charAt(i)==' ')||(s.charAt(i)=='.')||(s.charAt(i)=='-')||(s.charAt(i)=='+'))
break;
else{
digit=digit+s.charAt(i);
}
}
if(digit=="") return 0;
//System.out.print(sign);
try{
int n=(Integer.parseInt(digit));
//int a=Integer.parseInt(digit);
System.out.print(sign);
if(sign=='-')
return (-n);
return n;
}
//check for out of range for integer
catch(NumberFormatException e)
{
if(sign=='-')
{
//
int n=Integer.MIN_VALUE;
return n;}
else
{
int n=Integer.MAX_VALUE;
return n;
}
}
}
}
Er, just.. do what the exercise says? Not sure what you want to hear from SO here. I guess: "Can you regurgitate the question to me". Can do!
Your algorithm isn't doing anything like what the exercise spells out you need to do. You are triggering on a sign character appearing anywhere, and your code scans for letters, all things which the exercise doesn't mention. At all. The exercise mentions the concept of a 'not a digit' and the first character (after getting rid of spaces, which you already did with a trim() invocation).
So, do what the exercise says:
Instead of if (s.charAt(i) == '-' your code needs to involve s.charAt(0) - there are only 3 options:
The trimmed string starts with a +. Set the sign to +, and start looking at digits from position 1.
The trimmed string starts with a -. Set the sign to -, and start looking at digits from position 1.
Neither. Set the sign to + and start looking at digits from position 0.
Your s.charAt(i) >= 'a' is also wrong. You're not looking for a letter. You're looking for anything that isn't a digit. + isn't a letter. Nevertheless, in input -5+10, you're supposed to return -5. In -+10 you're supposed to return 0. (Because that's like -hello - the negative value of no digits, which is minus zero, which is just zero).
I think the intent of the exercise is not to use Integer.parseInt whatsoever.
Try this algorithm:
if your character is >= '0' and <= '9', you can subtract '0' to get the actual digit in integer form: char c = '5'; int y = c - '0'; System.out.println(y); would print 5.
multiply your existing input by 10, then add the digit you have. In other words, for text input "29", first you read a 2, you multiply the number you're working on (0, at first) to 10 (still 0), then you add 2, giving you 2. Then you get another digit, so you multiply what you ahve so far by 10 (giving you 20), and add the digit value, getting you the integer 29. No need for parseInt.
You now you need to clamp when your working total flips signs on you. So, if all of a sudden your input is negative (as you won't yourself make it negative until the very end), you know you have to clamp and return Integer.MIN_VALUE or Integer.MAX_VALUE, depending on the sign value.

How to compare char with number in Java

I got a problem and I think it is in comparing a char with a number.
String FindCountry = "BB";
Map<String, String> Cont = new HashMap <> ();
Cont.put("BA-BE", "Angola");
Cont.put("9X-92", "Trinidad & Tobago");
for ( String key : Cont.keySet()) {
if (key.charAt(0) == FindCountry.charAt(0) && FindCountry.charAt(1) >= key.charAt(1) && FindCountry.charAt(1) <= key.charAt(4)) {
System.out.println("Country: "+ Cont.get(key));
}
}
In this case the code print "Angola", but if
String FindCountry = "9Z"
it doesn't print anything. I am not sure I think the problem is in that it can't compare that is '2' greater than 'Z'. In that example, I got only two Cont.put(), but in my file, I got much more and a lot of them are not only with chars. I got a problem with them.
What is the smartest and best way to compare char with a number ? Actually, if I set a rule like "1" is greater than "Z" it will be okay because I need this way of greater: A-Z-9-0.
Thanks!
You can use a lookup "table", I used a String:
private static final String LOOKUP = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
And then compare the chars with indexOf(), but it seems messy and could probably be achieved more easily, I just can't come up with something easier at the moment:
String FindCountry = "9Z";
Map<String, String> Cont = new HashMap<>();
Cont.put("BA-BE", "Angola");
Cont.put("9X-92", "Trinidad & Tobago");
for (String key : Cont.keySet()) {
if (LOOKUP.indexOf(key.charAt(0)) == LOOKUP.indexOf(FindCountry.charAt(0)) &&
LOOKUP.indexOf(FindCountry.charAt(1)) >= LOOKUP.indexOf(key.charAt(1)) &&
LOOKUP.indexOf(FindCountry.charAt(1)) <= LOOKUP.indexOf(key.charAt(4))) {
System.out.println("Country: " + Cont.get(key));
}
}
If you only use the characters A-Z and 0-9, you could add a conversion method in between which will increase the values of the 0-9 characters so they'll be after A-Z:
int applyCharOrder(char c){
// If the character is a digit:
if(c < 58){
// Add 43 to put it after the 'Z' in terms of decimal unicode value:
return c + 43;
}
// If it's an uppercase letter instead: simply return it as is
return c;
}
Which can be used like this:
if(applyCharOrder(key.charAt(0)) == applyCharOrder(findCountry.charAt(0))
&& applyCharOrder(findCountry.charAt(1)) >= applyCharOrder(key.charAt(1))
&& applyCharOrder(findCountry.charAt(1)) <= applyCharOrder(key.charAt(4))){
System.out.println("Country: "+ cont.get(key));
}
Try it online.
Note: Here is a table with the decimal unicode values. Characters '0'-'9' will have the values 48-57 and 'A'-'Z' will have the values 65-90. So the < 58 is used to check if it's a digit-character, and the + 43 will increase the 48-57 to 91-100, putting their values above the 'A'-'Z' so your <= and >= checks will work as you'd want them to.
Alternatively, you could create a look-up String and use its index for the order:
int applyCharOrder(char c){
return "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".indexOf(c);
}
Try it online.
PS: As mentioned in the first comment by #Stultuske, variables are usually in camelCase, so they aren't starting with an uppercase letter.
As the others stated in the comments, such mathematical comparison operations on characters are based on the actual ASCII values of each char. So I'd suggest you refactor your logic using the ASCII table as reference.

Complex numbers string/array in java?

I want to assign complex numbers to binary values which i am doing using complex class, easily available; but when a i am appending complex numbers to string buffer, returning into a string, one complex number is taking multiple entries. How can i place 1 number to 1 entry and read afterwards? Ending string data like this "2.0+2.0i2.0-2.0i2.0+2.0i2.0-2.0i-2.0+2.0i2.0+2.0i....". Now character at 0 is '2', char at 1 is '.' and so on.. I need char at 0 to be 2.0+2.0i. and afterwards i should be able to separate real and imaginary parts of each entry.
StringBuilder symbs = new StringBuilder();
Complex s1 = new Complex(-2,-2);
Complex s2 = new Complex(+2,-2);
Complex s3 = new Complex(+2,+2);
Complex s4 = new Complex(-2,+2);
/////////////////////Symbols to vector ////////////////////
for(int i=0; i< plo.length()-1; i+=2)
{
if(plo.charAt(i)=='1' && plo.charAt(i+1)=='0')
{
symbs.append(s1);
}
else if(plo.charAt(i)=='0' && plo.charAt(i+1)=='1')
{
symbs.append(s2);
}
else if(plo.charAt(i)=='0' || plo.charAt(i+1)=='0')
{
symbs.append(s3);
}
else if(plo.charAt(i)=='1' && plo.charAt(i+1)=='1')
{
symbs.append(s4);
}
}
printComplex(symbs.toString());
"I need char at 0 to be 2.0+2.0i." thats not possible, as a char is one character.
you can append semicolons after every complex and then split for them
Use Regex pattern matching similar like this [[0-9].0+[0-9].0i]+
Pass the string to the Matcher compiler and check available pattern is found on the given string. Based on that extract the value with programmatic logic to get real and imaginary parts.
Explanation on regex string
Real part
[0-9] --> it check value from 0 to 9 followed by . and followed by 0
Imaginary part
[0-9] --> it check value from 0 to 9 followed by . and followed by 0 and then by i

How do I check if a char is a vowel?

This Java code is giving me trouble:
String word = <Uses an input>
int y = 3;
char z;
do {
z = word.charAt(y);
if (z!='a' || z!='e' || z!='i' || z!='o' || z!='u')) {
for (int i = 0; i==y; i++) {
wordT = wordT + word.charAt(i);
} break;
}
} while(true);
I want to check if the third letter of word is a non-vowel, and if it is I want it to return the non-vowel and any characters preceding it. If it is a vowel, it checks the next letter in the string, if it's also a vowel then it checks the next one until it finds a non-vowel.
Example:
word = Jaemeas then wordT must = Jaem
Example 2:
word=Jaeoimus then wordT must =Jaeoim
The problem is with my if statement, I can't figure out how to make it check all the vowels in that one line.
Clean method to check for vowels:
public static boolean isVowel(char c) {
return "AEIOUaeiou".indexOf(c) != -1;
}
Your condition is flawed. Think about the simpler version
z != 'a' || z != 'e'
If z is 'a' then the second half will be true since z is not 'e' (i.e. the whole condition is true), and if z is 'e' then the first half will be true since z is not 'a' (again, whole condition true). Of course, if z is neither 'a' nor 'e' then both parts will be true. In other words, your condition will never be false!
You likely want &&s there instead:
z != 'a' && z != 'e' && ...
Or perhaps:
"aeiou".indexOf(z) < 0
How about an approach using regular expressions? If you use the proper pattern you can get the results from the Matcher object using groups. In the code sample below the call to m.group(1) should return you the string you're looking for as long as there's a pattern match.
String wordT = null;
Pattern patternOne = Pattern.compile("^([\\w]{2}[AEIOUaeiou]*[^AEIOUaeiou]{1}).*");
Matcher m = patternOne.matcher("Jaemeas");
if (m.matches()) {
wordT = m.group(1);
}
Just a little different approach that accomplishes the same goal.
Actually there are much more efficient ways to check it but since you've asked what is the problem with yours, I can tell that the problem is you have to change those OR operators with AND operators. With your if statement, it will always be true.
So in event anyone ever comes across this and wants a easy compare method that can be used in many scenarios.
Doesn't matter if it is UPPERCASE or lowercase. A-Z and a-z.
bool vowel = ((1 << letter) & 2130466) != 0;
This is the easiest way I could think of. I tested this in C++ and on a 64bit PC so results may differ but basically there's only 32 bits available in a "32 bit integer" as such bit 64 and bit 32 get removed and you are left with a value from 1 - 26 when performing the "<< letter".
If you don't understand how bits work sorry i'm not going go super in depth but the technique of
1 << N is the same thing as 2^N power or creating a power of two.
So when we do 1 << N & X we checking if X contains the power of two that creates our vowel is located in this value 2130466. If the result doesn't equal 0 then it was successfully a vowel.
This situation can apply to anything you use bits for and even values larger then 32 for an index will work in this case so long as the range of values is 0 to 31. So like the letters as mentioned before might be 65-90 or 97-122 but since but we keep remove 32 until we are left with a remainder ranging from 1-26. The remainder isn't how it actually works, but it gives you an idea of the process.
Something to keep in mind if you have no guarantee on the incoming letters it to check if the letter is below 'A' or above 'u'. As the results will always be false anyways.
For example teh following will return a false vowel positive. "!" exclamation point is value 33 and it will provide the same bit value as 'A' or 'a' would.
For starters, you are checking if the letter is "not a" OR "not e" OR "not i" etc.
Lets say that the letter is i. Then the letter is not a, so that returns "True". Then the entire statement is True because i != a. I think what you are looking for is to AND the statements together, not OR them.
Once you do this, you need to look at how to increment y and check this again. If the first time you get a vowel, you want to see if the next character is a vowel too, or not. This only checks the character at location y=3.
String word="Jaemeas";
String wordT="";
int y=3;
char z;
do{
z=word.charAt(y);
if(z!='a'&&z!='e'&&z!='i'&&z!='o'&&z!='u'&&y<word.length()){
for(int i = 0; i<=y;i++){
wordT=wordT+word.charAt(i);
}
break;
}
else{
y++;
}
}while(true);
here is my answer.
I have declared a char[] constant for the VOWELS, then implemented a method that checks whether a char is a vowel or not (returning a boolean value). In my main method, I am declaring a string and converting it to an array of chars, so that I can pass the index of the char array as the parameter of my isVowel method:
public class FindVowelsInString {
static final char[] VOWELS = {'a', 'e', 'i', 'o', 'u'};
public static void main(String[] args) {
String str = "hello";
char[] array = str.toCharArray();
//Check with a consonant
boolean vowelChecker = FindVowelsInString.isVowel(array[0]);
System.out.println("Is this a character a vowel?" + vowelChecker);
//Check with a vowel
boolean vowelChecker2 = FindVowelsInString.isVowel(array[1]);
System.out.println("Is this a character a vowel?" + vowelChecker2);
}
private static boolean isVowel(char vowel) {
boolean isVowel = false;
for (int i = 0; i < FindVowelsInString.getVowel().length; i++) {
if (FindVowelsInString.getVowel()[i] == vowel) {
isVowel = true;
}
}
return isVowel;
}
public static char[] getVowel() {
return FindVowelsInString.VOWELS;
}
}

Comparing String Integers Issue

I have a scanner that reads a 7 character alphanumeric code (inputted by the user). the String variable is called "code".
The last character of the code (7th character, 6th index) MUST BE NUMERIC, while the rest may be either numeric or alphabetical.
So, I sought ought to make a catch, which would stop the rest of the method from executing if the last character in the code was anything but a number (from 0 - 9).
However, my code does not work as expected, seeing as even if my code ends in an integer between 0 and 9, the if statement will be met, and print out "last character in code is non-numerical).
example code: 45m4av7
CharacterAtEnd prints out as the string character 7, as it should.
however my program still tells me my code ends non-numerically.
I'm aware that my number values are string characters, but it shouldnt matter, should it?
also I apparently cannot compare actual integer values with an "|", which is mainly why im using String.valueOf, and taking the string characters of 0-9.
String characterAtEnd = String.valueOf(code.charAt(code.length()-1));
System.out.println(characterAtEnd);
if(!characterAtEnd.equals(String.valueOf(0|1|2|3|4|5|6|7|8|9))){
System.out.println("INVALID CRC CODE: last character in code in non-numerical.");
System.exit(0);
I cannot for the life of me, figure out why my program is telling me my code (that has a 7 at the end) ends non-numerically. It should skip the if statement and continue on. right?
The String contains method will work here:
String digits = "0123456789";
digits.contains(characterAtEnd); // true if ends with digit, false otherwise
String.valueOf(0|1|2|3|4|5|6|7|8|9) is actually "15", which of course can never be equal to the last character. This should make sense, because 0|1|2|3|4|5|6|7|8|9 evaluates to 15 using integer math, which then gets converted to a String.
Alternatively, try this:
String code = "45m4av7";
char characterAtEnd = code.charAt(code.length() - 1);
System.out.println(characterAtEnd);
if(characterAtEnd < '0' || characterAtEnd > '9'){
System.out.println("INVALID CRC CODE: last character in code in non-numerical.");
System.exit(0);
}
You are doing bitwise operations here: if(!characterAtEnd.equals(String.valueOf(0|1|2|3|4|5|6|7|8|9)))
Check out the difference between | and ||
This bit of code should accomplish your task using regular expressions:
String code = "45m4av7";
if (!code.matches("^.+?\\d$")){
System.out.println("INVALID CRC CODE");
}
Also, for reference, this method sometimes comes in handy in similar situations:
/* returns true if someString actually ends with the specified suffix */
someString.endsWith(suffix);
As .endswith(suffix) does not take regular expressions, if you wanted to go through all possible lower-case alphabet values, you'd need to do something like this:
/* ASCII approach */
String s = "hello";
boolean endsInLetter = false;
for (int i = 97; i <= 122; i++) {
if (s.endsWith(String.valueOf(Character.toChars(i)))) {
endsInLetter = true;
}
}
System.out.println(endsInLetter);
/* String approach */
String alphabet = "abcdefghijklmnopqrstuvwxyz";
boolean endsInLetter2 = false;
for (int i = 0; i < alphabet.length(); i++) {
if (s.endsWith(String.valueOf(alphabet.charAt(i)))) {
endsInLetter2 = true;
}
}
System.out.println(endsInLetter2);
Note that neither of the aforementioned approaches are a good idea - they are clunky and rather inefficient.
Going off of the ASCII approach, you could even do something like this:
ASCII reference : http://www.asciitable.com/
int i = (int)code.charAt(code.length() - 1);
/* Corresponding ASCII values to digits */
if(i <= 57 && i >= 48){
System.out.println("Last char is a digit!");
}
If you want a one-liner, stick to regular expressions, for example:
System.out.println((!code.matches("^.+?\\d$")? "Invalid CRC Code" : "Valid CRC Code"));
I hope this helps!

Categories