Java- Searching for trailing 0's in an array - java

I have a 2D Array filled with consecutive integers 1-52 as well as four 0's. I have also created a count variable and set it equal to 0; I want to search through the array and for every 0 that immediately follows either 13,26,39, or 52, increment count++.
int count =0;
for(int i=0;i<4;i++) {
for(int j=0; j<4;j++) {
if((board[i][j]== 13 && board[i][j+1]==0) || (board[i][j]== 26 && board[i][j+1]==0) || (board[i][j]== 39 && board[i][j+1]==0) || (board[i][j]== 52 && board[i][j+1]==0) ) {
count++;
}
}
}
while(count <4) {
move(board);
}
My current code runs properly and will increment count for a single zero following these numbers. However I want to increment count+=2 if one of my four numbers is immediately followed by two 0's (increment +=3 for three 0's and +=4 for four 0's).

Just make another method to count zeros:
int count =0;
for(int i=0;i<4;i++) {
for(int j=0; j<4;j++) {
if((board[i][j]== 13 || board[i][j]== 26 || board[i][j]== 39 || board[i][j]== 52 ) && board[i][j+1]==0 ) {
count += numberOfZeros(i, j);
}
}
}
while(count <4) {
move(board);
}
}
public int numberOfZeros(int i, int j){
int aux = 0;
for(; j<4;j++) {
if(board[i][j] == 0){
aux++;
}
}
return aux;
}
PS: I edited your if clause to make it more clear

You can use a boolean to check whether you are on a count 'streak' of zeroes:
int count = 0;
boolean onACountStreak = false;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (board[i][j] == 0) {
// Count only if this zero is found in a streak
if (onACountStreak) {
count++;
}
}
else if (board[i][j] % 13 == 0) {
onACountStreak = true;
}
else {
onACountStreak = false;
}
}
}
while (count < 4) {
move(board);
}

Related

How to find a >3 line of consecutive elements in a 2d array

