Flexible number of for-loops - Java - java

I'm looking for a way to use a flexible amount of for-loops or some solution that will do the same. Basically I want a variable to go from 0 to 100 in each loop and go through all combinations. The for-loops are nested so if I am looking for a solution for two agents I have:
for(int i = 0; i<=100; i++){
for(int j = 0; j<=100, j++){
//do some stuff with i and j
}
}
but I do not ex ante know how many agents will be needed so I'm looking for a flexible way to get the same result. This might be quite an easy question but I was not able to find a threat which gave me a working solution.
EDIT: It was pointed out to me that the question is not clear enough, I will try to demonstrate what I am trying to achieve:
Let's say I have n agents, if n == 1 then I would need this:
for(int j = 0; j<=100, j++){
//do some stuff with j
}
for n == 2 I would want:
for(int i = 0; i<=100; i++){
for(int j = 0; j<=100, j++){
//do some stuff with i and j
}
}
for n == 3 another for look around these existing ones and so on, but it need to be flexible as the user is asked for n and can type in any integer.
//EndEDIT I hope this made it clearer
Thank you in advance!

I think the easiest way to achieve this is recursively.
Assuming you want the same limits on each range (i.e. that i,j,k etc go from 0..100), you can do it like so:
void recursive(List<Integer> values, int depth) {
if (values.size() == depth) {
// Do the thing you want to do with the values, i.e. the "innermost loop".
} else {
// This is intentionally Integer, so that remove removes that value, not the element at that index.
for (Integer a = 0; a <= 100; ++a) {
values.add(a);
recursive(values, depth);
values.remove(a);
}
}
}
While there are fewer than depth values in the list, this adds each value in the range into the list in turn, and recurses.
Once there are enough values in the list, then it does the "thing" you want to do. The list will contain depth values, and you can access an individual value using values.get(i).

Related

Is it possible to iterate through a two-dimensional array without two loops for?

For example, if I have:
int Myarray[][] = new int[][] {{1,2}, {3,4}};
for (int line=0; line < Myarray.length; line++) {
for (int column = 0; column < Myarray[0].length; column++) {
// do something ...
}
}
How could I go through the entire array without the two loops?
Well you could use just a single loop:
for (int i = 0; i < Myarray.length*Myarray.length; i++) {
int row = i / Myarray.length;
int col = i % Myarray.length;
System.out.println(Myarray[row][col]);
}
But this assumes that your 2D array is square, i.e. its width and length are the same everywhere. Another way of saying this is that the 2D array is not jagged.
Demo
Note: As #Thilo mentioned above, this won't make things run faster. If you need to touch every element in your array, then my suggested code and your current double loop basically have the same complexity.
If you don’t need to know the line or column in the “do something” code (not stated in question), you could:
Arrays.stream(Myarray).flatMap(Arrays:stream)
.forEach(n -> /* do something with “n”, the cell value */);
You can iterate without any loops:
void recursive(int[][] array, int r, int c) {
if (r >= array.length) return;
if (c >= array[r].length) {
recursive(array, r+1, 0);
} else {
System.out.println(array[r][c]);
recursive(array, r, c+1);
}
}
Then invoke with recursive(array, 0, 0) to get started.
But there is no practical benefit in doing so. This would perform poorly, because of all the extra effort involved in calling a method vs just incrementing an int. (Plus, depending upon the size of the array, you could end up with a stack overflow).

Declaring 2 variables in a for() loop

