Weird thing happens in a for loop, java - java

I'm fairly new to programming and I started to write some basic codes. I tried to create an algorithm that found every position of the character you wanted in a string. If I were to enter "helllo" as a string and wanted to search for the character l, it would output 2, 3 and 4. The code worked fine until I tried to trick the code a bit to change something. To do so, I first removed the termination condition in the "for loop" and instead added an if statement during the loop to break it. I spent about 2h on the error that occurred after and I still can't find out what's happening.
Here's the code and the output it gives me. (I know my code is a mess and not properly optimized, but right now I would just like to know what is happening. I'll rearrange it later if I get it to work. thank you^-^.)
When I run the code, instead of displaying as it should, "7, 8, 9, 10"(it searches for the character ^ in the string Oioriew^^^^) it outputs "7-1,8,9,10". To fix it, I can simply insert the termination condition in the loop again, which was, "pow != -1" but at this point, I really want to know why it happens.
public class Tests {
static void zeMethod(String mainString,char charToFind) {
int a = 0;
String b, c;
char chartToConvert;
c = "";
b = "";
for (int pow = mainString.indexOf(charToFind);
; // *the condition was here.*
pow = mainString.indexOf(charToFind, pow + 1)) {
a++;
if (a == 1){
System.out.println("String: "+mainString);
System.out.println("il y a un "+charToFind+" à la/aux position(s)");
}
if (a == 1){
System.out.print(pow);
}
if (a%2 == 0 && pow != -1) {
c = b+", "+pow;
}
if (a%2 != 0 && a != 1 && pow != -1) {
b = c+", "+pow;
}
if (pow == -1){
System.out.print(pow);
break;
}
//*end of loop*
}
if (a%2 != 0){
System.out.println(c);
}
else {
System.out.println(b);
}
}
public static void main(String[] args){
String string = "Oioriew^^^^";
char chara = '^';
zeMethod(string, chara);
}
}
I'm sorry if my question is a bit incoherent or not properly asked. This is my first time on the site and English isn't my mother language. Thank you for your time!
Edit:
I know the question wasn't clear at first, but what I meant is, why does pow become -1 after the second iteration of the loop. Also, why does the break after the System.out.print(pow); doesn't make it leave the loop. (I'm looking how to make a debugger work atm too.)

[...] instead of displaying as it should, "7, 8, 9, 10" [...] it outputs "7-1,8,9,10 [...] I really want to know why it happens
Sounds like you're asking why it prints -1, which happens because you explicitly asked it to:
if (pow == -1){
System.out.print(pow);
break;
}
If pow is -1 then print pow (aka -1) and exit the loop.
UPDATE
As for why the order of the output, use a debugger and step through the code one statement at a time, and you'll see.
But, lets see: We can agree that loop will iterate with pow having these numbers in this order: 7, 8, 9, 10, -1
Why does it print 7 first?
Because you have this code inside the loop:
a++;
if (a == 1){
System.out.print(pow);
}
Why does it print -1 next?
Because there are no other print statements inside the loop, which would be a lot more apparent if you indented the code correctly, i.e. indented the content of the loop.
Why does it print 8,9,10 last?
Because you print the content of b or c after the loop, and that is the content of whichever one of them is being printed.
Note that first value (-7) is not added to b, because you explicitly exclude it in the if statement.

I'm all good, thank you all for your time and Andreas, for the debugger option. It's a must-have for anyone programming. I don't know how I didn't see this earlier, but to break, it had to become -1 and since I had to break before I could print my answer, -1 was first.

Related

Cannot come up with why does my Java code loop infinitely

I tried to do this LeetCode daily challenge but I've found out that my code loops infinitely.
I looked through it multiple times, but I cannot find where the problem is. If anyone could spot it, please answer.
public int longestValidParentheses(String s) {
int count, highestOne = 0, index = 0;
boolean isSevered = false;
boolean theEnd = false;
while(!theEnd) {
count = 0;
while(!isSevered) {
if(index<s.length()-2) {
if(s.charAt(index) == '(' & s.charAt(index++) == ')') {count = count + 2;index = index+2;}
else {isSevered = true;}}
else theEnd=true;isSevered=true;
}
highestOne = count;
}
return highestOne;
}
I have 2 suggestions for you:
Use indentation and do not write if/else on the same line as the code associated with them
Always, ALWAYS use bracelets, even if you have only a single command. I think one of the wrongs java did is letting the programmers the free not to use bracelets if there is just a single command after it. It confusing.
So you have 2 mistakes here that make your code run for infinity:
isSevered will always be true after one loop exactly, as you change it to true no matter what happens as it is outside the if else statements, hence the reason I wrote the 2 advices above.
You never changing isSeveres or theEnd at the outside loop. Meaning that if isSevers is true and theEnd is false, you will never enter the internal while and will never exit the outside while.
The two of those combined means that if the condition that make theEnd be initialized with true won't happen at the first run, you will be stuck with infinity loop.

I don't really understand the do { } while structure

I'm trying to learn Java, I studied Pascal in high school and it has the repeat until..; instruction.
I want to solve an exercise where I'm supposed to keep entering numbers until the penultimate + antepenultimate numbers equal the last number I entered.(a[i-2]+a[i-1] = a[i]); I'm doing it without arrays but that doesn't really matter.
In Pascal it would be easy because repeat until is more easier to use
For ex it would be
repeat
...
until ((a[i-2]+a[i-1] = a[i]) and (n=3));
n is the number of values I entered
I can't figure out how to introduce it in Java, so far I did this but it doesn't work if I enter 2 2 4. It should stop but it keeps asking for numbers
int pen = 0, ant = 0, s = 0, n = 1;
int ult = input.nextInt();
s = s + ult;
do {
do {
ant = pen;
pen = ult;
ult = input.nextInt();
n++;
s = s + ult;
} while (ant + pen != ult);
System.out.println(n);
} while ((n == 3) || (n < 4));
ult is the last number I enter, s is the sum of the numbers entered.
Could anyone tell me how to set the conditions so it will stop if I enter the values 2 2 4?
A Do-While loop runs the code in the loop first. It evaluates the logic last, and then if it's true it repeats the code inside the loop, and so on until the logic is false.
The way to solve tricky problems like this is to get out a sheet of paper and record what each variable does. Step through each line like a debugger and record what's being stored in each variable as the program progresses.
It's the best way to do it. You'll find that you'll gain a deeper understanding of how your programs are working.
Java isn't any more magic than Pascal, the issue might be you've had a long break from programming :). Anyway, its been a while since I wrote anything in Java, but the issue I could spot in your code is just that n equals three after you've entered three ints, and so the outer loop continues.
int pen = 0, ant = 0, ult = 0, n = 0;
do {
ant = pen;
pen = ult;
ult = input.nextInt();
} while (++n < 3 || ant + pen != ult );
assert n >= 3;
assert ant + pen == ult;
Note that ever since Pascal everything has been zero indexed instead of one indexed.
Pascal uses the form:
repeat
doStuff();
until (boleanValue);
Java is basically the same, except for one important point:
do
doStuff();
while (~boleanValue);
The important difference is that "~" before booleanValue. The Pascal repeat ... until keeps running until the boolean evaluates to true. In Java the do ... while keeps running until the boolean evaluates to false. When converting from Pascal to Java you need to switch the boolean to work the other way.
The primary difference between while loop and a do-while loop is that while loop does eager condition check where as do-while loop does lazy condition check
while: Expression is evaluated at the top of the loop
syntax:
while (expression) {
statement(s)
}
(taken from http://www.w3resource.com/c-programming/c-while-loop.php)
Example:
public class WhileDemo{
public static void main(String args[]) {
boolean isSunday = false;
while(isSunday) {
System.out.println("Yayy.. Its Sunday!!");
}
}
}
Output: (nothing is printed on console)
Reason: Since isSunday is false, the body of loop is not executed
do-while: Expression is evaluated at the bottom of the loop. Therefore, the statements within the do block are always executed at least once.
syntax:
do {
statement(s)
} while (expression);
(taken from http://www.w3resource.com/c-programming/c-do-while-loop.php)
Example:
public class DoWhileDemo{
public static void main(String args[]) {
boolean isSunday = false;
do {
System.out.println("Yayy.. Its Sunday!!");
} while(isSunday);
}
}
Output: Yayy.. Its Sunday!!
Reason: The body of do is executed first, there by printing Yayy.. Its Sunday!! and then the condition while(isSunday); evaluates to false since isSunday is false and the loop terminates
You're only missing one thing from your problem. Your explanation of the Pascal code is almost correct, but wouldn't work without some modification.
In Java, use short-circuit logical operators to do the check.
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html
Not tested:
int n = 0;
int a[] = new a[3];
do {
n++;
a[0] = a[1];
a[1] = a[2];
a[2] = input.nextInt();
} while ((n < 3) || (a[0]+a[1] != a[2]));
System.out.println(a[2]);

Half String every second char

I an coding beginner.I have started practicing SPOJ basic problems.This was the one I was trying to solve , But the code is incorrect.
Please help me where I have coded this question wrong as I am unable to figure out:
public class Print2ndChar {
public static void main(String[] args) throws java.lang.Exception {
Print2ndChar mainObj = new Print2ndChar();
java.io.BufferedReader inputReader = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
String noOfTestCase;
if(((noOfTestCase = inputReader.readLine()) == null))
System.exit(0);
int noOfLines = 0;
try{
noOfLines = Integer.parseInt(noOfTestCase);
}catch(Exception e){
System.exit(0);
}
if(noOfLines<0 || noOfLines>100)
System.exit(0);
String [] randomWords = new String[noOfLines];
for(int i=0;i<noOfLines;i++){
randomWords[i] = inputReader.readLine();
if(randomWords[i] == null || randomWords[i].length()<2 || randomWords[i].length()%2!=0 || (randomWords[i].length()/2)>100)
System.exit(0);
}
for (String word : randomWords){
mainObj.letsBegin(word.substring(0, word.length() / 2));
System.out.println();
}
}
private void letsBegin(String data) {
if (data.length() <= 0) {
return;
} else {
System.out.print(data.charAt(0));
if (data.length() >= 3)
letsBegin(data.substring(2, data.length()));
}
}
}
EDIT :
I/P : 4
your
progress
is
noticeable
O/P
y
po
i
ntc
OK! So after a lot of hit and trials, I know what is wrong with your code. The code that you have written fails because of the condition randomWords[i].length()%2!=0 inside your if. There is nothing wrong with you putting this condition to check the input, but if you will select sample test case, inside the highlighted blue area you will notice an extra space after every string. Like this :
You can see that other than the last input all other input strings have a space character at the end. So, when you read the string from stdin the length of the string is 2*k + 1 (because of the space), and your program will exit without any output. Hence you get a wrong answer.
This problem exists with other test cases as well probably. And how do I know this? After spoj shows you wrong answer, if you click on the wrong answer, it will show you 2 failed test cases, something like this:
It shows your program's output is empty because your code exited because of the extra space at the end of strings.
So, I believe the person who wrote the test cases should be given a WT Error (Wrong Test Cases) :P :D
So, the possible correction is you remove the mentioned condition from the if and you will get AC. Because now you will be dividing 2*k + 1 by 2, which will not be an integer and which will get rounded to the nearest smallest integer, which will be same as dividing 2*k by 2 and the program will give the correct result.
A few things that you should take care while solving questions on spoj, you do not have to verify that every input lies within the range specified in the question, or if it is a valid data type. The range is given to tell you that Spoj will only test your program with cases which lie between those ranges and will not exceed them. So, even if you remove all the code where you check for exceptions and ranges of input data, you will get an AC. Moreover, writing such code only adds to the burden.
Hope this helps. :)

In Java, when is a "do while" loop the only option?

Is there ever a situation where you must use a do while loop? Is it an accepted practice? It seems like it is equivalent to a plain while loop except that its first iteration happens before checking the conditional, if that is even true.
int i = 3;
while ( i > 0 ) { // runs 3 times
i--;
}
vs
int j = 3;
do {
j --;
} while ( j > 0 ); // runs 3 times
The same?
EDIT: I have seen the java doc, but
the example in the java docs doesn't look like it requires that the particular routine inside of the do while loop must be run in the do while loop instead of inside of a regular while loop!
Is there ever a situation where you must use a do while loop?
No: every do-while loop can be written as a while-loop by running the body once before the loop begins. However, there are certainly cases where it makes more sense to use the do-while construct (i.e. if you always want the loop to iterate at least once), which is why it exists in the first place.
Is it an accepted practice?
If you use it appropriately, then yes absolutely.
It seems like it is equivalent to a plain while loop except that its first iteration happens before checking the conditional, if that is even true.
That's right. You can read more about do-while in its tutorial.
This example maybe help you be clearer:
int i = 3;
System.out.print("while: ");
while (--i > 0){
System.out.print("x");
}
System.out.print("\ndo-while: ");
int j = 3;
do
{
System.out.print("x");
}while (--j > 0);
This prints
while: xx
do-while: xxx
A real time example.
There is a contest with 5 level.
In each level if you score 100 you can proceed to next level.
Less code for do while, but not for while.
boolean playContest()
{//do while
int level = 1;
int score;
do
{
score = 0;
score = play();
}while(score>99 && level++<6)
if(level>4 && score>99)
isWinner = true;
else
isWinner = false;
return isWinner;
}
boolean playContest()
{//while
int level = 1;
int score;
while(level <6)
{
score = 0;
score = play();
if(score < 100)
break;
level++;
}
if(level>4 && score>99)
isWinner = true;
else
isWinner = false;
return isWinner;
}
basic difference between while and do-while is do while will be executed at least once.
when do-while is best option?
in case when you want to execute some actions till you meet condition, of course you could achieve same thing by using while but early termination of loop with break, is nasty and ugly solution
When you want to execute the statement inside do for at least once, then you can go for it.
Directly from Docs
The difference between do-while and while is that do-while evaluates its expression at the bottom of the loop instead of the top. Therefore, the statements within the do block are always executed at least once,
do {
statement(s)
} while (expression);
No, there is no time a do-while loops is the only option, it is used for convenience when you do not want to repeat code.

How can I remove the while(true) from my loop in Java?

I've heard that using while(true) is a bad programming practice.
So, I've written the following code to get some numbers from a user (with default values). However, if the user happens to type in -1, then it will quit the program for them.
How should this be written then without a while(true)? I can think of a condition to make the while loop go off that will get caught right away without continuing on until the next iteration?
Here is how I have it now:
public static void main(String[] args)
{
System.out.println("QuickSelect!");
while (true)
{
System.out.println("Enter \"-1\" to quit.");
int arraySize = 10;
System.out.print("Enter the size of the array (10): ");
String line = input.nextLine();
if (line.matches("\\d+"))
{
arraySize = Integer.valueOf(line);
}
if (arraySize == -1) break;
int k = 1;
System.out.print("Enter the kth smallest element you desire (1): ");
line = input.nextLine();
if (line.matches("\\d+"))
{
k = Integer.valueOf(k);
}
if (k == -1) break;
List<Integer> randomData = generateRandomData(arraySize, 1, 100);
quickSelect(randomData, k);
}
}
while (true) is fine. Keep it.
If you had a more natural termination condition, I'd say to use it, but in this case, as the other answers prove, getting rid of while (true) makes the code harder to understand.
There is a Single Entry Single Exit (SESE) school of thought that suggests that you should not use break, continue or abuse exceptions to do the same for some value of abuse). I believe the idea here is not that you should use some auxiliary flag variable, but to clearly state the postcondition of the loop. This makes it tractable to formerly reason about the loop. Obviously use the stands-to-reason form of reasoning, so it is unpopular with the unwashed masses (such as myself).
public static void main(String[] args) {
...
do {
...
if (arraySize == -1) {
...
if (k != -1) {
...
}
}
} while (arraySze == -1 || k == -1);
...
}
Real code would be more complex and you would naturally(!) separate out the inputing, outputting and core "business" logic, which would make it easier to see what is going on.
bool exit = false;
while (!exit) {
...
...
if (k == -1) {
exit = true;
}
else {
List <Integer> ....;
quickselect(.......);
}
}
But as has been said before, your while loop is a valid usage in this situation. The other options would simply build upon the if statements to check for the boolean and exit.
While having a loop like this is not technically wrong, some people will argue that it is not as readable as the following:
bool complete = false;
while (!complete)
{
if (arraySize == -1)
{
complete = true;
break;
}
}
Additionally, it is sometimes a good idea to have a safety loop counter that checks to make sure the loop has not gone through, say, 100 million iterations, or some number much larger than you would expect for the loop body. This is a secure way of making sure bugs don't cause your program to 'hang'. Instead, you can give the user a friendly "We're sorry but you've discovered a bug.. program will now quit.." where you set 'complete' to true and you end the program or do additional error handling. I've seen this in production code, and may or may not be something you would use.
while ( true ) is perfectly fine here, since the condition is really "while the user doesn't want to quit"!
Alternatively you could prompt for both the inputs on one line to simplify the logic, and use "q" for quit: this allows you to refactor the loop to "while ( !line.equals("q") )".
The problem is that you're doing an awful lot in that loop, rather than separating the functionality into simple methods.
If you want to stick to a procedural approach, you could move the reading of the array size and k into separate methods, and use the fact that the result of an assignment is the assigned value:
for (int arraySize; ( arraySize = readArraySize ( input ) ) != -1;) {
final int k = readKthSmallestElement ( input );
List<Integer> randomData = generateRandomData(arraySize, 1, 100);
quickSelect(randomData, k);
}
However that's still a bit ugly, and not well encapsulated. So instead of having the two != -1 tests on separate variables, encapsulate arraySize, k and randomData in an object, and create a method which reads the data from the input, and returns either a QuickSelect object or null if the user quits:
for ( QuickSelect select; ( select = readQuickSelect ( input ) ) != null; ) {
select.generateRandomData();
select.quickSelect();
}
You might even want to go to the next stage of creating a sequence of QuickSelect objects from the input, each of which encapsulate the data for one iteration:
for ( QuickSelect select : new QuickSelectReader ( input ) ) {
select.generateRandomData();
select.quickSelect();
}
where QuickSelectReader implements Iterable and the iterator has the logic to create a QuickSelect object which encapsulates arraySize, k, the list and the quick select operation. But that ends up being quite a lot more code than the procedural variants.
I'd only do that if I wanted to reuse it somewhere else; it's not worth the effort just to make main() pretty.
Also note that "-1" doesn't match the regex "\\d+", so you really do have an infinite loop.
If you really don't like while(true) you can always go for for(;;). I prefer the latter because it seems less redundant.

Categories

Resources