I'm a game where you have to make a line in a row/column of 3 or more (up to 7) consecutive elements in a 2d array. Every time there is one of those lines you add the score and delete those consecutive elements from the row/column (Similar as to candycrash disappearing candies.
If you have something like this ['a' 'b' 'b' 'b' 'a'] the result should be ['a' '' '' '' 'a']
The problem comes to more complex cases like ['b' 'b' ' ' 'b' 'b'], that ends up like this
['' '' '' '' ''] because its also detected as a >=3 elem. consecutive line.
I know its due to the counter that keeps adding to the value it already has, but I couldnt come to any other solution till now
The code I have up to now is this:
**
public int[] checkRows() {
int[] results = new int[BOARD_SIZE];
for (int i = 0; i < BOARD_SIZE; i++) {
int counter = 1;
int counterHead = 1;
int j = 0;
while (j < BOARD_SIZE) {
if (j+1 < BOARD_SIZE) {
if (getBoard()[i][j].getType() == getBoard()[i][j+1].getType() && getBoard()[i][j].getType() != ' ') {
counter++;
}
}
if (counter >= 3)
deleteRows(i, j);
j++;
}
results[i] = counter;
}
return results;
}
**
So we want to see if there are 3 consecutive elements with the same value, but what it looks like to me is we are simply testing if there are three values in a row of the board that are equal. This works if we find a section of consecutive equivalent elements, but as soon as we find a space or non-equal element the logic fails.
Things we need to consider:
If the counter reaches 3 we can break out of your conditional and delete. This case is covered.
If your counter is updated from its original value (counter > 1) and never reaches 3 we know we must have encountered either a space or a non-equivalent value. In this case we should reset the counter and continue our test for the rest of the row.
Your problem is that you are not counting consecutive values, but rather pairs of consecutive values. For 'b', 'b', 'b', there are three b characters, but only 2 pairs of values, 1) the first and second b, and 2) the second and third b. Your counter should start at 1 rather than 0 because every value is by itself a run of 1 "consecutive" values. This, along with resetting the counter when you see a non-matching letter should give you the result you desire.
I haven't tried this as I don't have your data or the structures that this code uses, but try this:
public int[] checkRows() {
int[] results = new int[BOARD_SIZE];
for (int i = 0; i < BOARD_SIZE; i++) {
int counter = 1;
int counterHead = 1;
int j = 1;
while (j < BOARD_SIZE) {
if (j+1 < BOARD_SIZE) {
if (getBoard()[i][j].getType() == getBoard()[i][j+1].getType() && getBoard()[i][j].getType() != ' ') {
counter++;
}
else {
counter = 1;
}
}
if (counter >= 3)
deleteRows(i, j);
j++;
}
results[i] = counter;
}
return results;
}
First of all, I would suggest that for such complex problems, always try to break your problems and then merge those pieces together.
Below is the algorithm for your problem, just for simplicity and ease of explanation I used an Integer array which you can easily replace with a string or character array and change the condition.
A basic function for performing candyCrush Algorithm.
public void candyCrush(){
int[][] result = new int[][]{{1,2,2,2,2},
{1,2,2,2,1},
{1,2,1,1,1},
{2,1,2,1,1}
};
int count = 0;
for (int i = 0; i < result.length; i++) {
for (int j = 0; j < result[i].length; j++) {
if(result[i][j]==-1){
continue;
}
boolean hasRowElements = checkRowForCurrentIndex(result, i, j);
boolean hasColumnElements = checkColumnForCurrentIndex(result, i, j);
if(hasRowElements || hasColumnElements){
count++;
}
}
}
System.out.println(count);
}
private boolean checkRowForCurrentIndex(int[][] result, int row, int col) {
int forTop = row, forBottom = row;
int topStartingLimit = 0, bottomEndingLimit = 0;
while(forTop>= 0){
if(result[row][col] == result[forTop][col] && result[forTop][col]!=-1){
topStartingLimit = forTop;
}else{
break;
}
forTop--;
}
while(forBottom< result.length){
if(result[row][col] == result[forBottom][col] && result[forBottom][col]!=-1){
bottomEndingLimit = forBottom;
}else{
break;
}
forBottom++;
}
if(topStartingLimit==bottomEndingLimit){
return false;
}
if(bottomEndingLimit-topStartingLimit>=2 && bottomEndingLimit-topStartingLimit<= 6) {
deleteRows(result, topStartingLimit, bottomEndingLimit, row, col);
return true;
}
return false;
}
private void deleteRows(int[][] result, int topStartingLimit, int bottomEndingLimit, int row, int col) {
while(topStartingLimit<= bottomEndingLimit){
result[topStartingLimit][col] = -1;
topStartingLimit++;
}
return;
}
private boolean checkColumnForCurrentIndex(int[][] result, int row, int col) {
int forLeft = col, forRight = col;
int leftStartingLimit = 0, rightEndingLimit = 0;
while(forLeft>= 0){
if(result[row][col] == result[row][forLeft] && result[row][forLeft]!=-1){
leftStartingLimit = forLeft;
}else{
break;
}
forLeft--;
}
while(forRight< result[row].length){
if(result[row][col] == result[row][forRight] && result[row][forRight]!=-1){
rightEndingLimit = forRight;
}else{
break;
}
forRight++;
}
if(leftStartingLimit==rightEndingLimit){
return false;
}
if(rightEndingLimit-leftStartingLimit>=2 && rightEndingLimit-leftStartingLimit<= 6) {
deleteCols(result, leftStartingLimit, rightEndingLimit, row, col);
return true;
}
return false;
}
private void deleteCols(int[][] result, int leftStartingLimit, int rightEndingLimit, int row, int col) {
while(leftStartingLimit<= rightEndingLimit){
result[row][leftStartingLimit] = -1;
leftStartingLimit++;
}
return;
}
Definitely, you can optimize this code better by using the same function again for Rows and Cols, but for sake of simplicity. I tried to break everything so that the solution becomes more clear.
Hope this algorithm would work.

Codingbat how to count if there are three 3 in an array