I have 2 loops like this
goodexpressions and badexpressions are string arrays
for(int i =0; i < goodexpressions.length; i++) {}
&
for(int j =0; j < badexpressions.length; j++) {}
i'm trying to declare both of these in one loop, i've got this so far but it's not correct
for(int b = 0 , c = 0; b < goodexpressions.length; b++ c < badexpressions.length; c++)
what am I supposed to do to correct this statement?
Although what you are trying to do seems like a bad idea, here is a piece of code that will work. I don't know if it does exactly what you want it to though, since that isn't completely clear to me.
for(int b = 0, c = 0; b < goodexpressions.length || c < badexpressions.length; b++, c++) { }
When doing this, though, you still have to check if b and c are inside the array index range. You can also replace the || with && in which case you won't have to do that anymore, but you will be missing some items if the arrays are not equally long.
I think this will do what you are asking:
for (int b = 0, c = 0;
b < goodexpressions.length && c < badexpressions.length;
b++, c++)
Note that there are exactly 2 semicolons separators on an old-style for loop.
And based on your comment, I think this might be better:
for (int i = 0; i < Math.min(goodexpressions.length, badexpressions.length); i++)
Notes:
It is not at all clear what the loop body is going to do. That will determine the right way to combine the loops ... or if it is just a bad idea to combine them at all.
The above code is designed to stop at the smaller of the two lengths. If you want to stop at the larger, change && to || and min to max. However, if you do that, you also need to take care to avoid array bounds exceptions.
Unless the intent is to use both goodexpression[i] and badexpression[i] at the same time (e.g. compare them, combine them, and so on), your code will be more readable and more efficient if you use two separate loops.
Another possibility might be to simply check that the two arrays have the same length.
Depending on what you want to achieve, you should do one of the following. Say you have two lists A and B...
If you want to loop over all the elements in both lists A and B, create a new list, or array, holding the elements of both lists and loop over that list.
for (int i = 0; i < combinedAandB.length; i++) {
...
}
If you want to loop over all the combinations of elements from list A and list B, you have to use nested loops.
for (int i = 0; i < A.length; i++) {
for (int k = 0; k < B.length; k++) {
...
}
}
Update: Concerning the two-variable for-loop approach in your question and the other two answers: Note that since both those variables will take on exactly the same values in each iteration of the loop, you can just as well use just one variable:
for (int i = 0; i < goodexpressions.length || i < badexpressions.length; i++) { }
But also note that this will not do you any good in terms of avoiding code duplication, since you still have to everything to both, goodexpressions[i] and badexpressions[i]. A better approach might be to write a method holding the loop and calling that method once with goodexpressions and once with badexpressions.

Why when I reverse the comparison sign in my bubble sort algorithm does the resulting sorting list not reverse?

Java Code:
public static NHLList bubbleSort(NHLList players) {
for (int i = 0; i < players.size(); i++) {
for (int j = 0; j < players.size()-1; j++) {
if (players.get(j).getPoints() < players.get(j+1).getPoints()) {
PlayerRecord tempPlayer = players.get(j);
players.set(players.get(j+1), j);
players.set(tempPlayer, j+1);
}
}
}
return players;
}
If I change j < ... to j > ... the resulting list is not the previous list inverted, though I would assume it should be. All it's doing is reading numbers.
rolls sleeves up
You're inverting the sign on the wrong line.
As others have pointed out, please specify which line you are editing. If you are editing the right line then you may be unhappy to hear that this is not actually implementing BubbleSort.
You are actually performing a complete scan of the list n times which may, under some circumstances, result in a sorted list but is not actually what BubbleSort is all about. I would suggest you study your code and try to work out for yourself why your loop-counter i is never being referred to in the code (apart from in the loop control).

Java sudoku solver not changing empty cells

