Avoid matching the same value twice in string.matches() method in Java - java

Okay, I'm totally rewriting this question because this works and I want to know why it works.
Suppose I have a number, testNumber with a value of 567.
I want to know if the next two numbers (shouldPassTest and shouldFailTest) the same digits, but in different 10s places.
So here's the code:
int testNumber = 567;
int num1 = 5;
int num2 = 6;
int num3 = 7;
int shouldPassTest = 756;
int shouldFailTest = 777;
if(Integer.toString(shouldPassTest).matches("[5,6,7][5,6,7][5,6,7]")
{
//Do some cool stuff
}
if(Integer.toString(shouldFailTest).matches("[5,6,7][5,6,7][5,6,7]")
{
//Do some cool stuff
}
What happens when you run that, is that each digit is tested from the range of available digits (5, 6, and 7). Theoretically, shouldFailTest should actually pass the test seeing as how 7 matches one of my three criteria, albeit 3 times.
But what happens is that 777 returns false, when tested. This is precisely the result I wanted in my code, but I want to know why it happened. Does the matches method test to make sure that each number is only matched once?
Thanks!
This post was highly edited. After running my code, I found that the method does exactly what I want, but now I want to know why. Thanks.

I would use the following as regex is not a good solution to this problem:
public class Count {
private int value;
public Count() {
value=0;
}
void increment() {
value++;
}
void decrement() {
value--;
}
public int getValue() {
return value;
}
}
public static boolean isAnagram(int val1, int val2) {
Map<Character, Count> characterCountMap=new HashMap<>();
for(char c:Integer.toString(val1).toCharArray()) {
Count count=characterCountMap.get(c);
if(count==null) { count=new Count(); characterCountMap.put(c, count);}
count.increment();
}
for(char c:Integer.toString(val2).toCharArray()) {
Count count=characterCountMap.get(c);
if(count==null) { return false; }
else { count.decrement(); }
if(count.getValue()==0) {
characterCountMap.remove(c);
}
}
return characterCountMap.size()==0;
}
Please run:
System.out.println(Integer.toString(shouldFailTest).matches("[5,6,7][5,6,7][5,6,7]"));
to view the actual return value.

Theoretically, shouldFailTest should actually pass the test seeing as
how 7 matches one of my three criteria, albeit 3 times.
But what happens is that 777 returns false, when tested. This is
precisely the result I wanted in my code, but I want to know why it
happened. Does the matches method test to make sure that each number
is only matched once?
No, "777" does match the pattern you have specified "[5,6,7][5,6,7][5,6,7]"
Following condition in your code will evaluate to true.
if(Integer.toString(shouldFailTest).matches("[5,6,7][5,6,7][5,6,7]"))

Related

Issue converting double to boolean

I am working on a project in my Java class that is using multiple classes as well as GUI (not sure if that info is relevant). My group partner and I have come across an issue though. We have a Validator class, that should validate a "SSN" but we are continuously given the error:
java:146: error: incompatible types: double cannot be converted to boolean
if(Validator.isValidSSN(jTextFieldEmpSSN)){
Now obviously java:146 is the line. the code we have for each class is:
employeeUI class (the one showing the error):
private void jButtonEnterActionPerformed(java.awt.event.ActionEvent evt)
{
Employee e=new Employee();
if(Validator.isValidName(jTextFieldEmpFirst)){
if(Validator.isValidName(jTextFieldEmpLast)){
if(Validator.isValidEmail(jTextFieldEmpEmail)){
if(Validator.isValidSSN(jTextFieldEmpSSN)){
e.setFirstName(jTextFieldEmpFirst.getText());
e.setLastName(jTextFieldEmpLast.getText());
e.setEmailAdd(jTextFieldEmpEmail.getText());
e.setSSN(Integer.parseInt(jTextFieldEmpSSN.getText()));
}}}}
and the Validator class for isValidSSN is:
public static double isValidSSN(JTextField textfield)
{
double number = 0;
boolean inRange = false;
while(!inRange)
{
number = Double.parseDouble(textfield.getText());
if (number >= 100000000 && number <= 999999999)
{
inRange = true;
} else {}
}
return number;
}
We have been beating our head on how to fix this for quite some time, but are coming up at a loss. Are we missing something? we would greatly appreciate any help with this.
If I ask, "Is 123-45-6789" a valid SSN?" you wouldn't reply "123456789.0", would you? You'd give me a yes or a no. By returning double your method is doing the former. It's responding with a number instead of an answer to the question.
A good rule of thumb is that methods starting with is or has should return booleans. "Is this a valid SSN?" is a yes/no question, so isValidSSN should return the programming equivalent of yes/no.
public static boolean isValidSSN(JTextField textfield)
There are a couple of other design points here:
The loop isn't necessary. The SSN is either valid or it isn't.
A text field is not itself an SSN. It holds some text, and that text is the SSN. Rather than taking a text field and looking up the text in the field with getText(), it'd be better to have isValidSSN take the text directly. Let the caller extract the text from the text field.
In broader terms this is known as the single responsibility principle. Every method should ideally do just one thing.
Result:
public static boolean isValidSSN(String ssn) {
double number = Double.parseDouble(ssn);
if (number >= 100000000 && number <= 999999999) {
return true;
}
else {
return false;
}
}
P.S. If I don't mention it someone will surely comment that the if and else blocks aren't necessary; one can return the if result directly. They would be right, though I consider it a bit of an advanced trick. It would look like so:
public static boolean isValidSSN(String ssn) {
double number = Double.parseDouble(ssn);
return number >= 100000000 && number <= 999999999;
}

Removing a substring from a string, repeatedly

Problem:
Remove the substring t from a string s, repeatedly and print the number of steps involved to do the same.
Explanation/Working:
For Example: t = ab, s = aabb. In the first step, we check if t is
contained within s. Here, t is contained in the middle i.e. a(ab)b.
So, we will remove it and the resultant will be ab and increment the
count value by 1. We again check if t is contained within s. Now, t is
equal to s i.e. (ab). So, we remove that from s and increment the
count. So, since t is no more contained in s, we stop and print the
count value, which is 2 in this case.
So, here's what I have tried:
Code 1:
static int maxMoves(String s, String t) {
int count = 0,i;
while(true)
{
if(s.contains(t))
{
i = s.indexOf(t);
s = s.substring(0,i) + s.substring(i + t.length());
}
else break;
++count;
}
return count;
}
I am just able to pass 9/14 test cases on Hackerrank, due to some reason (I am getting "Wrong Answer" for rest of the cases). After a while, I found out that there is something called replace() method in Java. So, I tried using that by replacing the if condition and came up with a second version of code.
Code 2:
static int maxMoves(String s, String t) {
int count = 0,i;
while(true)
{
if(s.contains(t))
s.replace(t,""); //Marked Statement
else break;
++count;
}
return count;
}
But for some reason (I don't know why), the "Marked Statement" in the above code gets executed infinitely (this I noticed when I replaced the "Marked Statement" with System.out.println(s.replace(t,""));). I don't the reason for the same.
Since, I am passing only 9/14 test cases, there must be some logical error that is leading to a "Wrong Answer". How do I overcome that if I use Code 1? And if I use Code 2, how do I avoid infinite execution of the "Marked Statement"? Or is there anyone who would like to suggest me a Code 3?
Thank you in advance :)
Try saving the new (returned) string instead of ignoring it.
s = s.replace(t,"");
replace returns a new string; you seemed to think that it alters the given string in-place.
Try adding some simple parameter checks of the strings. The strings shouldn't be equal to null and they should have a length greater than 0 to allow for counts greater than 0.
static int maxMoves(String s, String t) {
int count = 0,i;
if(s == null || s.length() == 0 || t == null || t.length() == 0)
return 0;
while(true)
{
if(s.contains(t) && !s.equals(""))
s = s.replace(t,""); //Marked Statement
else break;
++count;
}
return count;
}
You might be missing on the edge cases in the code 1.
In code 2, you are not storing the new string formed after the replace function.
The replace function replaces each substring of this string that matches the literal target sequence with the specified literal replacement sequence.
Try this out:
public static int findCount(String s, String t){
if( null == s || "" == s || null == t || "" == t)
return 0;
int count =0;
while(true){
if(s.contains(t)){
count++;
int i = s.indexOf(t);
s = s.substring(0, i)+s.substring(i+t.length(), s.length());
// s = s.replace(t,"");
}
else
break;
}
return count;
}
String r1="ramraviraravivimravi";
String r2="ravi";
int count=0,i;
while(r1.contains(r2))
{
count++;
i=r1.indexOf(r2);
StringBuilder s1=new StringBuilder(r1);
s1.delete(i,i+r2.length());
System.out.println(s1.toString());
r1=s1.toString();
}
System.out.println(count);
First of all no logical difference in both the codes.
All the mentioned answers are to rectify the error of code 2 but none told how to pass all (14/14) cases.
Here I am mentioning a test case where your code will fail.
s = "abcabcabab";
t = "abcab"
Your answer 1
Expected answer 2
According to your code:
In 1st step, removig t from index 0 of s,
s will reduce to "cabab", so the count will be 1 only.
But actual answer should be 2
I first step, remove t from index 3 of s,
s will reduced to "abcab", count = 1.
In 2nd step removing t from index 0,
s will reduced to "", count = 2.
So answer would be 2.
If anyone know how to handle such cases, please let me know.

How do i find how many times a substring is used in a string?

public Object countOccurrences(String string)
{
int e = 0;
int i = 0;
while ( i < sentence.length())
{
if(sentence.contains(string))
{
e++;
i++;
return e;
}
else
{
break;
}
}
return e;
}
What is wrong with my code that won't allow me to pass the test? is there anyway I can use the substring method inside a loop to do this?
#Test
public void testCountOccurrences()
{
assertEquals(1, sc1.countOccurrences("ence"));
assertEquals(2, sc1.countOccurrences("en"));
assertEquals(1, sc2.countOccurrences("that"));
assertEquals(0, sc2.countOccurrences("This"));
}
What is wrong with my code that won't allow me to pass the test?
Before doing anything else, you should consider how you could have worked out what was wrong for your code to start with. Did you debug through it? At what point did it behave differently to how you expected it to? If you haven't learned how to use a debugger yet, now is a great time to start.
As for the next step, look at this code:
if(sentence.contains(string))
{
e++;
i++;
return e;
}
That condition doesn't depend on i or e, just on sentence and string. So as long as sentence is of length at least 1, you'll either return 1 or 0. Your code can never return more than 1.
That's what's wrong with your code at the moment - as for how to fix it, I'd start looking at String.indexOf(String, int). In other words, you want to find the first occurrence, then find the next occurrence, then the next occurrence, until you can't find any more. (Use the return value to work out where to start looking on the next iteration, as well as checking that there was a match.)
A couple of situations to be careful of:
How many times does "abbbc" contain "bb"?
How many times does "abbbc" contain ""?
I'd also urge a couple of other changes:
Your method has a return type of Object - why? Surely it's always going to return an integer, so a return type of int would be more appropriate
This is a great candidate for parameterized testing. Look into how you can effectively separate your single test into multiple test cases which can pass or fail independently, but without the source overhead of lots of test methods... (Hint: each test case should have the sentence, the text you're looking for, and the expected number of matches.)
public Object countOccurrences(String string) {
int e = 0;
int i = 0;
while (i <= (sentence.length() - string.length() + 1)) {
if (sentence.substr(i, string.length() - 1).equals(string)) {
e++;
}
i++;
}
return e;
}
I didn't got to try it myself but it should work.

Storing the result of a method in a variable

For the past few months, I switched to programming in a functional language (Racket), and recently restarted coding in Java, so I'm a bit confused regarding a few concepts.
The following (simplified version) code is an implementation of euclid's algorithm. It works just fine. My problem with it is the return statement. Is it possible in java to store the results of a method in a variable? For example,in my code, I initialized the variable result to store the gcd of two numbers. But that returns an incorrect value. However, if I remove the variable result, I get the correct value for the gcd, which brings me to my 2nd question: return statements. I don't quite understand what the return statement is doing here. The only reason I have it in the 1st place was because I was aiming to store the result of the method Recursion in a variable. But as far as I've tried it, and seems to be only messing up my code.
Primary objective: To store the result of the gcd of two numbers in a variable, so I can re-use it elsewhere.
Is there is a way to make this possible?
Any suggestions would be appreciated!
import java.util.*;
public class StoringResults
{
public static void main(String[]args)
{
int big,small,remainder,gcd; //Variables declared.
Scanner sc=new Scanner(System.in);
/* Use enters input */
//Big is the larger number.
//Small is the smaller of the two.
remainder=big%small;
int result=recursion(big,small,remainder);
System.out.println("FINAL RESULT:"+result);
}
//recursive method.
public static int recursion(int big,int small,int remainder)
{
remainder=big%small;
if(remainder==0)
{
System.out.println(small);
}
else
{
int dummyvar=remainder;
big=small;
small=dummyvar;
recursion(big,small,remainder);
}
return remainder;
}
}
As my comment already stated your logic is faulty.
And your statement if I remove the variable result,I get the correct value for the gcd is plain wrong. You get the correct result printed but not returned. And that is caused by the fact that you return the wrong value.
remove the remainder from the method signature since your first statement is assigning something to it
return the correct value: smaller instead of remained
return in the else branch
That will result in the following code:
public static int recursion(int big,int small)
{
int remainder=big%small;
if(remainder==0)
{
System.out.println(small);
}
else
{
big=small;
small=remainder;
return recursion(big,small);
}
return small;
}
Shortening results in
public static int recursion(int big, int small) {
int remainder = big % small;
if(remainder == 0) {
return small;
} else {
return recursion(small,remainder);
}
}
Adding to TDG's answer, your code should be more like this:
//recursive method.
public static int recursion(int big, int small, int remainder) {
remainder = big%small
if (remainder==0) {
System.out.println(small);
return small;
} else {
Int dummyvar = remainder;
big = small;
small = dummyvar;
return recursion(big, small, remainder);
}
}

Simple Binary Search Program....Please tell me what is wrong in this specific code

Im a beginner.
Here is a binary search code.Its showing array out of bounds error for main method.
please look into the program and kindly tell me my mistake.ill be grateful for ur service.
i have to write all this crap cause i cant post it as its asking for more details.
public class BinaryS
{
int n;
public BinaryS(int z)
{
n=z;
}
static int pos;
static boolean flag=false;
public void disp()
{
int arr[]={0,1,2,3,4};
int len=arr.length;
int first=0;
int last=len;
int mid=(int)(first+last/2);
//boolean flag=false;
while(mid>=0 && mid<=len)
{
if(n<arr[mid])
{
last=mid;
}
if(n>arr[mid])
{
first=mid;
}
if(n==arr[mid])
{
flag=true;
pos=mid+1;
}
}
if(flag==true){
System.out.println("the no."+n+"is found at"+pos);
}
else{
System.out.println("the no."+n+"is not found ");
}
}
public static void main(String args[])
{
BinaryS obj=new BinaryS(2);
obj.disp();
}
}
Currently your code does compile, and runs forever - because of this loop:
while(mid>=0 && mid<=len)
{
// Code which doesn't modify mid or len
}
Assuming it gets into that loop at all (which it does), the condition is never going to become false - so unless you return or break from within the loop (you don't) or an exception is thrown (it isn't) you're just going to keep going round the loop.
This is where you should:
Use a debugger to observe what's happening
Think about what the condition should actually be and how you want it to become false
Adjust your code to either change the condition, or change the loop body so that it modifies mid or len

Categories

Resources