Java newbie here, I'm doing some practice about array on Codingbat haveThree. This is the question :"Given an array of ints, return true if the value 3 appears in the array exactly 3 times, and no 3's are next to each other." My code works on most situation but not all.
My code:
public boolean haveThree(int[] nums){
int counter=0;
for(int i=0; i<nums.length-2;i++){
if(nums[i]==3){
counter++;
}
if(counter==3){
return true;
}
}
return false;
}
Can anyone help me and tell me where I was wrong? How can I fix it?
"Given an array of ints, return true if the value 3 appears in the
array exactly 3 times, and no 3's are next to each other."
you're almost there, however, there are a few mistakes and incomplete implementations:
you didn't check if the value 3 is next to another value 3 (in which case we return false)
you return as soon as count == 3 even though you didn't search the entire array to conclude that there is no more 3s.
as it stands your loop condition i < nums.length-2 doesn't include the last two elements of the array within the search.
solution:
public boolean haveThree(int[] nums){
int counter = 0;
for(int i = 0; i < nums.length; i++){
if(nums[i] == 3){
counter++;
}
if(i + 1 < nums.length) {
if (nums[i] == 3 && nums[i + 1] == 3) return false;
}
}
if(counter == 3) return true;
return false;
}
Here is my solution for this, Have a look :)
public boolean haveThree(int[] nums) {
boolean check=true;
int count = 0;
for(int i=0;i<nums.length;i++){
if( nums[i]==3 && count++>0 && ( (i>0 && nums[i-1] == 3) || (i<nums.length-1 && nums[i+1] == 3) ) )
{//just checking if there are any consecutive 3's next to each other and counting them
check = false;
}
}
return (check && count==3);//count should be 3 and no 3's should be next to each other
}
Here is my solution, which passed all the tests on CodingBat:
public boolean haveThree(int[] nums) {
int counter3 = 0;
if (nums.length >= 5) {
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 3) {
counter3++;
}
}
}
if (counter3 == 3) {
for (int i = 0; i < nums.length - 4; i++) {
if ( (nums[i] == 3) &&
(nums[i+1] != 3) &&
(nums[i+2] == 3) &&
(nums[i+3] != 3) &&
(nums[i+4] == 3)
) { return true; }
}
}
return false;
}
Your loop does not lookup for each element you are missing the last 2 ones. Should be i < nums.length or use simply enhanced for so you don't have to save the current num on a value.
Check if no 3's are next to each other, because now you aren't checking that. I think the best salution to secure that no 3's are next to each other is to save the last number and compare it to the current one.
You can only be sure that the value 3 appears exactly 3 times in the array if you had seen the whole array so check that at the end and not in the loop.
public boolean haveThree(int[] nums) {
int lastNum = 0;
int counter = 0;
for (int currNum : nums) {
if (currNum == 3) {
counter++;
if (lastNum == currNum) {
return false;
}
}
lastNum = currNum;
}
return counter == 3;
}
A very Simple solution for this problem:
public boolean haveThree(int[] nums) {
int count = 0;
int preNum = 0;
for(int i =0; i<nums.length;i++){
if(nums[i]==3){
count++;
if(preNum ==3){
return false;
}
}
preNum = nums[i];
}
return count == 3;
}

How can I gets histogram using arrays in java?

