Okay so my current assignment has me making a program that can mimic percolation, meaning that it has to read an array, where 1 means the space is closed, 0 means the space is open. Next, it must change all the 0's at the top row of the array to 2's representing the liquid being poured in. The liquid can then follow the 0's (representing the flow), changing them all to twos along the way. Liquid can move up, down, left, and right. not diagonal. I have my program almost working, but the for loops don't seem to go through more than the first row of the array.
public class Percolation2 {
public static void main (String[] args) {
int[][] filter1 = {{1,0,1,0,1,1,0},
{1,0,1,1,1,0,0},
{0,0,0,1,0,0,1},
{1,1,0,1,1,1,1},
{1,0,0,1,1,0,1},
{1,0,1,0,1,0,1},
{0,0,0,0,1,1,0},
{1,1,1,0,1,0,1}};
for(int i=0; i<7; i++) {
if(filter1[0][i] ==0) {
filter1[0][i] = 2;
}
}
for ( int i = 0 ; i < filter1.length ; i++ ) {
for ( int j = 0 ; j < filter1[i].length ; j++ ) {
if ( filter1[i][j] == 0 )
if(i-1 > 0 && filter1[i-1][j] == 2)
filter1[i][j] = 2;
if(i+1 < 7 && filter1[i+1][j] ==2)
filter1[i][j] = 2;
if(j-1 > 0 && filter1[i][j-1]==2)
filter1[i][j] = 2;
if(j+1 < 7 && filter1[i][j+1] == 2)
filter1[i][j] = 2;
}
}
for(int i = 0; i < filter1.length; i++) {
for(int j = 0; j < filter1[i].length; j++) {
System.out.print(filter1[i][j]);
if(j < filter1[i].length - 1) System.out.print(" ");
}
System.out.println();
}
}
}
My output is as follows:
2 2 2 2 2 2 2
1 0 1 1 1 0 0
0 0 0 1 0 0 1
1 1 0 1 1 1 1
1 0 0 1 1 0 1
1 0 1 0 1 0 1
0 0 0 0 1 1 0
1 1 1 0 1 0 1
So you can clearly tell that it is not looping properly.
Each turn the liquid can move one level. Your for statements are correct, all elements of the array are visited. You need another loop for the proper amount of turns.
I don't want to give you the answer directly as there is a lesson to be learned here, you need to have something like:
//Init
boolean done = false;
while(!done) {
for (int i = 0; i < filter1.length; i++) {
for(int j = 0; j < filter1[i].length; j++) {
if(filter1[i][j] == 0)
....
}
}
//add the print matrix code here if you want it done after each turn.
done = amIDone();
}
Overall your code is structured pretty poorly. You should make use of constants for the array lengths, and you could also define methods for your two doubly nested for loops. At the bare mininum, I would have a printMatrix() method.
I see a couple problems here:
1) You seemed to have left out curly brackets around the block of code following if(filter1[i][j] == 0) in your double for loop.
2) Below that, your check for out-of-bounds is incorrect if(i-1 > 0 && ... should be if(i-1 >= 0 && .... And, if(j+1 < 7 && ... should be if(j+1 < 8 && ...
3) In your question you say that your output is 2 2 2 2 2 2 2 ... . But your code produces different results, your output should be 1 2 1 2 1 1 2 .... Thats what I get when I run for(int i=0; i<7; i++) { if(filter1[0][i] == 0) { filter1[0][i] = 2; } }
4) Pete hints at the problem. But more specifically, you are doing one pass down the matrix (2D array). There is no ability to go up with the liquid (nor left).
Lets call these items cells. And when a cell gets liquid (a.k.a. it turns to == 2), it should percolate that liquid to the neighboring cells which are empty (a.k.a. set to 0). This sounds like a call for recursion, IMHO!
Once you fix the first three issues. Put the payload of your double for loop into a recursive function such as this here:
public void percolate(int x, int y) {
if ( filter1[x][y] == 0 ) {
if(x-1 >= 0 && filter1[x-1][y] == 2) filter1[x][y] = 2;
if(x+1 < 7 && filter1[x+1][y] == 2) filter1[x][y] = 2;
if(y-1 >= 0 && filter1[x][y-1] == 2) filter1[x][y] = 2;
if(y+1 < 8 && filter1[x][y+1] == 2) filter1[x][y] = 2;
if ( filter1[x][y] == 2 ) {
if ( x-1 >= 0 ) percolate(x-1,y);
if ( x+1 < 7 ) percolate(x+1,y);
if ( y-1 >= 0 ) percolate(x,y-1);
if ( y+1 < 8 ) percolate(x,y+1);
}
}
}
Then just call it for each cell in your double for loop. Actually, since the liquid starts at the top, I guess you could just call this percolate for each cell in the second row, only. It will percolate down and round from there.
As you might can see, this is not the most efficient solution, it double/triple checks for percolation on some cells. But this is the slim, nuts and bolts version.
EDIT: Fixed typeos, got rid of unnecessary boolean.
Related
there is such a question. I have a method that reads the bytes from a file into an array, and the method that searches for the longest byte sequence in this array.
private int element;
private int lastElement;
private int length;
private byte[] readByteFromFile(File name) throws IOException {
return Files.readAllBytes(name.toPath());
}
private void searchByte(byte[] byteMass) {
for (int i = 0; i < byteMass.length; i++) {
int count = 0;
for (int j = i + 1; j < byteMass.length; j++) {
if (byteMass[i + count] == byteMass[j]) {
if (count >= length) {
length = count + 1;
element = i;
lastElement = j - count;
}
count++;
} else {
count = 0;
}
}
}
}
Suppose that my file contains such a sequence of numbers:
444478126354444
In the case of processing, my method will deduce that the first occurrence was at 0, and the second at 11 and length of sequence = 4
But if I have such a sequence
133333444478126354444
Then my method will deduce that the first occurrence was at 1, and the second at 2, and the length of the sequence 4
How it can be fixed, that the method to continue to work correctly?
It is not tested. Don't have IDE infront of me.
The changes from the original code are. The second loop iterates one element less. If the next element is not equel to the previous then the loop exits.
private void searchByte(byte[] byteMass) {
int maxLength = 0
int element;
for (int i = 0; i < byteMass.length; i++) {
int count = 0;
for (int j = i + 1; j < byteMass.length-1; j++) {
if (byteMass[i] == byteMass[j]) {
if (count > length) {
maxLength = count;
element = i;
}
count++;
} else {
break;
}
}
}
If you haven't already I think it's very important to trace out the logic of your code!!! It's really important that you attempt to do this before asking for help. If you rely on others to work out your own logic, you won't make much progress as a programmer.
That being said, let's dive in and follow your code when it runs with the problem input (this isn't actual code, we're just looking at the values as the program runs)
byteMass = 133333444478126354444
(byteMass.length = 21)
length = 0
0 (i) < 21 (byteMass.length): true
count = 0
1 (j) < 21: true
1 (byteMass[0 (i + count)]) == 3 (byteMass[1 (j)]): false
count = 0
2 (j) < 21: true
1 (byteMass[0 (i + count)]) == 3 (byteMass[2 (j)]): false
count = 0
3 (j) < 21: true
1 == 3: false
it continues on like this, but something interesting happens when j = 12
12 (j) < 21: true
1 (byteMass[0 (i + count)]) == 1 (byteMass[12 (j)]): true
0 (count) >= 0 (length): true
length = 1 (count + 1)
element = 0 (i)
lastElement = 12 (j - count)
count = 1
This, to me at least, looks like unexpected behavior! We want to count repeated numbers, but this 1 is 11 digits away from the previous 1! We can fix this by editing the inner for loop like this
for (int j = i + 1; j < byteMass.length && byteMass[i] == byteMass[j]; j++) {
This way, the inner loop breaks as soon as byteMass[i] == byteMass[j] evaluates to false. now let's restart our process with the new inner for loop
byteMass = 133333444478126354444
(byteMass.length = 21)
length = 0
0 (i) < 21 (byteMass.length): true
count = 0
1 (j) < 21 && 1 (byteMass[0 (i)]) == 3 (byteMass[1 (j)]): false
1 (i) < 21: true
count = 0
2 (j) < 21 && 3 (byteMass[1 (i)]) == 3 (byteMass[2 (j)]): true
0 (count) >= 0 (length): true
length = 1 (0 (count) + 1)
element = 1 (i)
lastElement = 2 (2 (j) - 0 (count))
count = 1 (0 (count) + 1)
3 (j) < 21 && 3 (byteMass[2 (1 (i) + 1 (count))]) == 3 (byteMass[3 (j)]): true
1 (count) >= 1 (length): true
length = 2 (1 (count) + 1)
element = 1 (i)
lastElement = 2 (3 (j) - 1 (count))
This seems like unexpected behavior to me, but I won't fix it because I don't know how: I have no idea what element and lastElement represent. The code continues on like this until j = 6:
6 (j) < 21 && 3 (byteMass[5 (1 (i) + 4 (count))]) == 4 (bteMass[3 (j)]): false
2 (i) < 21: true
count = 0
3 (j) < 21: true
3 (byteMass[2 (2 (i) + 0 (count))]) == 3 (byteMass[3 (j)]): true
length = 1 (0 (count) + 1)
element = 2 (i)
lastElement = 3 (3 (j) - 1 (count))
count = 1 (0 (count) + 1)
This once again continues in the same fashion until j = 6. At this point hopefully you can see why your program isn't working as expected. But I still haven't answered the question of how to fix it. I don't really understand your thought process on how to solve this problem but I'll share with you my own
First of all we need to break the problem into smaller chunks!
You can do that any way you want to but here's my way: Our goal is to find the longest repeated pattern. Well in order to do that we need to figure out
when a number repeats itself and how many times it repeats itself
if that specific number repeated itself that specific amount of times anywhere else in the sequence. If it does, we'll need to save the amount of times it repeats itself
Then we'll repeat the process but only save the data if the number of repeats is larger than the saved data
It's actually a kind of complex problem and will probably be easier to solve with helper functions to be honest. I hope this helps!
The Question was:
You are given a binary matrix (i.e. each element of matrix is either 0 or 1) of size n × n. You want to re-arrange 1's in such a way that they form a rectangular region. Note that the rectangular region should be made of only 1's, and all the 1's of the entire matrix should be in this rectangular region.
For achieving rectangular region, you can swap any two elements of the matrix. Please find out the minimum number of swaps needed. If it is not possible to re-arrange 1's in the desired way, please print -1.
Input
First line of the input contains a single integer T denoting number of test cases.
Description of T test cases follows.
First line of each test case will contain a single integer n denoting dimension of matrix.
Each of next n lines will contain n space separated integers denoting the ith row of the matrix.
Output
For each test case, print a single line containing a single integer denoting minimum number of swaps needed or -1 depending on the situation.
Example
Input:
2
2
0 1
1 0
2
1 1
1 0
Output:
1
-1
Explanation
Example case 1. You can swap 1 of second row first column with 0 of first row first column.
After the swap, matrix will look as follows.
1 1
0 0
Here all the 1's form a rectangular region of dimension 1 × 2. In this case, 1 swap will be needed.
Note that you can also swap 1 at first row second column with 0 at second row second column too.
Matrix after this swap will be following.
0 0
1 1
So you need 1 swap in this case too.
So overall, you need 1 swap.
Example case 2. There is no way to create a rectangular region containing 3 1's in a matrix of dimension 2 × 2, hence answer is -1.
My Algorithm [Edit]
First i am Taking Number of Cases from user
Then the order of matrix [will be of nxn order].
So logic is that if matrix is 1x1 then it will simply print 0
else while taking input from user [that will be only 1 or 0] i am counting 1's because the logic i develop that when in a matrix of odd order the 1's will be even then it cannot be arranged in rectangular form.and for even order of matrix if 1's are odd , not arrange able .
Next i am traversing each index if i find one then i move to next element else i try to find 1 in the same colomn if dont find than i am breaking loop showing -1 that it is not arrange able in rectangular form
Than after arranging a row i check the next row whether it is already arranged or not if it is than i break everything and moves to next case
n rectangular form
My Solution
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Main {
static long startTime;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int numberOfOnes = 0;
int T = scanner.nextInt();
for (int t = 1; t <= T; t++) {
int n = scanner.nextInt();
int loopCounter, swapCounter = 0;
boolean rowContainsZero = false;
int array[][] = new int[n][n];
boolean reject = true;
//Worst and the most simpler conditions
if (n == 1) {
System.out.print("0");
exitingSystem();
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
array[i][j] = scanner.nextInt();
if (array[i][j] == 1) {
numberOfOnes++;
}
}
}
if (n % 2 == 0 && numberOfOnes % 2 != 0) {
System.out.println("-1");
if (t == T) {
exitingSystem();
}
continue;
} else if (n % 2 != 0 && numberOfOnes % 2 == 0) {
System.out.println("-1");
if (t == T) {
exitingSystem();
}
continue;
}
// System.out.println("Here i am");
//From here swaping processes will take the place
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (array[i][j] == 1) {
continue;
} else if (array[i][j] == 0) {
loopCounter = i;
reject = true;
while (loopCounter < n) {
if (array[loopCounter][j] == 1) {
int temp = array[loopCounter][j];
array[loopCounter][j] = array[i][j];
array[i][j] = temp;
reject = false;
swapCounter += 1;
break;
}
loopCounter++;
}
if (rowContainsZero) {
System.out.println("" + swapCounter);
break;
}
if (reject == true) {
System.out.println("-1");
break;
} else {
for (int m = i + 1; m < n; m++) {
for (int k = 0; k < n; k++) {
if (array[m][k] == 0) {
rowContainsZero = true;
} else {
rowContainsZero = false;
break;
}
}
}
}
} else {
System.out.println("0's and 1's were Expected :(");
exitingSystem();
}
}
if (reject == true) {
break;
}
}
}
}
public static void exitingSystem() {
System.exit(0);
}
}
BUT THE CODECHEF COMPUTER SAYING WRONG ANSWER + They allowed to take input from keyboard too
I think your algorithm isn't fully correct.
I think the following is a counter-example for your step 4 / odd order (n=3) and even number of ones (numberOfOnes=4):
1 1 0
1 1 0
0 0 0
This should give 0.
Similar for n=4 and numberOfOnes=3:
1 1 1 0
0 0 0 0
0 0 0 0
0 0 0 0
This should give 0 as well.
I haven't yet deeply analyzed your steps 5 and 6.
Here are some more examples:
1 1 1 0
1 1 0 0
1 1 1 0
1 1 0 0
This should give -1, as from 10 ones you can only form rectangles of the form 2*5 or 1*10, which both don't fit into the 4*4 frame.
1 1 1 0
1 1 0 0
1 1 1 0
1 0 0 0
This should give 1, as by moving the lower-left 1 two palces up and right, you get a 3*3 rectangle.
This is not the way you are trying to solve problem. Suppose you have
0 0 1
0 1 1
0 0 1
This is a perfect example of solveable matrix but you can't simply use random swap and then acquire result. You need to use A* search algorithm with manhatten distance.
Make a priority queue
Define manhatten distance.
Create a function which creates succesors of each board. Like if i have above board then it will give you a collection of boards back:
0 0 1
0 1 1 ==> colection
0 0 1
0 1 1
0 0 1
0 0 1
0 0 1
0 0 1
0 1 1
0 1 0
0 1 1
0 0 1
0 0 1
0 1 1
0 1 0
Description of A:*
an initial lis to store visited boar so that you don't visit them again.
i will call MinPriority queue a pq
`insert the initial_board in pq
while(!pq.isEmpty() && !foundGoal(pq.min)) //You find goal when your
manhatten distance is 0.
board = pq.delMin(); //you have to override the distance method in
priority queue so it will return you that board whoms manhatten
distance is smallest.
for(boards b :board.getSuccesors(); // give you collection of boards.
if(notvisited(b,vistiedList)) // so that you don't come in same state again and
again.
pq.insert(b);
visitedList.add(b);`
In first year i had to solve 8-puzzle and you can solve this way however you can also use hamming distance but that's not efficient and here is 8-puzzle code(with A* implementation).
I have to show a message in the console after reaching a specific number of loops in an array list (e.g. 10) and then display a message about the remaining items in the array list.
The array list contains all the lowercase letters from a to z.
Now, in a counter, I have used MOD to check that
for (int i = 0; i > arrayList.length; i++)
{
// If loop is not at 0 and MOD with 10 is == 0 then it means we have to show message
if(i != 0 and i % 10 == 0)
{
// Show console
}
}
How do I handle the remaining items? Since there are 26 letters in the alphabet, it will print on first 20 but I'm not sure how to deal with the last six. The message should be printed on that too. It should show a console message 3 times not 2.
Simple Change is to check again if the array end is reached .
for (int i = 0; i < arrayList.length; i++)
{
// If loop is not at 0 and MOD with 10 is == 0 then it means we have to show message
if((i != 0 and i % 10 == 0) || (i == arrayList.length - 1))
{ // This executes on 10 , 20, and end of array.
// Show console
}
}
Since there is 26 in your list, you could break it up more evenly and on the last value.
for (int i = 0; i < arrayList.length; i++) {
// do something
// every ~1/3rd completed
if(i % 9 == 8 || i == arrayList.length - 1) {
// Show console
}
}
You can simply add an additional condition, that checks if the message was shown thrice. If the message was not shown thrice, the third message will be shown on the last element of the array.
This could work for arrays with elements greater than 20 elements.
int count = 0;
for (int i = 0; i > arrayList.length; i++)
{
// If loop is not at 0 and MOD with 10 is == 0 then it means we have to show message
if((i != 0 and i % 10 == 0) or (count<3 and i = arrayList.length-1))
{
count++;
// Show console
}
}
I'm trying to create a table using a method and either my logic is wrong or the stack overflow is what is causing my problem, this is what I'm trying to create...
1 1 1 1 1
1 2 2 2 1
1 2 3 2 1
1 2 2 2 1
1 1 1 1 1
And this is what I'm getting
1 1 1 1 1
2 2 2 2 2
1 2 3 2 1
2 2 2 2 2
1 1 1 1 1
[[I#4d0948bd
Here is my code, it's just those 4 corner 2s that need to be ones and if that's fixed my error might be fixed.
public class Server{
public static int[][] tableMaker(){
int[][] table = new int[5][5];
for(int i=0; i<table.length; i++){
for(int j=0; j<table.length; j++){
if(i==2 && j==2){
table[i][j] =3;
}
if(i==0 || i==4){
table[i][j] = 1;
}
if(j==4 || j==0){
table[i][j] = 1;
}
if((i==1 || i==3) && (j>0 || j<4)){
table[i][j] = 2;
}
if((i==2 && j==1) || (i==2 && j==3)){
table[i][j] = 2;
}
}
}
for(int i=0; i<table.length; i++){
for(int j=0; j<table.length; j++){
System.out.print(table[i][j] + " ");
}
System.out.println();
}
return table;
}
}
Here is my print command in the Client
public class Client{
public static void main(String[] args){
System.out.println(Server.tableMaker());
}
}
Don't call println and pass in the tableMaker() method. That's what is causing you to get the default toString() result from a 2D array of int, [[I#4d0948bd. Instead just call the tableMaker method.
Re-think your logic of how to create the table by first creating it on paper and thinking through the steps required to create it. I'd use if + else if blocks. i.e., if the cell is on an edge, put in one, else if the cell is one away from an edge (translate logic to Java) put in a 2, else if,...
If this were my method, I wouldn't have any println's or print commands in the method at all. I'd create and return the 2D array, and then let the calling code decide what to do with the array -- likely it would use nested for loops, as your method does, but that's up to the calling code.
You may have worked this out already, but you just needed to change the line
if((i==1 || i==3) && (j>0 || j<4)){
to
if((i==1 || i==3) && (j>0 && j<4)){
I have a for loop that checks for every 5th position. And at every 5th position, I'm performing an action like so (which works):
for(int i = 0; i < foo().length; i++)
{
System.out.print(i);
if(i == 5 || i == 10 || i == 15)
System.out.println();
}
Is there a way to write if statement so no matter how long foo().length is, I don't have to keep coming back to adjust it?
Use modulus(%) operator: -
if (i % 5 == 0) {
}
5 % 5 == 0, 10 % 5 == 0, ...
Since you are using a for loop, you can simply change your increment from i++ to i += 5, and leave the if condition.
for (int i = 0; i < someNum; i += 5) {
// No need to check for `i` against `modulus 5`.
}
You can use next for witout if statement
for(int i = 0; i < foo().length; i+=5)
{
adding 5 to i step by step
Use the following:
if ( i % 5 == 0 )
if you want to put it in a single print statement this would work too.
for(int i = 0; i < foo().length; i++)
{
System.out.printf("%d%s", i, (i%5==0) ? "\n" : "");
}