Comparing String Integers Issue - java

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!

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.

Find the letter that occur most times from user with using tables [duplicate]

This question already has answers here:
Java program to find the character that appears the most number of times in a String?
(8 answers)
Closed 6 years ago.
I got a task from my university today:
Write a program that reads a ( short ) text from the user and prints the so called max letter (most common character in string) , that the letter which the greatest number of occurrences of the given text .
Here it is enough to look at English letters (A- Z) , and not differentiate between uppercase and lowercase letters in the count of the number of occurrences .
For example, if : text = " Ada bada " so should the print show the most common character, this example it would be a.
This is an introductory course, so in this submission we do not need to use the " scanner - class" . We have not gone through this so much.
The program will use the show message input two get the text from user .
Info: The program shall not use while loop ( true / false ) , "return " statement / "break " statement .
I've been struggling with how I can get char values into a table.. am I correct I need to use array to search for most common character? I think I need to use the binarySearch, but that only supports int not char.
I'll be happy for any answers. hint's and solutions. etc.. if you're very kind a full working program, but again please don't use the things I have written down in the "info" section above.
My code:
String text = showInputDialog("Write a short text: ");
//format string to char
String a = text;
char c = a.charAt(4);
/*with this layout it collects number 4 character in the text and print out.
* I could as always go with many char c... but that wouldn't be a clean program * code.. I think I need to make it into a for-loop.. I have only worked with * *for-loops with numbers, not char (letters).. Help? :)
*/
out.print( text + "\n" + c)
//each letter into 1 char, into table
//search for most used letter
Here's the common logic:
split your string into chars
loop over the chars
store the occurrences in a hash, putting the letter as key and occurrences as value
return the highest value in the hash
As how to split string into chars, etc., you can use Google. :)
Here's a similar question.
There's a common program asked to write in schools to calculate the frequency of a letter in a given String. The only thing you gotta do here is find which letter has the maximum frequency. Here's a code that illustrates it:
String s <--- value entered by user
char max_alpha=' '; int max_freq=0, ct=0;
char c;
for(int i=0;i<s.length();i++){
c=s.charAt(i);
if((c>='a'&&c<='z')||(c>='A'&&c<='Z')){
for(int j=0;j<s.length();j++){
if(s.charAt(j)==c)
ct++;
} //for j
}
if(ct>max_freq){
max_freq=ct;
max_alpha=c;
}
ct=0;
s=s.replace(c,'*');
}
System.out.println("Letter appearing maximum times is "+max_alpha);
System.out.println(max_alpha+" appears "+max_freq+" times");
NOTE: This program presumes that all characters in the string are in the same case, i.e., uppercase or lowercase. You can convert the string to a particular case just after getting the input.
I guess this is not a good assigment, if you are unsure about how to start. I wish you for having better teachers!
So you have a text, as:
String text = showInputDialog("Write a short text: ");
The next thing is to have a loop which goes trough each letter of this text, and gets each char of it:
for (int i=0;i<text.length();i++) {
char c=text.charAt(i);
}
Then comes the calculation. The easiest thing is to use a hashMap. I am unsure if this is a good topic for a beginners course, so I guess a more beginner friendly solution would be a better fit.
Make an array of integers - this is the "table" you are referring to.
Each item in the array will correspond to the occurrance of one letter, e.g. histogram[0] will count how many "A", histogram[1] will count how many "B" you have found.
int[] histogram = new int[26]; // assume English alphabet only
for (int i=0;i<histogram.length;i++) {
histogram[i]=0;
}
for (int i=0;i<text.length();i++) {
char c=Character.toUppercase(text.charAt(i));
if ((c>=65) && (c<=90)) {
// it is a letter, histogram[0] contains occurrences of "A", etc.
histogram[c-65]=histogram[c-65]+1;
}
}
Then finally find the biggest occurrence with a for loop...
int candidate=0;
int max=0;
for (int i=0;i<histogram.length;i++) {
if (histogram[i]>max) {
// this has higher occurrence than our previous candidate
max=histogram[i];
candidate=i; // this is the index of char, i.e. 0 if A has the max occurrence
}
}
And print the result:
System.out.println(Character.toString((char)(candidate+65));
Note how messy this all comes as we use ASCII codes, and only letters... Not to mention that this solution does not work at all for non-English texts.
If you have the power of generics and hashmaps, and know some more string functions, this mess can be simplified as:
String text = showInputDialog("Write a short text: ");
Map<Char,Integer> histogram=new HashMap<Char,Integer>();
for (int i=0;i<text.length();i++) {
char c=text.toUppercase().charAt(i));
if (histogram.containsKey(c)) {
// we know this letter, increment its occurrence
int occurrence=histogram.get(c);
histogram.put(c,occurrence+1);
}
else {
// we dunno this letter yet, it is the first occurrence
histogram.put(c,1);
}
}
char candidate=' ';
int max=0;
for (Char c:histogram.keySet()) {
if (histogram.get(c)>max) {
// this has higher occurrence than our previous candidate
max=histogram.get(c);
candidate=c; // this is the char itself
}
}
System.out.println(c);
small print: i didn't run this code but it shall be ok.

