DFS method not producing expected output - java

So the goal is to print all possible numbers whose digits can be formed by a sequence of adjacent characters on a board using dfs. By adjacent I mean next to each other, either vertically, horizontally or diagonally. There are 8 total movement directions. Ex: the board below
1 2
3 4
To make it simpler let's say that we always have to start at row0 column0, which is 1. So the possible numbers are: 1, 12, 13, 14, 123, 124, 132, 134, 142, 143, 1234, etc (this case is pretty trivial because all numbers are directly adjacent to each other)
So I have the following code:
static char[][] grid;
static int rows;
static int columns;
public static void main(String[] args) {
//test grid. made it small so that solutions are easy to count
grid = new char[][]{
new char[]{'1', '2'},
new char[]{'3', '4'},
};
rows = grid.length;
columns = grid[0].length;
dfs(0, 0, new boolean[rows][columns], new StringBuilder());
}
public static void dfs(int row, int col, boolean[][] visited, StringBuilder builder){
visited[row][col] = true;
builder.append(grid[row][col]);
System.out.println(builder.toString());
//the 2 loops are for the 8 movement directions
for(int x = -1; x <= 1; x++){
for(int y = -1; y <= 1; y++){
//index bounds check
if((row + x >= 0) && (row + x < rows) && (col + y >= 0) && (col + y < columns)){
if(!visited[row + x][col + y]){
dfs(row + x, col + y, visited, builder);
// I tried changing it so that it passes a COPY of 'visited' and 'builder',
// but output still the same
dfs(row + x, col + y, Arrays.copyOf(visited, visited.length), new StringBuilder(builder));
}
}
}
}
}
My code's output is not right. Here's what it prints:
1
12
123
1234
Those numbers are part of the solution, but are a lot more numbers than that. The error probably has something to do with passing the same object into the recursive dfs() call, but I tried changing it so that it only copies the object, and it still gives the same output.
Any ideas?

You should be able to do achieve the expected output without creating a copy of the visited matrix.
The important thing is to set visited[row][col] to false after each COMPLETE visit down a path.
Example:
Let's say you've traversed '12' and now have '3' and '4' left to visit. In the current state, visited matrix's values for '1' and '2' are set to true and for '3' and '4' are set to false. Once you have finished generating all strings that begin with '12', you will start looking at all strings beginning with '13'.
But look at what happens here! You had set the visited value of '2' to true, and so no future strings containing '2' will ever be generated.
This is why you must set visited[row][col] to false after you are done generating all paths from that point onward.
To truly understand this, trace your code with pen and paper and you will remember it better.
Note:
In reality, in the example described above, you will never generate strings beginning with '13' because visited[1][1] would have been set to true before and so 3 would have never been reached again. I ignored that fact to illustrate a point.
Why do I suggest not making a deep copy of visited each recursive call? Simple, to save time and space. Each call will take O(m*n) space and time to generate and store a new visited matrix.
Here is one variant of the correct code:
import java.util.*;
public class DFS{
static char[][] grid;
static int rows;
static int columns;
public static void main(String[] args) {
//test grid. made it small so that solutions are easy to count
grid = new char[][]{
new char[]{'1', '2'},
new char[]{'3','4'},
};
rows = grid.length;
columns = grid[0].length;
ArrayList<String>list = new ArrayList<>();
dfs(0, 0, new boolean[rows][columns], new StringBuilder());
//System.out.println(list);
}
public static void dfs(int row, int col, boolean[][] visited, StringBuilder builder){
visited[row][col] = true;
builder.append(grid[row][col]);
System.out.println(builder);
for(int x = -1; x <= 1; x++){
for(int y = -1; y <= 1; y++){
//index bounds check
if((row + x >= 0) && (row + x < rows) && (col + y >= 0) && (col + y < columns)){
if(!visited[row + x][col + y]){
dfs(row + x, col + y, visited, builder);
}
}
}
}
visited[row][col]=false;
builder.deleteCharAt(builder.length()-1);
}
}
EDIT: I forgot to highlight the last line of code added where I delete the last character of the current StringBuilder. This is the backtracking bit so that after all '12xx' strings are generated, you delete '2', replace it with '3' and now start exploring the '13xx' family of strings.

