Related
I am working on a direction reduction problem from codewars and I can't figure out the error it is giving me. I know there have been similar cases as this but when I test my code on Visual Studio Code it works flawlessly so I'm not sure why codewars is giving me this error. The error I am getting is: "NORTH","SOUTH","SOUTH","EAST","WEST","NORTH": array lengths differed, expected.length=0 actual.length=6
Here is my code. Keep in mind that codewars tests it for you so my main method is not actually needed:
import java.lang.*;
public class DirReduction {
public static String[] dirReduc(String[] arr) {
int directionNS = 0;
int directionEW = 0;
for(int i = 0; i < arr.length; i++){
if(arr[i] == "NORTH"){
directionNS++;
} else if(arr[i] == "SOUTH"){
directionNS--;
} else if(arr[i] == "EAST"){
directionEW++;
} else if(arr[i] == "WEST"){
directionEW--;
} else {
System.out.println("Invalid Direction.");
}
}
String[] reducArray;
if(directionNS == 0 && directionEW == 0){
reducArray = new String[arr.length];
System.arraycopy(arr, 0, reducArray, 0, arr.length);
} else {
reducArray = new String[Math.abs(directionNS + directionEW)];
if(directionNS > 0){
for(int i = 0; i < directionNS; i++){
reducArray[i] = "NORTH";
}
} else if(directionNS < 0){
for(int i = 0; i > directionNS; i--){
reducArray[i] = "SOUTH";
}
}
if(directionEW > 0){
for(int i = 0; i < directionEW; i++){
reducArray[i] = "EAST";
}
} else if(directionEW < 0){
for(int i = 0; i > directionEW; i--){
reducArray[i] = "WEST";
}
}
}
return reducArray;
}
public static void main(String[] args){
String[] a = {"NORTH", "SOUTH", "SOUTH", "EAST", "WEST", "NORTH","WEST"};
String[] result = dirReduc(a);
for(int i = 0; i < result.length; i++){
System.out.println(result[i]);
}
}
}
There were four errors I found.
1) The case "NORTH","SOUTH","SOUTH","EAST","WEST","NORTH" should end up back where you started, so the array length should be 0, as requested by Codewars. To get that to work, I got rid of your special case for both direction counts being 0 and let what had been your else case deal with it by adding 0 and 0 to get the array size. [This error is the one mentioned in your question]
2) Your calculation of the array size was a little off. For example for "SOUTH" "EAST" it was calculating a size of 0 because they canceled out. Instead you need to sum the absolute values, not take the absolute value of the sum.
3) Your EAST/WEST in the reduced array were starting at position 0, and so overwriting NORTH/SOUTH. I made sure to offset into the array before doing those.
4) Your strategy of going negative on the for loop will try to write to a negative index if you have like SOUTH, EAST, SOUTH. I kept it positive using Math.abs
Here is the resulting method.
public static String[] dirReduc(String[] arr) {
int directionNS = 0;
int directionEW = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == "NORTH") {
directionNS++;
} else if (arr[i] == "SOUTH") {
directionNS--;
} else if (arr[i] == "EAST") {
directionEW++;
} else if (arr[i] == "WEST") {
directionEW--;
} else {
System.out.println("Invalid Direction.");
}
}
String[] reducArray;
//removed special case for ending up back where one started, that will be made a 0 length array as it should be
reducArray = new String[Math.abs(directionNS) + Math.abs(directionEW)]; //note have to take abs of each so one does not cancel out the other
if (directionNS > 0) {
for (int i = 0; i < directionNS; i++) {
reducArray[i] = "NORTH";
}
} else if (directionNS < 0) {
for(int i = 0; i < Math.abs(directionNS); i++){//keep the i's positive so they work in the array easily
reducArray[i] = "SOUTH";
}
}
if (directionEW > 0) {
for (int i = 0; i < directionEW; i++) {
reducArray[i + Math.abs(directionNS)] = "EAST"; //note have to start where north south left off
}
} else if (directionEW < 0) {
for(int i = 0; i < Math.abs(directionEW); i++){
reducArray[i + Math.abs(directionNS)] = "WEST";
}
}
return reducArray;
}`
I've got a nested loop construct like this:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
break; // Breaks out of the inner loop
}
}
}
Now how can I break out of both loops? I've looked at similar questions, but none concerns Java specifically. I couldn't apply these solutions because most used gotos.
I don't want to put the inner loop in a different method.
I don't want to return the loops. When breaking I'm finished with the execution of the loop block.
Like other answerers, I'd definitely prefer to put the loops in a different method, at which point you can just return to stop iterating completely. This answer just shows how the requirements in the question can be met.
You can use break with a label for the outer loop. For example:
public class Test {
public static void main(String[] args) {
outerloop:
for (int i=0; i < 5; i++) {
for (int j=0; j < 5; j++) {
if (i * j > 6) {
System.out.println("Breaking");
break outerloop;
}
System.out.println(i + " " + j);
}
}
System.out.println("Done");
}
}
This prints:
0 0
0 1
0 2
0 3
0 4
1 0
1 1
1 2
1 3
1 4
2 0
2 1
2 2
2 3
Breaking
Done
Technically the correct answer is to label the outer loop. In practice if you want to exit at any point inside an inner loop then you would be better off externalizing the code into a method (a static method if needs be) and then call it.
That would pay off for readability.
The code would become something like that:
private static String search(...)
{
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
return search;
}
}
}
return null;
}
Matching the example for the accepted answer:
public class Test {
public static void main(String[] args) {
loop();
System.out.println("Done");
}
public static void loop() {
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (i * j > 6) {
System.out.println("Breaking");
return;
}
System.out.println(i + " " + j);
}
}
}
}
You can use a named block around the loops:
search: {
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
break search;
}
}
}
}
I never use labels. It seems like a bad practice to get into. Here's what I would do:
boolean finished = false;
for (int i = 0; i < 5 && !finished; i++) {
for (int j = 0; j < 5; j++) {
if (i * j > 6) {
finished = true;
break;
}
}
}
You can use labels:
label1:
for (int i = 0;;) {
for (int g = 0;;) {
break label1;
}
}
Use a function:
public void doSomething(List<Type> types, List<Type> types2){
for(Type t1 : types){
for (Type t : types2) {
if (some condition) {
// Do something and return...
return;
}
}
}
}
You can use a temporary variable:
boolean outerBreak = false;
for (Type type : types) {
if(outerBreak) break;
for (Type t : types2) {
if (some condition) {
// Do something and break...
outerBreak = true;
break; // Breaks out of the inner loop
}
}
}
Depending on your function, you can also exit/return from the inner loop:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
return;
}
}
}
If you don't like breaks and gotos, you can use a "traditional" for loop instead the for-in, with an extra abort condition:
int a, b;
bool abort = false;
for (a = 0; a < 10 && !abort; a++) {
for (b = 0; b < 10 && !abort; b++) {
if (condition) {
doSomeThing();
abort = true;
}
}
}
Using 'break' keyword alone is not the appropriate way when you need to exit from more than one loops.
You can exit from immediate loop
No matter with how many loops your statement is surrounded with.
You can use 'break' with a label!
Here I've used the label "abc"
You can write your code as following, within any function in Java
This code shows how to exit from the most outer loop
abc:
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
if (k == 1){
break abc;
}
}
}
}
Also you can use break statement to exit from any loop in a nested loop.
for (int i = 0; i < 10; i++) {
abc:for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
if (k == 1){
break abc;
}
}
}
}
The following code shows an example of exiting from the innermost loop.
In other works,after executing the following code, you are at the outside of the loop of 'k' variables and still inside the loop of 'j' and 'i' variables.
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
if (k == 1){
break;
}
}
}
}
I needed to do a similar thing, but I chose not to use the enhanced for loop to do it.
int s = type.size();
for (int i = 0; i < s; i++) {
for (int j = 0; j < t.size(); j++) {
if (condition) {
// do stuff after which you want
// to completely break out of both loops
s = 0; // enables the _main_ loop to terminate
break;
}
}
}
I prefer to add an explicit "exit" to the loop tests. It makes it clear to
any casual reader that the loop may terminate early.
boolean earlyExit = false;
for(int i = 0 ; i < 10 && !earlyExit; i++) {
for(int j = 0 ; i < 10 && !earlyExit; j++) { earlyExit = true; }
}
Java 8 Stream solution:
List<Type> types1 = ...
List<Type> types2 = ...
types1.stream()
.flatMap(type1 -> types2.stream().map(type2 -> new Type[]{type1, type2}))
.filter(types -> /**some condition**/)
.findFirst()
.ifPresent(types -> /**do something**/);
Labeled break concept is used to break out nested loops in java, by using labeled break you can break nesting of loops at any position.
Example 1:
loop1:
for(int i= 0; i<6; i++){
for(int j=0; j<5; j++){
if(i==3)
break loop1;
}
}
suppose there are 3 loops and you want to terminate the loop3:
Example 2:
loop3:
for(int i= 0; i<6; i++){
loop2:
for(int k= 0; k<6; k++){
loop1:
for(int j=0; j<5; j++){
if(i==3)
break loop3;
}
}
}
Usually in such cases, it is coming in scope of more meaningful logic, let's say some searching or manipulating over some of the iterated 'for'-objects in question, so I usually use the functional approach:
public Object searching(Object[] types) { // Or manipulating
List<Object> typesReferences = new ArrayList<Object>();
List<Object> typesReferences2 = new ArrayList<Object>();
for (Object type : typesReferences) {
Object o = getByCriterion(typesReferences2, type);
if(o != null) return o;
}
return null;
}
private Object getByCriterion(List<Object> typesReferences2, Object criterion) {
for (Object typeReference : typesReferences2) {
if(typeReference.equals(criterion)) {
// here comes other complex or specific logic || typeReference.equals(new Object())
return typeReference;
}
}
return null;
}
Major cons:
roughly twice more lines
more consumption of computing cycles, meaning it is slower from algorithmic point-of-view
more typing work
The pros:
the higher ratio to separation of concerns because of functional granularity
the higher ratio of re-usability and control of
searching/manipulating logic without
the methods are not long, thus they are more compact and easier to comprehend
higher ratio of readability
So it is just handling the case via a different approach.
Basically a question to the author of this question: what do you consider of this approach?
You can break from all loops without using any label: and flags.
It's just tricky solution.
Here condition1 is the condition which is used to break from loop K and J.
And condition2 is the condition which is used to break from loop K , J and I.
For example:
public class BreakTesting {
public static void main(String[] args) {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
for (int k = 0; k < 9; k++) {
if (condition1) {
System.out.println("Breaking from Loop K and J");
k = 9;
j = 9;
}
if (condition2) {
System.out.println("Breaking from Loop K, J and I");
k = 9;
j = 9;
i = 9;
}
}
}
}
System.out.println("End of I , J , K");
}
}
Demo
public static void main(String[] args) {
outer:
while (true) {
while (true) {
break outer;
}
}
}
Best and Easy Method..
outerloop:
for(int i=0; i<10; i++){
// here we can break Outer loop by
break outerloop;
innerloop:
for(int i=0; i<10; i++){
// here we can break innerloop by
break innerloop;
}
}
Use Labels.
INNER:for(int j = 0; j < numbers.length; j++) {
System.out.println("Even number: " + i + ", break from INNER label");
break INNER;
}
Refer to this article
It's fairly easy to use label, You can break the outer loop from inner loop using the label, Consider the example below,
public class Breaking{
public static void main(String[] args) {
outerscope:
for (int i=0; i < 5; i++) {
for (int j=0; j < 5; j++) {
if (condition) {
break outerscope;
}
}
}
}
}
Another approach is to use the breaking variable/flag to keep track of required break. consider the following example.
public class Breaking{
public static void main(String[] args) {
boolean isBreaking = false;
for (int i=0; i < 5; i++) {
for (int j=0; j < 5; j++) {
if (condition) {
isBreaking = true;
break;
}
}
if(isBreaking){
break;
}
}
}
}
However, I prefer using the first approach.
boolean broken = false; // declared outside of the loop for efficiency
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
broken = true;
break;
}
}
if (broken) {
break;
}
}
If it is inside some function why don't you just return it:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
return value;
}
}
}
Rather unusual approach but in terms of code length (not performance) this is the easiest thing you could do:
for(int i = 0; i++; i < j) {
if(wanna exit) {
i = i + j; // if more nested, also add the
// maximum value for the other loops
}
}
Another one solution, mentioned without example (it actually works in prod code).
try {
for (Type type : types) {
for (Type t : types2) {
if (some condition #1) {
// Do something and break the loop.
throw new BreakLoopException();
}
}
}
}
catch (BreakLoopException e) {
// Do something on look breaking.
}
Of course BreakLoopException should be internal, private and accelerated with no-stack-trace:
private static class BreakLoopException extends Exception {
#Override
public StackTraceElement[] getStackTrace() {
return new StackTraceElement[0];
}
}
Demo for break, continue, and label:
Java keywords break and continue have a default value. It's the "nearest loop", and today, after a few years of using Java, I just got it!
It's seem used rare, but useful.
import org.junit.Test;
/**
* Created by cui on 17-5-4.
*/
public class BranchLabel {
#Test
public void test() {
System.out.println("testBreak");
testBreak();
System.out.println("testBreakLabel");
testBreakLabel();
System.out.println("testContinue");
testContinue();
System.out.println("testContinueLabel");
testContinueLabel();
}
/**
testBreak
a=0,b=0
a=0,b=1
a=1,b=0
a=1,b=1
a=2,b=0
a=2,b=1
a=3,b=0
a=3,b=1
a=4,b=0
a=4,b=1
*/
public void testBreak() {
for (int a = 0; a < 5; a++) {
for (int b = 0; b < 5; b++) {
if (b == 2) {
break;
}
System.out.println("a=" + a + ",b=" + b);
}
}
}
/**
testContinue
a=0,b=0
a=0,b=1
a=0,b=3
a=0,b=4
a=1,b=0
a=1,b=1
a=1,b=3
a=1,b=4
a=2,b=0
a=2,b=1
a=2,b=3
a=2,b=4
a=3,b=0
a=3,b=1
a=3,b=3
a=3,b=4
a=4,b=0
a=4,b=1
a=4,b=3
a=4,b=4
*/
public void testContinue() {
for (int a = 0; a < 5; a++) {
for (int b = 0; b < 5; b++) {
if (b == 2) {
continue;
}
System.out.println("a=" + a + ",b=" + b);
}
}
}
/**
testBreakLabel
a=0,b=0,c=0
a=0,b=0,c=1
* */
public void testBreakLabel() {
anyName:
for (int a = 0; a < 5; a++) {
for (int b = 0; b < 5; b++) {
for (int c = 0; c < 5; c++) {
if (c == 2) {
break anyName;
}
System.out.println("a=" + a + ",b=" + b + ",c=" + c);
}
}
}
}
/**
testContinueLabel
a=0,b=0,c=0
a=0,b=0,c=1
a=1,b=0,c=0
a=1,b=0,c=1
a=2,b=0,c=0
a=2,b=0,c=1
a=3,b=0,c=0
a=3,b=0,c=1
a=4,b=0,c=0
a=4,b=0,c=1
*/
public void testContinueLabel() {
anyName:
for (int a = 0; a < 5; a++) {
for (int b = 0; b < 5; b++) {
for (int c = 0; c < 5; c++) {
if (c == 2) {
continue anyName;
}
System.out.println("a=" + a + ",b=" + b + ",c=" + c);
}
}
}
}
}
for (int j = 0; j < 5; j++) //inner loop should be replaced with
for (int j = 0; j < 5 && !exitloops; j++).
Here, in this case complete nested loops should be exit if condition is True . But if we use exitloops only to the upper loop
for (int i = 0; i < 5 && !exitloops; i++) //upper loop
Then inner loop will continues, because there is no extra flag that notify this inner loop to exit.
Example : if i = 3 and j=2 then condition is false. But in next iteration of inner loop j=3 then condition (i*j) become 9 which is true but inner loop will be continue till j become 5.
So, it must use exitloops to the inner loops too.
boolean exitloops = false;
for (int i = 0; i < 5 && !exitloops; i++) { //here should exitloops as a Conditional Statement to get out from the loops if exitloops become true.
for (int j = 0; j < 5 && !exitloops; j++) { //here should also use exitloops as a Conditional Statement.
if (i * j > 6) {
exitloops = true;
System.out.println("Inner loop still Continues For i * j is => "+i*j);
break;
}
System.out.println(i*j);
}
}
Like #1800 INFORMATION suggestion, use the condition that breaks the inner loop as a condition on the outer loop:
boolean hasAccess = false;
for (int i = 0; i < x && hasAccess == false; i++){
for (int j = 0; j < y; j++){
if (condition == true){
hasAccess = true;
break;
}
}
}
Java does not have a goto feature like there is in C++. But still, goto is a reserved keyword in Java. They might implement it in the future. For your question, the answer is that there is something called label in Java to which you can apply a continue and break statement. Find the code below:
public static void main(String ...args) {
outerLoop: for(int i=0;i<10;i++) {
for(int j=10;j>0;j--) {
System.out.println(i+" "+j);
if(i==j) {
System.out.println("Condition Fulfilled");
break outerLoop;
}
}
}
System.out.println("Got out of the outer loop");
}
If it's a new implementation, you can try rewriting the logic as if-else_if-else statements.
while(keep_going) {
if(keep_going && condition_one_holds) {
// Code
}
if(keep_going && condition_two_holds) {
// Code
}
if(keep_going && condition_three_holds) {
// Code
}
if(keep_going && something_goes_really_bad) {
keep_going=false;
}
if(keep_going && condition_four_holds) {
// Code
}
if(keep_going && condition_five_holds) {
// Code
}
}
Otherwise you can try setting a flag when that special condition has occured and check for that flag in each of your loop-conditions.
something_bad_has_happened = false;
while(something is true && !something_bad_has_happened){
// Code, things happen
while(something else && !something_bad_has_happened){
// Lots of code, things happens
if(something happened){
-> Then control should be returned ->
something_bad_has_happened=true;
continue;
}
}
if(something_bad_has_happened) { // The things below will not be executed
continue;
}
// Other things may happen here as well, but they will not be executed
// once control is returned from the inner cycle.
}
HERE! So, while a simple break will not work, it can be made to work using continue.
If you are simply porting the logic from one programming language to Java and just want to get the thing working you can try using labels.
You just use label for breaking inner loops
public class Test {
public static void main(String[] args) {
outerloop:
for (int i=0; i < 5; i++) {
for (int j=0; j < 5; j++) {
if (i * j > 6) {
System.out.println("Breaking");
break outerloop;
}
System.out.println(i + " " + j);
}
}
System.out.println("Done");
}
}
You can do the following:
set a local variable to false
set that variable true in the first loop, when you want to break
then you can check in the outer loop, that whether the condition is set then break from the outer loop as well.
boolean isBreakNeeded = false;
for (int i = 0; i < some.length; i++) {
for (int j = 0; j < some.lengthasWell; j++) {
//want to set variable if (){
isBreakNeeded = true;
break;
}
if (isBreakNeeded) {
break; //will make you break from the outer loop as well
}
}
I've got a nested loop construct like this:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
break; // Breaks out of the inner loop
}
}
}
Now how can I break out of both loops? I've looked at similar questions, but none concerns Java specifically. I couldn't apply these solutions because most used gotos.
I don't want to put the inner loop in a different method.
I don't want to return the loops. When breaking I'm finished with the execution of the loop block.
Like other answerers, I'd definitely prefer to put the loops in a different method, at which point you can just return to stop iterating completely. This answer just shows how the requirements in the question can be met.
You can use break with a label for the outer loop. For example:
public class Test {
public static void main(String[] args) {
outerloop:
for (int i=0; i < 5; i++) {
for (int j=0; j < 5; j++) {
if (i * j > 6) {
System.out.println("Breaking");
break outerloop;
}
System.out.println(i + " " + j);
}
}
System.out.println("Done");
}
}
This prints:
0 0
0 1
0 2
0 3
0 4
1 0
1 1
1 2
1 3
1 4
2 0
2 1
2 2
2 3
Breaking
Done
Technically the correct answer is to label the outer loop. In practice if you want to exit at any point inside an inner loop then you would be better off externalizing the code into a method (a static method if needs be) and then call it.
That would pay off for readability.
The code would become something like that:
private static String search(...)
{
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
return search;
}
}
}
return null;
}
Matching the example for the accepted answer:
public class Test {
public static void main(String[] args) {
loop();
System.out.println("Done");
}
public static void loop() {
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (i * j > 6) {
System.out.println("Breaking");
return;
}
System.out.println(i + " " + j);
}
}
}
}
You can use a named block around the loops:
search: {
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
break search;
}
}
}
}
I never use labels. It seems like a bad practice to get into. Here's what I would do:
boolean finished = false;
for (int i = 0; i < 5 && !finished; i++) {
for (int j = 0; j < 5; j++) {
if (i * j > 6) {
finished = true;
break;
}
}
}
You can use labels:
label1:
for (int i = 0;;) {
for (int g = 0;;) {
break label1;
}
}
Use a function:
public void doSomething(List<Type> types, List<Type> types2){
for(Type t1 : types){
for (Type t : types2) {
if (some condition) {
// Do something and return...
return;
}
}
}
}
You can use a temporary variable:
boolean outerBreak = false;
for (Type type : types) {
if(outerBreak) break;
for (Type t : types2) {
if (some condition) {
// Do something and break...
outerBreak = true;
break; // Breaks out of the inner loop
}
}
}
Depending on your function, you can also exit/return from the inner loop:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
return;
}
}
}
If you don't like breaks and gotos, you can use a "traditional" for loop instead the for-in, with an extra abort condition:
int a, b;
bool abort = false;
for (a = 0; a < 10 && !abort; a++) {
for (b = 0; b < 10 && !abort; b++) {
if (condition) {
doSomeThing();
abort = true;
}
}
}
Using 'break' keyword alone is not the appropriate way when you need to exit from more than one loops.
You can exit from immediate loop
No matter with how many loops your statement is surrounded with.
You can use 'break' with a label!
Here I've used the label "abc"
You can write your code as following, within any function in Java
This code shows how to exit from the most outer loop
abc:
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
if (k == 1){
break abc;
}
}
}
}
Also you can use break statement to exit from any loop in a nested loop.
for (int i = 0; i < 10; i++) {
abc:for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
if (k == 1){
break abc;
}
}
}
}
The following code shows an example of exiting from the innermost loop.
In other works,after executing the following code, you are at the outside of the loop of 'k' variables and still inside the loop of 'j' and 'i' variables.
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
if (k == 1){
break;
}
}
}
}
I needed to do a similar thing, but I chose not to use the enhanced for loop to do it.
int s = type.size();
for (int i = 0; i < s; i++) {
for (int j = 0; j < t.size(); j++) {
if (condition) {
// do stuff after which you want
// to completely break out of both loops
s = 0; // enables the _main_ loop to terminate
break;
}
}
}
I prefer to add an explicit "exit" to the loop tests. It makes it clear to
any casual reader that the loop may terminate early.
boolean earlyExit = false;
for(int i = 0 ; i < 10 && !earlyExit; i++) {
for(int j = 0 ; i < 10 && !earlyExit; j++) { earlyExit = true; }
}
Java 8 Stream solution:
List<Type> types1 = ...
List<Type> types2 = ...
types1.stream()
.flatMap(type1 -> types2.stream().map(type2 -> new Type[]{type1, type2}))
.filter(types -> /**some condition**/)
.findFirst()
.ifPresent(types -> /**do something**/);
Labeled break concept is used to break out nested loops in java, by using labeled break you can break nesting of loops at any position.
Example 1:
loop1:
for(int i= 0; i<6; i++){
for(int j=0; j<5; j++){
if(i==3)
break loop1;
}
}
suppose there are 3 loops and you want to terminate the loop3:
Example 2:
loop3:
for(int i= 0; i<6; i++){
loop2:
for(int k= 0; k<6; k++){
loop1:
for(int j=0; j<5; j++){
if(i==3)
break loop3;
}
}
}
Usually in such cases, it is coming in scope of more meaningful logic, let's say some searching or manipulating over some of the iterated 'for'-objects in question, so I usually use the functional approach:
public Object searching(Object[] types) { // Or manipulating
List<Object> typesReferences = new ArrayList<Object>();
List<Object> typesReferences2 = new ArrayList<Object>();
for (Object type : typesReferences) {
Object o = getByCriterion(typesReferences2, type);
if(o != null) return o;
}
return null;
}
private Object getByCriterion(List<Object> typesReferences2, Object criterion) {
for (Object typeReference : typesReferences2) {
if(typeReference.equals(criterion)) {
// here comes other complex or specific logic || typeReference.equals(new Object())
return typeReference;
}
}
return null;
}
Major cons:
roughly twice more lines
more consumption of computing cycles, meaning it is slower from algorithmic point-of-view
more typing work
The pros:
the higher ratio to separation of concerns because of functional granularity
the higher ratio of re-usability and control of
searching/manipulating logic without
the methods are not long, thus they are more compact and easier to comprehend
higher ratio of readability
So it is just handling the case via a different approach.
Basically a question to the author of this question: what do you consider of this approach?
You can break from all loops without using any label: and flags.
It's just tricky solution.
Here condition1 is the condition which is used to break from loop K and J.
And condition2 is the condition which is used to break from loop K , J and I.
For example:
public class BreakTesting {
public static void main(String[] args) {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
for (int k = 0; k < 9; k++) {
if (condition1) {
System.out.println("Breaking from Loop K and J");
k = 9;
j = 9;
}
if (condition2) {
System.out.println("Breaking from Loop K, J and I");
k = 9;
j = 9;
i = 9;
}
}
}
}
System.out.println("End of I , J , K");
}
}
Demo
public static void main(String[] args) {
outer:
while (true) {
while (true) {
break outer;
}
}
}
Best and Easy Method..
outerloop:
for(int i=0; i<10; i++){
// here we can break Outer loop by
break outerloop;
innerloop:
for(int i=0; i<10; i++){
// here we can break innerloop by
break innerloop;
}
}
Use Labels.
INNER:for(int j = 0; j < numbers.length; j++) {
System.out.println("Even number: " + i + ", break from INNER label");
break INNER;
}
Refer to this article
It's fairly easy to use label, You can break the outer loop from inner loop using the label, Consider the example below,
public class Breaking{
public static void main(String[] args) {
outerscope:
for (int i=0; i < 5; i++) {
for (int j=0; j < 5; j++) {
if (condition) {
break outerscope;
}
}
}
}
}
Another approach is to use the breaking variable/flag to keep track of required break. consider the following example.
public class Breaking{
public static void main(String[] args) {
boolean isBreaking = false;
for (int i=0; i < 5; i++) {
for (int j=0; j < 5; j++) {
if (condition) {
isBreaking = true;
break;
}
}
if(isBreaking){
break;
}
}
}
}
However, I prefer using the first approach.
boolean broken = false; // declared outside of the loop for efficiency
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
broken = true;
break;
}
}
if (broken) {
break;
}
}
If it is inside some function why don't you just return it:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
return value;
}
}
}
Rather unusual approach but in terms of code length (not performance) this is the easiest thing you could do:
for(int i = 0; i++; i < j) {
if(wanna exit) {
i = i + j; // if more nested, also add the
// maximum value for the other loops
}
}
Another one solution, mentioned without example (it actually works in prod code).
try {
for (Type type : types) {
for (Type t : types2) {
if (some condition #1) {
// Do something and break the loop.
throw new BreakLoopException();
}
}
}
}
catch (BreakLoopException e) {
// Do something on look breaking.
}
Of course BreakLoopException should be internal, private and accelerated with no-stack-trace:
private static class BreakLoopException extends Exception {
#Override
public StackTraceElement[] getStackTrace() {
return new StackTraceElement[0];
}
}
Demo for break, continue, and label:
Java keywords break and continue have a default value. It's the "nearest loop", and today, after a few years of using Java, I just got it!
It's seem used rare, but useful.
import org.junit.Test;
/**
* Created by cui on 17-5-4.
*/
public class BranchLabel {
#Test
public void test() {
System.out.println("testBreak");
testBreak();
System.out.println("testBreakLabel");
testBreakLabel();
System.out.println("testContinue");
testContinue();
System.out.println("testContinueLabel");
testContinueLabel();
}
/**
testBreak
a=0,b=0
a=0,b=1
a=1,b=0
a=1,b=1
a=2,b=0
a=2,b=1
a=3,b=0
a=3,b=1
a=4,b=0
a=4,b=1
*/
public void testBreak() {
for (int a = 0; a < 5; a++) {
for (int b = 0; b < 5; b++) {
if (b == 2) {
break;
}
System.out.println("a=" + a + ",b=" + b);
}
}
}
/**
testContinue
a=0,b=0
a=0,b=1
a=0,b=3
a=0,b=4
a=1,b=0
a=1,b=1
a=1,b=3
a=1,b=4
a=2,b=0
a=2,b=1
a=2,b=3
a=2,b=4
a=3,b=0
a=3,b=1
a=3,b=3
a=3,b=4
a=4,b=0
a=4,b=1
a=4,b=3
a=4,b=4
*/
public void testContinue() {
for (int a = 0; a < 5; a++) {
for (int b = 0; b < 5; b++) {
if (b == 2) {
continue;
}
System.out.println("a=" + a + ",b=" + b);
}
}
}
/**
testBreakLabel
a=0,b=0,c=0
a=0,b=0,c=1
* */
public void testBreakLabel() {
anyName:
for (int a = 0; a < 5; a++) {
for (int b = 0; b < 5; b++) {
for (int c = 0; c < 5; c++) {
if (c == 2) {
break anyName;
}
System.out.println("a=" + a + ",b=" + b + ",c=" + c);
}
}
}
}
/**
testContinueLabel
a=0,b=0,c=0
a=0,b=0,c=1
a=1,b=0,c=0
a=1,b=0,c=1
a=2,b=0,c=0
a=2,b=0,c=1
a=3,b=0,c=0
a=3,b=0,c=1
a=4,b=0,c=0
a=4,b=0,c=1
*/
public void testContinueLabel() {
anyName:
for (int a = 0; a < 5; a++) {
for (int b = 0; b < 5; b++) {
for (int c = 0; c < 5; c++) {
if (c == 2) {
continue anyName;
}
System.out.println("a=" + a + ",b=" + b + ",c=" + c);
}
}
}
}
}
for (int j = 0; j < 5; j++) //inner loop should be replaced with
for (int j = 0; j < 5 && !exitloops; j++).
Here, in this case complete nested loops should be exit if condition is True . But if we use exitloops only to the upper loop
for (int i = 0; i < 5 && !exitloops; i++) //upper loop
Then inner loop will continues, because there is no extra flag that notify this inner loop to exit.
Example : if i = 3 and j=2 then condition is false. But in next iteration of inner loop j=3 then condition (i*j) become 9 which is true but inner loop will be continue till j become 5.
So, it must use exitloops to the inner loops too.
boolean exitloops = false;
for (int i = 0; i < 5 && !exitloops; i++) { //here should exitloops as a Conditional Statement to get out from the loops if exitloops become true.
for (int j = 0; j < 5 && !exitloops; j++) { //here should also use exitloops as a Conditional Statement.
if (i * j > 6) {
exitloops = true;
System.out.println("Inner loop still Continues For i * j is => "+i*j);
break;
}
System.out.println(i*j);
}
}
Like #1800 INFORMATION suggestion, use the condition that breaks the inner loop as a condition on the outer loop:
boolean hasAccess = false;
for (int i = 0; i < x && hasAccess == false; i++){
for (int j = 0; j < y; j++){
if (condition == true){
hasAccess = true;
break;
}
}
}
Java does not have a goto feature like there is in C++. But still, goto is a reserved keyword in Java. They might implement it in the future. For your question, the answer is that there is something called label in Java to which you can apply a continue and break statement. Find the code below:
public static void main(String ...args) {
outerLoop: for(int i=0;i<10;i++) {
for(int j=10;j>0;j--) {
System.out.println(i+" "+j);
if(i==j) {
System.out.println("Condition Fulfilled");
break outerLoop;
}
}
}
System.out.println("Got out of the outer loop");
}
If it's a new implementation, you can try rewriting the logic as if-else_if-else statements.
while(keep_going) {
if(keep_going && condition_one_holds) {
// Code
}
if(keep_going && condition_two_holds) {
// Code
}
if(keep_going && condition_three_holds) {
// Code
}
if(keep_going && something_goes_really_bad) {
keep_going=false;
}
if(keep_going && condition_four_holds) {
// Code
}
if(keep_going && condition_five_holds) {
// Code
}
}
Otherwise you can try setting a flag when that special condition has occured and check for that flag in each of your loop-conditions.
something_bad_has_happened = false;
while(something is true && !something_bad_has_happened){
// Code, things happen
while(something else && !something_bad_has_happened){
// Lots of code, things happens
if(something happened){
-> Then control should be returned ->
something_bad_has_happened=true;
continue;
}
}
if(something_bad_has_happened) { // The things below will not be executed
continue;
}
// Other things may happen here as well, but they will not be executed
// once control is returned from the inner cycle.
}
HERE! So, while a simple break will not work, it can be made to work using continue.
If you are simply porting the logic from one programming language to Java and just want to get the thing working you can try using labels.
You just use label for breaking inner loops
public class Test {
public static void main(String[] args) {
outerloop:
for (int i=0; i < 5; i++) {
for (int j=0; j < 5; j++) {
if (i * j > 6) {
System.out.println("Breaking");
break outerloop;
}
System.out.println(i + " " + j);
}
}
System.out.println("Done");
}
}
You can do the following:
set a local variable to false
set that variable true in the first loop, when you want to break
then you can check in the outer loop, that whether the condition is set then break from the outer loop as well.
boolean isBreakNeeded = false;
for (int i = 0; i < some.length; i++) {
for (int j = 0; j < some.lengthasWell; j++) {
//want to set variable if (){
isBreakNeeded = true;
break;
}
if (isBreakNeeded) {
break; //will make you break from the outer loop as well
}
}
I'm implementing Insertionsort for university. My code works in theory, but my for-loop is executed only once instead of books.size() (which is 5, I've tested that). I tried it using the number 5, but it won't work and I'm kind of desperate because I can't seem to find the error.
Here is my code:
static void sort(LinkedList<Book> books)
{
int i;
for ( i = 0; i < books.size(); i++)
{
Book temp = books.get(i);
books.remove(i);
for (int j = 0; j < books.size(); j++) {
if (books.get(j).compareTo(temp) > 0) {
books.add(j, temp);
return;
}
}
books.add(temp);
}
}
The compareTo function of the Book-Class looks like the following:
public int compareTo(Book other)
{
int iAutor = autor.compareTo(other.getAutor());
if (iAutor != 0)
return iAutor;
else
{
int iTitel = titel.compareTo(other.getTitel());
if (iTitel != 0)
return iTitel;
else
{
if (this.auflage < other.getAuflage())
return -1;
else if (this.auflage > other.getAuflage())
return 1;
else
return 0;
}
}
}
Am I simply blind?
You need to swap return for break and fix the logic to avoid adding the book twice. There may be more elegant ways than this, but it should work:
int i;
for ( i = 0; i < books.size(); i++)
{
Book temp = books.get(i);
books.remove(i);
bool added = false;
for (int j = 0; j < books.size(); j++) {
if (books.get(j).compareTo(temp) > 0) {
books.add(j, temp);
added = true;
break;
}
}
if (!added) {
books.add(temp);
}
}
Well, I found out how to solve it, just if someone has the same problem (don't think that will happen, but it's a good habit I hope).
As #Klitos Kyriacou pointed out right, I had a twist in my thoughts about the process of Insertionsorting.
The solution is changing the loops in the following:
static void sort(LinkedList<Book> books) {
Book temp;
for (int counter = 0; counter < books.size(); counter++) {
temp = books.get(counter);
for (int position = 0; position < counter; position++)
{
if (temp.compareTo(books.get(position)) < 0)
{
books.remove(counter);
books.add(position, temp);
break;
}
}
}
}
I am a beginner android "developer" developing a chess app.
There is one variable in the InGameActivity class called currentBoardState which is public static. Every ChessPiece has a boolean[][] possibleMoves. This following method will take the possibleMoves and determine if any of the moves will cause the player to put him/herself in check and set it to false because it is no longer a possible move.
#Override
public void eliminateMovesThatPutYouInCheck() {
ChessPiece[][] originalBoard = InGameActivity.currentBoardState;
final ChessPiece emptyPiece = new EmptyPiece(Color.EMPTY);
final ChessPiece tempKnight = new Knight(side);
//This block eliminates moves that will cause a player
//to put him/her self in check.
InGameActivity.currentBoardState[x][y] = emptyPiece;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (possibleMoves[i][j] == true) {
tempKnight.x = i;
tempKnight.y = j;
InGameActivity.currentBoardState[i][j] = tempKnight;
if (InGameActivity.isPlayerInCheck(side)) {
possibleMoves[i][j] = false;
}
InGameActivity.currentBoardState[i][j] = emptyPiece;
}
}
}
InGameActivity.currentBoardState = originalBoard;
}
The problem is, my currentBoardState variable is being messed up and I dont know why, ive saved the value then reset it at the end of the method why is it losing its values?
EDIT: Here is the isPlayerInCheck method if you need it, thank you.
public static boolean isPlayerInCheck(Color side) {
List<boolean[][]> opponentsMoves = new ArrayList<boolean[][]>();
int xKing = -1;
int yKing = -1;
if (side.equals(Color.WHITE)) {
xKing = whiteKing.x;
yKing = whiteKing.y;
} else {
xKing = blackKing.x;
yKing = blackKing.y;
}
if (side.equals(Color.WHITE)) {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (currentBoardState[i][j].isBlack()) {
opponentsMoves.add(currentBoardState[i][j].possibleMoves);
}
}
}
for (boolean[][] b : opponentsMoves) {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (b[xKing][yKing] == true) {
return true;
}
}
}
}
return false;
} else {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (currentBoardState[i][j].isWhite()) {
opponentsMoves.add(currentBoardState[i][j].possibleMoves);
}
if (currentBoardState[i][j].isBlack() && currentBoardState[i][j].getType().equals(Type.KING)) {
xKing = currentBoardState[i][j].x;
yKing = currentBoardState[i][j].y;
}
}
}
for (boolean[][] b : opponentsMoves) {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (b[xKing][yKing] == true) {
return true;
}
}
}
}
return false;
}
}
Also, I understand and appreciate that my code is probably very inefficient and the design is horrible for chess but that isn't really what I am concerned about at the moment.
I'm assuming by messed up you mean the currentBoardState variable isn't being "reset" to the original board.
This is due to this line:
ChessPiece[][] originalBoard = InGameActivity.currentBoardState;
passing a reference of the current board state to the variable originalBoard.
As you make you modification to currentBoardState, since the originalBoard variable points to the same object, it gets modified as well.
Copy the array to the originalBoard variable like such:
ChessPiece[][] originalBoard = new ChessPiece[InGameActivity.currentBoardState.length][];
for(int i = 0; i < InGameActivity.currentBoardState.length; i++){
ChessPiece[] pieces = InGameActivity.currentBoardState[i];
int len = pieces.length;
originalBoard[i] = new ChessPiece[len];
System.arraycopy(pieces, 0, originalBoard[i], 0, len);
}
//Rest of code here...
Only when you copy by value does a actual copy of the data exist. Disregarding primitive types and some immutable data, using the assignment operator = merely assigns the reference of the RHS to the LHS.
If I understand your code correctly, I think you need to copy the original to a new array, for example:
ChessPiece[][] originalBoard = Arrays.copyOf(
InGameActivity.currentBoardState, InGameActivity.currentBoardState.length);
This prevents modification of the original array.
You have the problem here:
if (possibleMoves[i][j])
{
tempKnight.x = i;
tempKnight.y = j;
InGameActivity.currentBoardState[i][j] = tempKnight;
if (InGameActivity.isPlayerInCheck(side))
{
possibleMoves[i][j] = false;
}
/** whatever was before next line resets the value at i,j: puts empty piece here */
InGameActivity.currentBoardState[i][j] = emptyPiece;
}