Java String += Shorthand explanation needed

While I was creating a program to compress a string I ran into this strange problem, I will paste the code snippets with their outputs, I would like someone to clearly explain why this is happening.
The first code snippet: here if same letter appears consecutively, then the successive occurrences of the letter is replaced by the total count of same letters. Ex: aaabbb should be written as a3b3.
public static String compress(String str){
String compressed = "";
char prev = str.charAt(0);
int count = 1;
for (int i = 1; i < str.length(); i++) {
char curr = str.charAt(i);
if (curr == prev) { // in case curr is equal to prev
count++;
} else { // in case curr is not equal to prev
//compressed=compressed+prev+count;
compressed+=prev+count; // Shorthand used here
count=1;
prev=curr;
}
}
compressed=compressed+prev+count; // Shorthand not used
System.out.println(compressed);
return compressed;
}
the output for this above code when inputted with aabbccaabbccaabbccaabb is 99100101991001019910010199b2, observe the last two elements of the output, this is because outside the loop, shorthand is not used. If I write the expression as compressed = compressed +prev+count inside the loop, I'll get the intended output.
I thought this output is because the operation is messing with the address of the String. But the next code confused me again.
String prev= "abc";
String curr = "def";
String result="";
result+=prev+curr;
System.out.println(result);
I think this is because the right hand operation is performing an ASCII addition, I cannot come to a conclusion, can anyone clarify.
I am sleep deprived and hence I am not able to come to a conclusion, hence asking someone to clarify my trivial doubt.
It has nothing to do with the reference. When you did prev+count ascii value of the character in prev is added with the integer count. In this case :
ascii of "a" is 97, and it occurred twice... so 97 +2 = 99 ..
ascii of "b" is 98, and it occurred twice... so 98 +2 = 100 ..
ascii of "c" is 99, and it occurred twice... so 99 +2 = 101 ..
that's why the output is 99100101991001019910010199100
try this : compressed+=(""+prev)+count; // Shorthand used here
In this case, or in compressed+=""+prev+count case, since the operation happens from left to right, the + operator is applied on a string ("") and char(prev) and behaves like append and also returns a string. The resulting string is then appened with another int (prev)
A better way is using a StringBuilder
Take a look at this subject and at JLS 15.18.1 section :
You see this behavior as a result of the combination of operator
precedence and string conversion.
JLS 15.18.1 states:
If only one operand expression is of type String, then string conversion (§5.1.11) is performed on the other operand to produce a
string at run time.
Therefore the right hand operands in your first expression are
implicitly converted to string: string = string + ((char)65) + 5;
For the second expression however string += ((char)65) + 5; the +=
compound assignment operator has to be considered along with +.
Since += is weaker than +, the + operator is evaluated first.
There we have a char and an int which results in a binary numeric
promotion to int. Only then += is evaluated, but at this time
the result of the expression involving the + operator has already been evaluated.
Whenever you add a char to an int in java first it converts the character into its equivalent ASCII value and then adds it to the integer
eg suppose the following scenario ,
char c = 'a'; // ASCII value of 'a' is 97
int i = c + 5 ; // result will be 97 + 5 = 102
I think this answers your first half question
Now the Second part ,
Whenever you use the shorthand operator in Java the expression at right hand side is evaluated first.
Hence , for expresion
result += prev + curr it is evaluated as
result = result + (prev + curr);
Therefore ,
result+=prev+curr; // Here first it appends "abc" with "def" and then the resultant "abcdef" is appended to as result .
you can convert your charater value "prev" to string and than append count to it.
compressed += Character.toString(prev) + count;

Java: looking for the fastest way to check String for presence of Unicode chars in certain range