Related

How to find most profitable Path in 2-Dimensional Array

I'm trying to implement a game where the viable moves are down-left and down-right.
The parameter for the function is for the size of the array, so if you pass 4 it will be a 4 by 4 array.
The starting position is the top row from any column. Every element in the array is a number in the range 1-100, taken from a file. I need to find the resulting value for the most profitable route from any starting column.
My current implementation will compare the right position and left position and move to whichever is higher. The problem is, for example, if the left position is lower in value than the right, but the left position will provide more profit in the long run since it can access higher value elements, my algorithm fails.
Here is a demo:
84 (53) 40 62
*42* 14 [41] 57
76 *47* 80 [95]
If we start at number 53. The numbers enclosed in * are the moves that my algorithm will take, but the numbers enclosed in [] are the moves my algorithm should take.
This is my code:
import java.util.ArrayList;
import java.util.Scanner;
public class bestPathGame{
private int[][] grid;
private int n;
public bestPathGame(int num){
Scanner input = new Scanner(System.in);
n = num;
grid = new int[n][n];
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
grid[i][j] = input.nextInt();
}
}
}
public static void main(String[] args){
bestPathGame obj = new bestPathGame(Integer.parseInt(args[0]));
obj.bestPath();
}
private boolean moveLeftBetter(int r,int c){
if(c <= 0){
return false;
} else if (c >= n -1 ){
return true;
}
return grid[r][c-1] > grid[r][c+1];
}
public void bestPath(){
ArrayList<Integer> allOptions = new ArrayList<>();
for(int k = 0; k < n; k++){
int row = 0;
int col = k;
int collection = grid[row][col];
while(row < n - 1){
row += 1;
if(moveLeftBetter(row,col)){
col-=1;
} else{
col+=1;
}
collection += grid[row][col];
}
allOptions.add(collection);
}
System.out.println(allOptions.stream().reduce((a,b)->Integer.max(a,b)).get());
}
}
Greedy algorithm vs Dynamic programming
There's an issue with the logic of your solution.
Basically, what you are implemented is a called a greedy algorithm. At each step of iteration, you are picking a result that optimal locally, assuming that this choice will lead to the optimal global result. I.e. your code is based on the assumption that by choosing a local maximum between the two columns, you will get the correct global maximum.
As a consequence, your code in the bestPath() method almost at each iteration will discard a branch of paths based on only one next value. This approach might lead to incorrect results, especially with large matrixes.
Greedy algorithms are rarely able to give an accurate output, usually their result is somewhat close but not precise. As an upper-hand, they run fast, typically in O(n) time.
For this problem, you need to use a dynamic programming (DP).
In short, DP is an enhanced brute-force approach which cashes the results and reuses them instead of recalculating the same values multiple times. And as well, as a regular brute-force DP algorithms are always checking all possible combinations.
There are two major approaches in dynamic programming: tabulation and memoization (take a look at this post for more information).
Tabulation
While implementing a tabulation first you need to create an array which then need to be prepopulated (completely or partially). Tabulation is also called the bottom-up approach because calculation start from the elementary edge cases. Every possible outcome is being computed based on the previously obtained values while iterating over this array. The final result will usually be stored in the last cell (in this case in the last row).
To implement the tabulation, we need to create the matrix of the same size, and copy all the values from the given matrix into it. Then row by row every cell will be populated with the maximum possible profit that could be obtained by reaching this cell from the first row.
I.e. every iteration will produce a solution for a 2D-array, that continuously increases by one row at each step. It'll start from the array that consists of only one first row (no changes are needed), then to get the profit for every cell in the second row it's values has to be combined with the best values from the first row (that will be a valid solution for 2D-array of size 2 * n), and so on. That way, solution gradually develops, and the last row will contain the maximum results for every cell.
That how the code will look like:
public static int getMaxProfitTabulation(int[][] matrix) {
int[][] tab = new int[matrix.length][matrix.length];
for (int row = 0; row < tab.length; row++) { // populating the tab to preserve the matrix intact
tab[row] = Arrays.copyOf(matrix[row], matrix[row].length);
}
for (int row = 1; row < tab.length; row++) {
for (int col = 0; col < tab[row].length; col++) {
if (col == 0) { // index on the left is invalid
tab[row][col] += tab[row - 1][col + 1];
} else if (col == matrix[row].length - 1) { // index on the right is invalid
tab[row][col] += tab[row - 1][col - 1];
} else {
tab[row][col] += Math.max(tab[row - 1][col - 1], tab[row - 1][col + 1]); // max between left and right
}
}
}
return getMax(tab);
}
Helper method responsible for extracting the maximum value from the last row (if you want to utilize streams for that, use IntStream.of(tab[tab.length - 1]).max().orElse(-1);).
public static int getMax(int[][] tab) {
int result = -1;
for (int col = 0; col < tab[tab.length - 1].length; col++) {
result = Math.max(tab[tab.length - 1][col], result);
}
return result;
}
Memoization
The second option is to use Memoization, also called the top-down approach.
As I said, DP is an improved brute-force algorithm and memoization is based on the recursive solution that generates all possible outcomes, that is enhanced by adding a HashMap that stores all previously calculated results for every cell (i.e. previously encountered unique combination of row and column).
Recursion starts with the first row and the base-case of recursion (condition that terminates the recursion and is represented by a simple edge-case for which output is known in advance) for this task is when the recursive call hits the last row row == matrix.length - 1.
Otherwise, HashMap will be checked whether it already contains a result. And if it not the case all possible combination will be evaluated and the best result will be placed into the HashMap in order to be reused, and only the then the method returns.
Note that tabulation is usually preferred over memoization, because recursion has significant limitations, especially in Java. But recursive solutions are sometimes easier to came up with, so it's completely OK to use it when you need to test the idea or to prove that an iterative solution is working correctly.
The implementation will look like that.
public static int getMaxProfitMemoization(int[][] matrix) {
int result = 0;
for (int i = 0; i < matrix[0].length; i++) {
result = Math.max(result, maxProfitHelper(matrix, 0, i, new HashMap<>()));
}
return result;
}
public static int maxProfitHelper(int[][] matrix, int row, int col,
Map<String, Integer> memo) {
if (row == matrix.length - 1) { // base case
return matrix[row][col];
}
String key = getKey(row, col);
if (memo.containsKey(key)) { // if cell was already encountered result will be reused
return memo.get(key);
}
int result = matrix[row][col]; // otherwise result needs to be calculated
if (col == matrix[row].length - 1) { // index on the right is invalid
result += maxProfitHelper(matrix, row + 1, col - 1, memo);
} else if (col == 0) { // index on the left is invalid
result += maxProfitHelper(matrix, row + 1, col + 1, memo);
} else {
result += Math.max(maxProfitHelper(matrix, row + 1, col - 1, memo),
maxProfitHelper(matrix, row + 1, col + 1, memo));
}
memo.put(key, result); // placing result in the map
return memo.get(key);
}
public static String getKey(int row, int col) {
return row + " " + col;
}
Method main() and a matrix-generator used for testing purposes.
public static void main(String[] args) {
int[][] matrix = generateMatrix(100, new Random());
System.out.println("Tabulation: " + getMaxProfitTabulation(matrix));
System.out.println("Memoization: " + getMaxProfitMemoization(matrix));
}
public static int[][] generateMatrix(int size, Random random) {
int[][] result = new int[size][size];
for (int row = 0; row < result.length; row++) {
for (int col = 0; col < result[row].length; col++) {
result[row][col] = random.nextInt(1, 101);
}
}
return result;
}

