In following program, what is the purpose of the while loop? - java

There are no problems with the compilation, but whether or not I have the while loop in place or not, the result is the same. I can't understand why the while loop is included. BTW, this is just an example program from the Java SE tutorial:
public class ContinueWithLabelDemo {
public static void main(String[] args) {
String searchMe = "Look for a substring in me";
String substring = "sub";
boolean foundIt = false;
int max = searchMe.length() - substring.length();
test:
for (int i = 0; i <= max; i++) {
int n = substring.length();
int j = i;
int k = 0;
while (n-- != 0) { // WTF???
if (searchMe.charAt(j++) != substring.charAt(k++)) {
continue test;
}
}
foundIt = true;
break test;
}
System.out.println(foundIt ? "Found it" : "Didn't find it");
}
}

You can replace your
while (n-- != 0) { // WTF???
with
System.out.println("outside loop");
while (n-- != 0) { // WTF???
System.out.println("inside loop: comparing "
+ searchMe.charAt(j) + ":" + substring.charAt(k));
to see how this example works. Below is little explanation.
This code is searching for substring in searchMe string. Take a look at this example:
Look for a substring in me
^
sub
If you compare characters at position 0 in searchMe and substring you will notice that they are not the same L != s so we can skip matching rest of letters and go to next position (that is the purpose of continue test;)
Look for a substring in me
^
sub
So now we will try compare next letter with first letter of searchMe with first letter of substring. This time we get o!=s so there is no way that substring starts in this place, lets carry on.
After few comparisons we finally found promising place
Look for a substring in me
^
sub
where first letter of substring is the same as current letter in searchMe (s==s) so we wont jump from while loop yet and will try to check next letter. And we have another success
Look for a substring in me
^
sub
because u==u, so we will continue our loop until we iterate over our entire substring which can happen in next step.
Look for a substring in me
^
sub
And this time we compared b with b. Since they are equal and we don't have more letters in substring to check we can set value of foundIt to true and brake test for loop.
And that is the end.
If you remove while from your code you will get positive response as soon as you will find first character that will match first letter of substring in your case in after checking Look for a program will match s with first letter on substring which will also be s.
While loop is used here to iterate over entire substring and only in case of fail in matching corresponding characters we will move searching one place forward. If we would ignore this inner loop and just iterate over entire data we can ignore some positive results like in case where we would look for aab in aaab String. Take a look
aaab
aab
^^
^ will match but after them we will have to match a with b which will fail. Without inner while loop we would probably start another match from last checked position that failed which would be
aaab
aab
^
This time we also failed to find match for substring so we skipped a*aab* part.

Related

What happens when if statement goes true (in this code)?

There is a problem in codingbat.com which you're supposed to remove "yak" substring from the original string. and they provided a solution for that which I can't understand what happens when the if statement goes true!
public String stringYak(String str) {
String result = "";
for (int i=0; i<str.length(); i++) {
// Look for i starting a "yak" -- advance i in that case
if (i+2<str.length() && str.charAt(i)=='y' && str.charAt(i+2)=='k') {
i = i + 2;
} else { // Otherwise do the normal append
result = result + str.charAt(i);
}
}
return result;
}
It just adds up i by 2 and what? When it appends to the result string?
Link of the problem:
https://codingbat.com/prob/p126212
The provided solution checks for all single characters in the input string. For this i is the current index of the checked character. When the current char is not a y and also the (i+2) character is not a k the current char index is advanced by 1 position.
Example:
yakpak
012345
i
So here in the first iteration the char at i is y and i+2 is a k, so we have to skip 3 chars. Keep in mind i is advanced by 1 everytime. So i has to be increased by 2 more. After this iteration i is here
yakpak
012345
i
So now the current char is no y and this char will get added to the result string.
But it's even simpler in Java as this functionality is build in with regex:
public String stringYak(String str) {
return str.replaceAll("y.k","");
}
The . means every char.
If i is pointing at a y and there is as k two positions down, then it wants to skip the full y*k substring, so it add 2 to i so i now refers to the k. WHen then loop continues, i++ will skip past the k, so in effect, the entire 3-letter y*k substring has been skipped.

A java string exercise i came across

Look for patterns like "zip" and "zap" in the string -- length-3, starting with 'z' and ending with 'p'. Return a string where for all such words, the middle letter is gone, so "zipXzap" yields "zpXzp"
Here is a solution i got from someone:
public class Rough {
public static void main(String [] args){
StringBuffer mat = new StringBuffer("matziplzdpaztp");
for(int i = 0; i < mat.length() - 2; ++i){
if (mat.charAt(i) == 'z' & mat.charAt(i + 2) == 'p'){
mat.deleteCharAt(i + 1);
}
}
System.out.println(mat);
}
}
But why is it that the for loop condition (i < mat.length() -2) is not (i < mat.length())????
Because in the loop:
if (mat.charAt(i) == 'z' & mat.charAt(i + 2) == 'p'){
// -----------------------------------^^^^^
If i were bound by i < mat.length(), then i + 2 would be out of bounds.
Because you don't have to reach the end of your sentence since your words are at least three letters long.
"2" stands for "the length except the first word",you just need to check all the positions in the string variable , and treat the positions as the first word of the substring , so just ignore the "length of the substring without the first word".
in your case , the length of "z*p" is 3, you just check all the position in the string , and treat the position as z to check something ,so just ignore "*p" ,which has length 2.
mat.length() will give length 14 and if you check for mat.charAt(i + 2) at the end it will give java.lang.StringIndexOutOfBoundsException because the string counts from index 0 not from 1. If you still want to use mat.length() you have to replace the AND '&' operator with short circuit AND '&&' operator in if condition.

Java Searching through a String for a valid character sequence

I just took a codility test and was wondering why my solution only scored 37/100. The problem was that you were given a String and had to search through it for valid passwords.
Here are the rules:
1) A valid password starts with a capital letter and cannot contain any numbers. The input is restricted to any combination of a-z, A-Z and 0-9.
2)The method they wanted you to create is suppose to return the size of the largest valid password. So for example if you input "Aa8aaaArtd900d" the number 4 is suppose to be outputted by the solution method. If no valid String is found the method should return -1
I cannot seem to figure out where I went wrong in my solution. Any help would be greatly appreciated! Also any suggestions on how to better test code for something like this would be greatly appreciated.
class Solution2 {
public int solution(String S) {
int first = 0;
int last = S.length()-1;
int longest = -1;
for(int i = 0; i < S.length(); i++){
if(Character.isUpperCase(S.charAt(i))){
first = i;
last = first;
while(last < S.length()){
if(Character.isDigit(S.charAt(last))){
i = last;
break;
}
last++;
}
longest = Math.max(last - first, longest);
}
}
return longest;
}
}
added updated solution, any thoughts to optimize this further?
Your solution is too complicated. Since you are not asked to find the longest password, only the length of the longest password, there is no reason to create or store strings with that longest password. Therefore, you do not need to use substring or an array of Strings, only int variables.
The algorithm for finding the solution is straightforward:
Make an int pos = 0 variable representing the current position in s
Make a loop that searches for the next candidate password
Starting at position pos, find the next uppercase letter
If you hit the end of line, exit
Starting at the position of the uppercase letter, find the next digit
If you hit the end of line, stop
Find the difference between the position of the digit (or the end of line) and the position of the uppercase letter.
If the difference is above max that you have previously found, replace max with the difference
Advance pos to the position of the last letter (or the end of line)
If pos is under s.length, continue the loop at step 2
Return max.
Demo.

java replacing char in string

firstLetter = word.charAt(0);
lastLetter = word.charAt((word.length()) - 1);
noFirstLetter = word.substring(1);
newWord = noFirstLetter + firstLetter;
if(word.equalsIgnoreCase(newWord))
So im trying to take the first letter of the word and if I take the first letter of the word away and move it to the end it should be equal to the same word. My code here isn't working. For example if the user entered "dresser" if you move the "d" to the end of the word you get the word "dresser" again. That is what im trying to check
I think what you are trying to do is to remove the first character, and then check if rest of the characters are symmetrical around the center of the word.(OK even it is complicated for me)
EG:
dresser => (drop d) => resser => (add d to the right) => resserd (read from right to left and it is dresser again).
after you drop the first letter:
resser (there are even number of letters in the word)
r e s s e r
|_|
|_____|
|_________|
since they are symmetrical, you can say that that word would be Palindromic if you move D from left to right (or vice versa).
The whole thing above could be horribly wrong if I misunderstood your question at the first place. But I assumed, your question was NOT a simple substring question.
Cheers.
Okay, so I'm presuming that you want to take a string, move it's first index to the end and then reverse the string. If you do this to a word such as 'dresser' then you end up with the same value.
Something like this could work, currently untested:
public StringBuilder reverseWord(String word){
firstLetter = word.charAt(0); //find the first letter
noFirstLetter = word.substring(1); //removing the first index
newWord = noFirstLetter + firstLetter; //move first index to end
return new StringBuilder(newWord).reverse().toString(); //reverse
}
if(reverseWord("dresser").equals("dresser")){
//do something
}
Edit: As Jose has pointed out, it is important to check the length of the actual parameter by invoking length() on word.
If you move 'd' to the end of the word "dresser" you get "resserd" which is not equal to "dresser".
If you move 'd' to the end and then reverse the word then they are equal.
So, assuming you consider strings equals even if they are reversed, the code you want would be :
boolean testPass = false;
if ( word.length()==0 )
testPass = true;
else
{
firstLetter = word.charAt(0);
noFirstLetter = word.substring(1);
newWord = noFirstLetter + firstLetter;
reversed = new StringBuilder(newWord).reverse().toString()
if (word.equalsIgnoreCase(newWord) || word.equalsIgnoreCase(reversed))
testPass = true;
}
if ( testPass )
// Do something
Take notice of the important check of word having lenght 0. Otherwise word.charAt(0) will throw an exception.

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;
}
}

Categories