I need to implement a very crude language identification algorithm. In my world, there are only two languages: English and not-English. I have ArrayList and I need to determine if each String is likely in English or the other language which has its Unicode chars in a certain range. So what I want to do is to check each String against this range using some type of "presence" test. If it passes the test, I say the String is not English, otherwise it's English. I want to try two type of tests:
TEST-ANY: If any char in the string falls within the range, the string passes the test
TEST-ALL: If all chars in the string fall within the range, the string passes the test
Since the array might be very long, I need to implement this very efficiently. What would be the fastest way of doing this in Java?
Thx
UPDATE: I am specifically checking for non-English by looking at a specific range of Unicodes rather then checking for whether the characters are ASCII, in part to take care of the "resume" problem mentioned below. What I am trying to figure out is whether Java provides any classes/methods that essentially implement TEST-ANY or TEST-ALL (or another similar test) as efficiently as possible. In other words, I am trying to avoid reinventing the wheel especially if the wheel invented before me is better anyway.
Here's how I ended up implementing TEST-ANY:
// TEST-ANY
String str = "wordToTest";
int UrangeLow = 1234; // can get range from e.g. http://www.utf8-chartable.de/unicode-utf8-table.pl
int UrangeHigh = 2345;
for(int iLetter = 0; iLetter < str.length() ; iLetter++) {
int cp = str.codePointAt(iLetter);
if (cp >= UrangeLow && cp <= UrangeHigh) {
// word is NOT English
return;
}
}
// word is English
return;
I really don't think that this solution is ideal for determining language, but if you want to check to see if a string is all ascii, you could do something like this:
public static boolean isASCII(String s){
boolean ret = true;
for(int i = 0; i < s.length() ; i++) {
if(s.charAt(i)>=128){
ret = false;
break;
}
}
return ret;
}
So then if you try this:
boolean r = isASCII("Hello");
r would equal true. But if you try:
boolean r = isASCII("Grüß dich");
then r would equal false. I haven't tested performance, but this would work reasonably fast, because all it does is compare a character to the number 128.
But as #AlexanderPogrebnyak mentioned in the comments above, this will return false if you give it "résumé". Be aware of that.
Update:
I am specifically checking for non-English by looking at a specific range of Unicodes rather then checking for whether the characters are ASCII
But ASCII is a range in Unicode (well at least in UTF-8). Unicode is just an extension of ASCII. What the code #mP. and I provided does is it checks to see whether each character is in a certain range. I chose that range to be ASCII, which is any Unicode character that has a decimal value of less than 128. You can just as well choose any other range. But the reason I chose ASCII is because it's the one with the Latin alphabet, the Arabic numbers, and some other common characters that would normally be in an 'English' string.
public static boolean isAscii( String s ){
int length = s.length;
for( int i = 0; i < length; i++){
final char c = s.charAt( i );
if( c > 'z' ){
return false;
}
}
return true;
}
#Hassan thanks for picking the typo replaced test against big Z with little z.

How can I extract the numbers from a string only using charAt(), length() and/or toCharArray() in Java

I have to do this for an assignment in my java class. I have been searching for a while now, but only find solutions with regex etc.
For my assignment however I may only use charAt(), length() and/or toCharArray(). I need to get from a string like gu578si300 for example just the numbers so it will become: 578300.
i know numbers are 48 - 57 in ASCII but i can't figure out how to do this in java. You guys any ideas?
i was thinking about a for loop that checks whether the (int) char is between 48-57 en if so puts the value into a seperate array. Howeevr i dont know how to programm that last thing.
I now have this;
public static String filterGetallenreeks(String reeks){
String temp = "";
for (char c : reeks.toCharArray()) {
if ((int) c > 47 && (int) c < 58)
temp += c;
}
return temp;
however it is not working, it just outputs the same as goes in.
is it something in my mainm which looks like this. If i'm right the return temp; will return the temp string into the reeks string in the main right? why is my input still the same a sthe output?
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Voer een zin, woord of cijferreeks in:");
String reeks = sc.nextLine();
if (isGetallenreeks(reeks)){
System.out.println("is getallenreeks");
filterGetallenreeks(reeks);
System.out.println(reeks);
}
Since this is homework I will not be providing the complete solution, however, this is how you should go about it:
Do a for loop that iterates for the total amount of characters within the string (.length). Check if the character is a digit using the charAt and isDigit methods.
You could do a loop that checks a character in the string, and if it's a number, append it to another string:
//I haven't tested this, so you know.
String test = "gu578si300 ";
String numbers = "";
for(int i=0; i<test.length(); i++){
if("0123456789".indexOf(test.charAt(i)) // if the character at position i is a number,
numbers = numbers + test.charAt(i); // Add it to the end of "numbers".
}
int final = Integer.parseInt(numbers); // If you need to do something with those numbers,
// Parse it.
Let me know if that works for you.
It seems like a reasonable approach, but I'd make a couple of changes from what you suggested:
If you need to result as a string then use a StringBuilder instead of an array.
Use character literals like '0' and '9' instead of ASCII codes to make your code more readable.
Update
The specific problem with your code is this line:
temp = temp + (int)c;
This converts the character to its ASCII value and then converts that to a decimal string containing the ASCII value. That's not what you want. Use this instead:
temp += c;

Categories