Project Euler Problem 18 - Pascal's Triangle

EDIT 2
I separated out the offset code into a new method at Gavin's suggestion:
private static int getOffset(int offset, int row, int col, ArrayList<ArrayList<Integer>> triangle, ArrayList<ArrayList<Integer>> p_triangle, ArrayList<Integer> sums) {
int row_num = (row+1); //= 1-indexed row #
int p_value = p_triangle.get(row).get(col); // number from pascal's triangle
if (col > 1) {
// element is in the left half of Pascal's Triangle
if (col <= (row_num/2)) offset++;
// penultimate element
else if (col == row_num - 2) offset = sums.size() - p_value;
// elements halfway until penultimate;
// [-2, -3] all work up until row 10 and fail thereafter
else offset = sums.size() - p_value - (row_num - col - 2);
}
return offset;
}
And found that, oddly enough, subtracting 2 or 3 both work when calculating the offset for an element in the latter half of the given row (between halfway and antepenultimate). And I have no idea why that's the case.
Even stranger is that I modified Oleg's answer
public static int findMaxSum(ArrayList<ArrayList<Integer>> data) {
for (int row = data.size() - 2; row >= 0; row--)
for (int col = 0; col < data.get(row).size(); col++)
data.get(row).set(col, data.get(row).get(col) + Math.max(data.get(row + 1).get(col), data.get(row + 1).get(col + 1)));
return data.get(0).get(0);
}
and found that the behavior of algorithm appears to be correct up to a triangle of size 10. However, it starts to breakdown after that with the following discrepancies in rows 11-15:
size = 11 [correct:772 | mine:752]
size = 12 [correct:850 | mine:830]
size = 13 [correct:908 | mine:921]
size = 14 [correct:981 | mine:961]
size = 15 [correct:1074 | mine:1059]
Unfortunately, I still can't discern a pattern from this.
EDIT
I'd like to emphasize that I'm not looking for a better way to solve this particular Project Euler problem; instead, I just want to know if it's possible to use Pascal's Triangle to do it in the way I described (or in some slightly modified way) and if someone can see the logic in my code I may be blind to.
ORIGINAL QUESTION
I am trying to solve Project Euler problem 18.
The goal is to find the max sum of all the 2^14 paths down a triangle of numbers.
I was struck by the similarity with Pascal's Triangle and wondered if it could be used to solve the problem.
My logic is as follows:
1.) Calculate the sums by row.
2.) Use Pascal's triangle to determine how many there must be (as each row adds up to a power of two) and to determine the offset from the start of the of the previous rows sums.
Ex.
Pascal's Triangle
1
1 1
1 2 1
1 3 3 1
Triangle To Process
3
7 4
2 4 6
8 5 9 3
Sums
[3]
[10, 7]
[12, 14, 11, 13]
[20, 17, 19, 16, 23, 20, 22, 16]
For row 3, we see Pascal's Triangle informs us that there will be 1 + 2 + 1 or 4 values. Furthermore, it describes how to build the sums because it's the first and last element added to the sum directly preceding them and the middle value added to both of those sums as it has contact with both the preceding chains.
By extension, the fourth row shows that the second number in the Triangle to Process should be added to the first three sums from row three and the third number should be added to the final three.
The way I get the offset is kind of ugly (and maybe the source of the trouble):
if (i > 1) {
if (i < (p_triangle.get(row).size()/2)) offset++;
else if (i == triangle.get(row).size()-2) offset = sums.size() - p_triangle.get(row).get(i);
else offset = sums.size() - p_triangle.get(row).get(i) - (p_triangle.get(row).size() - i - 2);
}
Where p_triangle.get(row) is the current Pascal's Triangle row being used, sums is the array of cumulative sums (2^(row-1) in length), offset is where to start the summations from, and the Pascal's Triangle number is how many elements from the sum list starting at the offset to sum the number at index i in the Triangle to Process, i.e., triangle.get(row).get(i).
I know this may not be the most efficient algorithm to solve the problem, but it seems like it could be a nice one. The thing is, I can't get it to work.
SPOILER ALERT ON THE ANSWER TO THE PROBLEM
The correct answer is apparently 1074
Can anyone tell me where in the code or in my logic for using Pascal's Triangle, I might have messed up?
THE FULL CODE:
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.lang.Math;
public class MaxPathSum {
private static ArrayList<ArrayList<Integer>> pascalsTriangle(int n_rows) {
ArrayList<ArrayList<Integer>> triangle = new ArrayList<>();
triangle.add(new ArrayList<Integer>(){{add(1);}});
triangle.add(new ArrayList<Integer>(){{add(1); add(1);}});
for (int row = 2; row < n_rows; row++) {
ArrayList<Integer> next_row = new ArrayList<>();
next_row.add(1);
for (int i = 1; i < triangle.get(row-1).size(); i++) {
next_row.add(triangle.get(row-1).get(i-1) + triangle.get(row-1).get(i));
}
next_row.add(1);
triangle.add(next_row);
}
return triangle;
}
private static ArrayList<ArrayList<Integer>> buildTriangle(int n_rows) {
Scanner sc = new Scanner(System.in);
ArrayList<ArrayList<Integer>> triangle = new ArrayList<>();
for (int row = 1; row <= n_rows; row++) {
ArrayList<Integer> row_arr = new ArrayList<>();
for (int elem = 1; elem <= row; elem++) {
row_arr.add(sc.nextInt());
}
triangle.add(row_arr);
}
return triangle;
}
private static int findLargestSum(ArrayList<ArrayList<Integer>> triangle, ArrayList<ArrayList<Integer>> p_triangle) {
ArrayList<Integer> sums = new ArrayList<>();
sums.add(triangle.get(0).get(0));
// traverse the rows
for (int row = 1, offset = 0; row < triangle.size(); row++, offset = 0) {
ArrayList<Integer> new_sums = new ArrayList<>();
// traverse each element in each row
new_sums.add(sums.get(0) + triangle.get(row).get(0));
for (int i = 1; i < triangle.get(row).size()-1; i++) {
int n_times = p_triangle.get(row).get(i);
for (int j = 0; j < n_times; j++) {
new_sums.add(triangle.get(row).get(i) + sums.get(j+offset));
}
if (i > 1) {
if (i < (p_triangle.get(row).size()/2)) offset++;
else if (i == triangle.get(row).size()-2) offset = sums.size() - p_triangle.get(row).get(i);
else offset = sums.size() - p_triangle.get(row).get(i) - (p_triangle.get(row).size() - i - 2);
System.out.println("Row: " + row + " | Offset: " + offset);
}
}
new_sums.add(sums.get(sums.size()-1) + triangle.get(row).get(triangle.get(row).size()-1));
sums = new_sums;
}
Collections.sort(sums);
return sums.get(sums.size() - 1);
}
public static void main(String[] args) {
int n_rows = Integer.parseInt(args[0]);
// build pascalsTriangle
ArrayList<ArrayList<Integer>> p_triangle = pascalsTriangle(n_rows);
// build triangle from input
ArrayList<ArrayList<Integer>> triangle = buildTriangle(n_rows);
// traverse triangle finding largest sum
int largest_sum = findLargestSum(triangle, p_triangle);
// display results
System.out.println(largest_sum);
}
}
Just be simple!
public static int findMaxSum(int[][] data) {
for (int row = data.length - 2; row >= 0; row--)
for (int col = 0; col < data[row].length; col++)
data[row][col] += Math.max(data[row + 1][col], data[row + 1][col + 1]);
return data[0][0];
}