I am in the process of writing a sudoku solver (still need to write the box check and actually complete the program) but I'm testing it as I know. The puzzle I'm testing right now is "very easy" as in there is only one empty cell in any row/column. THe puzzle starts with "empty" cells as zeros. My issues is that when I run the program and print out the puzzle after solve() is called, the zeros aren't changing and the original puzzle is just printed out. Not sure what my issue is, would appreciate some direction!
public ArrayList<Integer> create(){
ArrayList<Integer> possible = new ArrayList<Integer>();
for(int i=1; i<10; i++){
possible.add(i);
}
return possible;
}
public sudoku( int size )
{
SIZE = size;
N = size*size;
Grid = new int[N][N];
for( int i = 0; i < N; i++ )
for( int j = 0; j < N; j++ )
Grid[i][j] = 0;
}
public void solve()
{
int a, b, c, d, i, j, k, l;
int count = 0;
int value= 0;
for(i=0; i<N;i++){
for(j=0; j<N;j++){
if(Grid[i][j]==0){
ArrayList<Integer> possible = create();
//check row
for(a=0; a<N;a++){
for(b=0; b<N; b++){
if(Grid[a][0]==possible.get(a)){
possible.set(a, 0);
}
}
}
//check column
for(c=0; c<N;c++){
for(d=0; d<N;d++){
if(Grid[0][d]==possible.get(d)){
possible.set(d,0);
}
}
}
for(k=0; k<9; k++){
if(possible.get(k)!=0){
count++;
}
}
if(count==1){
for(l=0; l<9; l++){
if(possible.get(l)!=0){
value=possible.get(l);
}
}
}
Grid[i][j]=value;
}
}
}
}
Look at your line if(Grid[a][0]==possible.get(a)) (and similar spots). What is it doing there vs what do you actually want?
Your possible array looks something like this:
[1,2,3,4,5,6,7,8,9]
and your grid (just the first row, since you're only checking Grid[a][0]) might look something like this:
[3,7,8,1,2,9,5,0,4]
Your loop is looking at each element stepwise individually and seeing if they're equal, like this:
if(1 == 3) ... it's not
if(2 == 7) ... it's not
if(3 == 8) ... it's not
... etc
So, as you can see, when you do your
for(k=0; k<9; k++){
if(possible.get(k)!=0){
count++;
}
}
Your possible array is still going to be full of options most of the time, unless your first row happens to be some variation on [1,2,3,4,5,6,7,8,9] with a 0 in one of the spaces... so count is definitely going to be > 1
So, your next loop (for(l=0; l<9; l++)) next gets executed, so value is still (as you initialized it) 0.
Try stepping through a debugger on these points and seeing how the arrays are interacting.
if(Grid[a][0]==possible.get(a))
if(Grid[0][d]==possible.get(d))
You don't use b or c in these lines. You probably want:
if(Grid[a][i]==possible.get(b))
if(Grid[j][d]==possible.get(c))
Also, the Grid[i][j]=value check should be inside the if block.
You might want to use a Set for the possible values instead of an ArrayList.
You are always checking only the first row and first column and the way you check for the possible numbers is also not doing what you want.
A few tips first:
First of all, it is not necessary to always define a new variable for the loops, you can reuse them and then you won't have too many of them and you won't get so easily confused in them.
Secondly, if you name all the variables a, b, c, d, etc. you can also easily get confused. While it is ok to name variables in loops as i, j, if you have too many loops, it may be better to think of better names. In this case row and column for example.
Why don't you remove the numbers from the possible list? Something like:
int index = possible.indexOf(a);
if (index != -1) possible.remove(index);
Then it would be easier to determine how many values you still have left. You can simply do:
if (possible.size()==1) value = possible.get(0);
And one last note, to obey the convention for variable names, you should probably use grid instead of Grid.
And now the code:
public void solve() {
int row, column, i;
int count = 0;
int value= 0;
int index = 0;
for(row=0; row<N; row++){
for(column=0; column<N; column++){
if(Grid[row][column]==0){
ArrayList<Integer> possible = create();
//check row
for(i=0; i<N; i++){
index = possible.indexOf(Grid[row][i]);
if (index != -1) possible.remove(index);
}
//check column
for(i=0; i<N; i++){
index = possible.indexOf(Grid[i][column]);
if (index != -1) possible.remove(index);
}
if (possible.size()==1) value = possible.get(0);
Grid[row][column]=value;
}
}
}
}
EDIT: Rewritten the whole answer into a better form.

Odd problem with implementing max with for loop

I spend the last hour doing trial and error with this problem with no avail. We have to, using general coding guidelines (like scan.nextDouble) instead of actual numbers, find the max of a certain number of double values. The only catch is that we can only add code at a certain point. (where the ... is)
double value, valMax;
int n;
n = scan.nextInt();
for(int j = 0; j < n; j++)
{
value = scan.nextDouble();
...
}
Where the first value read in is an int and that is the amount of doubles to be entered.
It is difficult because I have to find a way to initialize valMax inside the loop without messing up anything else.
This is what I have been working with, but with nothing working for me.
for(int j = 0; j < n; j++)
{
value = scan.nextDouble();
if(j == 0)
{
valMax = scan.nextDouble();
j++;
}
else
{
continue;
}
if(value >= valMax)
{
valMax = value;
}
}
Example input:
5 -4.7 -9.2 -3.1 -8.6 -5.0
Where -3.1 is the max and 5 is the count of following numbers.
Your code seems like a good start.
To help solve your problem, consider:
Why did you put in the extra j++? Do you really need it? (Hint: no ;-) )
What will the loop do for j>0 (i.e. after the first iteration)?
That should quickly give you a working solution.
Are you allowed to set the valMax before the loop? Because in that case you can just do
valMax = Double.MIN_VALUE
and just forget about strange things by doing a normal comparison value > valMax.
If you are not your approach is how you should do but two things:
you shouldn't care about incrementing with j++ since the for loop will care about it by itself..
having a else { continue; } will make the body of the for jump to next iteration without caring about code that is after the continue. Are you sure that is what you want to do?
I think that you can initialize to Double.MIN_VALUE at first iteration (j == 0) and just behave normally afterwards: the only thing you need is that valMax is initialized before the first comparison with value, not before the scan from stdin..

Categories