Take input from user in an array in form of numeric and show histogram Where i'm wrong The code is given in java the user can enter 5 input in number and histogram should show in any form with no constraints
package p21;
import java.util.Scanner;
public class P21 {
public static void main(String[] args) {
{
int count[] = new int[10]; // count array will keep elements of element
// in particular range;
int elements[]; // for example 27 15 34 22 11 11 19
{ // in above input there is count[0]=0;
for (int i = 0; i < elements.length; i++) // count[1]=4 and count[2]=2 and count[3]=1;
{
if (elements[i] >= 0 && elements[i] < 50) {
if (elements[i] < 10) {
count[0]++;}
else if (elements[i] >= 10 && elements[i] < 20) {
count[1]++;}
else if (elements[i] >= 20 && elements[i] < 30) {
count[2]++;}
else if (elements[i] >= 30 && elements[i] < 40) {
count[3]++;}
else {
count[4]++;
}}
else if (elements[i] >= 50 && elements[i] <= 100) {
if (elements[i] < 60) {
count[5]++;}
else if (elements[i] >= 60 && elements[i] < 70) {
count[6]++;}
else if (elements[i] >= 70 && elements[i] < 80) {
count[7]++;}
else if (elements[i] >= 80 && elements[i] < 90) {
count[8]++;}
else {
count[9]++;
}}}}
{
System.out.println("Histogram of the elements:");
for (int i = 0; i < count.length; i++) // this loop will print line
{
for (int j = 0; j < count[i]; j++) // this will print elements element(*)
{ // at each line.
System.out.print("* ");
}
if (count[i] != 0) // if line does'nt contain zero
System.out.println(""); // then if will change the row;
}
}
}
/*
in above code if count[i]=zero means if there is elements
element in particular range say [0-9] then it will
elementst jump on next line;
*/
{
{
Histogram hg = new Histogram();
System.out.println("Enter the elements of Elements want in a Histogram:");
Scanner sc = new Scanner(System.in);
int noOfElements = sc.nextInt();
int histogramElements[] = new int[noOfElements];
System.out.println("Enter the Elements for Histogram:");
for (int i = 0; i < noOfElements; i++) {
histogramElements[i] = sc.nextInt();
}
hg.showHistogram(histogramElements);
}
For your binning approach..... since you only care about groups of 10. Divide the input number by 10. Bound the divided result then use the result to index your counter array.

Find the Last Digit In An Array

I need to find the last digit in a array and see if it is equal to zero. Here is the code I'm using;
import java.util.Scanner;
public class NrOccurrence
{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
System.out.print("Enter the integers between 1 and 100: ");
int[] numbers = new int[100], times = new int[100];
boolean zero = false;
while (zero == false)
{
for (int a = 0; a <= numbers.length; a++)
{
numbers[a] = scan.nextInt();
times[a]++;
if (numbers.equals(0))
{
zero = true;
}
}
}
for (int b = 0; b <= numbers.length; b++)
{
System.out.println(numbers[b] + " occurs " + times[b] + " times");
}
scan.close();
}
}
Create a method like this:
private boolean isLastItemZero(int[] numbers)
{
boolean isLastItemZero = false;
if ((numbers != null) && (numbers.length > 0))
{
isLastItemZero = numbers[numbers.length - 1] == 0;
}
return isLastItemZero;
}
And call it once you're done reading in all of the numbers from the user.
First of all for (int a = 0; a <= numbers.length; a++) will give youIndexOutOfBoundsException .Java uses 0 bases indexing which means that an array of size n has indices up to and including n-1. Change it tofor (int a = 0; a < numbers.length; a++) . Same thing here for (int b = 0; b <= numbers.length; b++)
Second i am not sure what you are trying to check here :
if (numbers.equals(0))
{
zero = true;
}
but you could simply do :
if(numbers[i] == 0);
Now if you wanna check if the last element in the array is 0you can simply do:
if(numbers[numbers.length - 1] == 0)
//do something
By definition, if the remainder of a number divided by 10 is 0, then the last digit must be 0. So you just need;
if(numbers[i] % 10 == 0) { zero = true; }
Hope this helps.

Nested loop construction

This is part of my homework. All I need is a bit of advice. I need to write some nested loop constructs, to print the following:
"122333444455555"
"+**+++****+++++"
"--***++++-----******+++++++"
Here is my code to print the first set of symbols
public static void main (String[] args)
{
int i,j;
for(i=1;i<6;++i)
{
for(j=1;j<i+1;++j)
{
System.out.print(i);
}
}
}
This works perfectly fine. I'm just having trouble figuring out the second and third set of symbols. Apologies for my lack of experience, I'm fairly new to Java.
One solution is:
final String[] arr = {"*", "+"};
And in your inner loop:
System.out.print(arr[i % 2]);
The % (Modulo) operator is responsible of the switches between * and + symbols:
For even i it'll be *, otherwise it'll be +.
Output: "+**+++****+++++".
(Regarding the second output, I'll not show you the solution, but it's very similar to this one once you understand it).
public static void main(String[] args) throws IOException {
int i, j;
for (i = 1; i < 6; ++i) {
for (j = 1; j < i + 1; ++j) {
System.out.print(i);
}
}
System.out.println();
for (i = 1; i < 6; i++) {
if (i % 2 == 1) {
for (j = 1; j < i + 1; ++j){
System.out.print("+");
}
} else {
for (j = 1; j < i + 1; ++j){
System.out.print("*");
}
}
}
System.out.println();
for (i = 2; i < 8; i++) {
if (i % 3 == 1) {
for (j = 1; j <= i; ++j){
System.out.print("+");
}
} else if (i % 3 == 2) {
for (j = 1; j <= i; ++j){
System.out.print("-");
}
} else {
for (j = 1; j <= i; ++j){
System.out.print("*");
}
}
}
}
Cycle #1:
You have to print out numbers from one to five and each number N has to be printed out N times.
for (i = 1; i < 6; ++i) { // this would set `i` to numbers from 1-5
for (j = 1; j < i + 1; ++j) { // for each cycle (next number) it prints
//it out N times where N is the cycle number. 1 is the first cycle,
//2 is the second and so on.
Cycle #2:
Same problem but instead of printing out number of the cycle you have to print out + or * based on if the cycle number is odd or even.
To check if the number is even you can use:
int number = 1;
if(number % 2 == 0){ // is true if the number is even
This checks whats the remainder from the division of number by two.
Cycle #3:
Same as #2 but you start from the second cycle, not from the first and you check for the remainder after division by 3.
If I understand, the third set is composed by sequence of "-*+" so:
String sequence = "-*+";
String s = "+**+++****+++++";
int seqI = 0;
for(i=0; i != s.size(); ++i) {
for(j=0; j < i+2; ++j) {
System.out.print(sequence[seqI]);
}
if(seqI < sequence.size()) {
++seqI;
} else {
seqI = 0;
}
}
You can define a function like this:
public static char Output(int i, int mode)
{
if (mode == 1)
{
return (char) i;
}
else if (mode == 2)
{
if (i % 2 == 0)
{
return '+';
}
else
{
return '*';
}
}
else if (mode == 3)
{
if (i % 3 == 0)
{
return '-';
}
else if (i % 3 == 1)
{
return '*';
}
else
{
return '+';
}
}
}
And use it just like:
for (int mode = 1 ; mode < 4 ; mode++)
{
for (int i = 1 ; i < 6 ; i++)
{
for (int j = 0 ; j < i + (int)(mode / 3) ; j++)
{
System.out.println(Output(i, mode));
}
}
}
Note: Yes! Actually my code is hard to read, but if you try to read it, you will learn something more than other answers!

Categories