Leetcode solution not working the same as local environment (Surrounded Regions)

https://leetcode.com/problems/surrounded-regions/
I read through the editorial, and coded up a solution. Everything makes sense, and locally my code changes the board to the expected output, yet when I paste the code to Leetcode, my board stays the same. I used their debugger and placed a breakpoint at line 24, sure enough, I don't see any changes on the board.
Not sure where else to ask this, so I'm sorry if this isn't the right place.
The following is my code:
import java.util.Arrays;
class Solution {
private int ROWS;
private int COLS;
public void solve(char[][] board) {
ROWS = board.length;
COLS = board[0].length;
// parse left and right borders
for (int i = 0; i < ROWS; i++) {
DFS(board, i, 0); // left border
DFS(board, i, ROWS - 1); // right border
}
// parse top and bottom borders
for (int j = 0; j < COLS; j++) {
DFS(board, 0, j); // top border
DFS(board, COLS - 1, j); // bottom border
}
// after parsing, we end up with x, o, e board. Pass through it, and change
// 1) o to x
// 2) e to o
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
if (board[i][j] == 'o') {
board[i][j] = 'x';
}
else if (board[i][j] == 'e') {
board[i][j] = 'o';
}
}
}
}
private void DFS(char[][] board, int i, int j) {
if (i >= ROWS || j >= COLS) return; // bounds
if (board[i][j] != 'o') return;
board[i][j] = 'e'; // temporary marker, to help identify border-connected cells
// go right
DFS(board, i, j + 1);
// go down
DFS(board, i + 1, j);
// go left
DFS(board, i, j - 1);
// go up
DFS(board, i - 1, j);
}
public static void main (String[] args) {
char[][] test1 = new char[][] {
{'x','x','x','x'},
{'x','o','o','x'},
{'x','x','o','x'},
{'x','o','x','x'}
};
new Solution().solve(test1);
Arrays.stream(test1).forEach(e -> System.out.println(Arrays.toString(e)));
}
}
Running it locally, I get exactly what's expected in the console
[x, x, x, x]
[x, x, x, x]
[x, x, x, x]
[x, o, x, x]
Your main issue is that your code assumes a matrix of lowercase O and X, while the LeetCode problem gives you matrix of uppercase O and X. Since 'o' is not the same as 'O', and 'x' is not the same as 'X', your code doesn't solve the LeetCode problem.
In the future, I recommend using copy-and-paste when copying test-cases, so that you get them exactly right.
Since I'm here, I'll also point out two other issues with your code:
Your depth-first search has logic to ensure that you never walk off the bottom or right edge of the grid, but it doesn't do anything to ensure that you never walk off the top or left edge. (Your test-case doesn't trigger that, because there are no O's along the top or left edge that test-case.)
Your code has various comments that talk about "parsing", when in fact you're doing no such thing. (See https://www.google.com/search?q=parsing.) That won't affect your code's behavior, obviously, but it can confuse human readers, or at least make you look a bit clueless. I'd suggest writing (for example) // find all O's connected to left and right borders, and change them to E's.

Java Sudoku brute force solver, how does it work?

So you find the code below here. Most of the code I understand, but there is one bit I don't. The place where we create the boolean array called digits and the bit after that 3 * (x / 3).
I think it's used to check if each square in the sudoku has 9 unique numbers as well, but I'm not sure on how I can explain this to let's say someone next to me.
Why do I need the array of boolean here? Can someone explain to me what it is doing and why?
Kind regards!
public int[][] solvePuzzle(int[][] matrix) {
int x, y = 0;
boolean found = false;
// First we check if the matrix contains any zeros.
// If it does we break out of the for loop and continue to solving the puzzle.
for (x = 0; x < 9; x++) {
for (y = 0; y < 9; y++) {
if (matrix[x][y] == 0) {
found = true;
break;
}
}
if (found) {
break;
}
}
// If the puzzle doesn't contain any zeros we return the matrix
// We now know that this is the solved version of the puzzle
if (!found) {
return matrix;
}
boolean digits[] = new boolean[11];
for (int i = 0; i < 9; i++) {
digits[matrix[x][i]] = true;
digits[matrix[i][y]] = true;
}
int boxX = 3 * (x / 3), boxY = 3 * (y / 3);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
digits[matrix[boxX + i][boxY + j]] = true;
}
}
// We loop over all the numbers we have to check if the next number fits in the puzzle
// We update the matrix and check recursively by calling the same function again to check if the puzzle is correct
// If it's not correct we reset the matrix field to 0 and continue with the next number in the for loop
for (int i = 1; i <= 9; i++) {
if (!digits[i]) {
matrix[x][y] = i;
if (solvePuzzle(matrix) != null) {
return matrix;
}
matrix[x][y] = 0;
}
}
// The puzzle can't be solved so we return null
return null;
}
I have added some explanation as comments inline:
//we need to know what digits are we still allowed to use
//(not used in this row, not used in this column, not used in
//the same 3x3 "sub-box")
boolean digits[] = new boolean[11];
//so we run through the rows/coumns around the place (x,y)
//we want to fill in this iteration
for (int i = 0; i < 9; i++) {
//take a used number from the row of x (matrix[x][i]) and mark it
// as used
digits[matrix[x][i]] = true;
//take a used number from the column of y (matrix[i][y]) and mark it
// as used
digits[matrix[i][y]] = true;
}
//find the top-left corner of the sub-box for the position (x,y) we
//want to fill in
//example: x is 8 -> 3 * 8/3 -> 6, so we start from 6
int boxX = 3 * (x / 3), boxY = 3 * (y / 3);
//iterate through the sub-box horizontally and vertically
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//take a used number from the sub-box and mark it
// as used
digits[matrix[boxX + i][boxY + j]] = true;
}
}
There seem to be two issues you are unclear on:
The boolean array - this array is used to track which digits have been used already on a specific row or column. So imagine a row of tick boxes each with a digit written next to it (the array index) - these boxes are checked or unchecked to show a digit has been used or not.
The expressions 3* (x/3) and 3 * (y/3) - what you need to remember here is that this is integer division (that means the result of the division is always rounded down to an integer. For example if x=1 then 3 (x/3) is 3 (1/3) is 3 * (0) =0 (whereas if this was float division the result would be 3*(0.3333)=1. So these maths expressions essentially change you number to the next lowest multiple of three - that is 1 -> 0, 2 -> 0, 3 -> 3, 4 -> 3 etc.

Android - Compute times a two numbers appear in cell number

Could anyone help me. I am trying to compute the number of times certain numbers appear in a table layout row - vertically and Horizontally, in other words. I would like to fill an array of numbers between say (4 and 5) to make it so that the number say 4 appears only 4times and 5 only twice (vertically & Horizontally) in say 6 * 6..take note
How can I work with any of this?
public boolean hasRepeatedNumbers(int[] x) {
int[] y = new int[x.length];
System.arraycopy(x, 0, y, 0, y.length);
Array.sort(y);
int i;
for (i = 1; i < y.length; i++) {
if (y[i] == y[i-1]) return true;
}
return false;
}
or
private int[] calculateUsedCells(int x, int y) {
int c[] = new int[2];
// horizontal
for (int i = 0; i < 2; i++) {
if (i == y)
continue;
int t = getCell(x, i);
if (t != 0)
c[t - 1] = t;
}
}
Any advice would be great, thanks.
Consider taking an int array and increase the element in the array at index of the value in the cell, at the end check the values in the array. You will get the number of times each number appeared.
Ex:
Number 4 has appeared in 1, 2, 5, 6 cells
array[content of the cell]++;
So at the end array[4] gives the number of times 4 appeared.

Categories

Resources