how to count number of un-ordered partitions of a number - java

I am really stuck at this problem.
In this problem, you are given a 2xN board. You need to fill in non-negative numbers in this board in such a way, that:
The sum of all the numbers filled = N
Each of the 2 rows
consist of numbers in non-increasing order
Each of the N
columns consist of numbers in non-increasing order.
In how many ways can this be done, given the number N?
Two ways are considered different if there is a cell in the board which has different numbers.
The output should be the number of ways the matrix can be formed.
The matrix can have repetitive numbers and zero can be used. The matrix should not have increasing numbers but equal numbers can be filled along side each other.
Example:
input-> 5
output->16

From your example (input=5, output=16) I suppose only integer numbers are allowed.
One naive (brute force) solution is to use backtracing algorithm:
http://en.wikipedia.org/wiki/Backtracking
On this site you can see example with sudoku board being filled until solution is found.
==
For example:
You have array of integers with size 2N.
For position 0 you take first free number.
If solution is not broken yet you go to position 1 of array.
If solution is broken - stop as cannot back anymore
For position 1 you take next free number.
If solution is not broken you you go to position 2 of array.
If solution is broken you back to previous sten and take next free number.
For position 2...
This is typically done with recursion.
I think, on each position (recursion level) numbers can be taken from pool 0..N.
Try - good luck.
EDIT:
Here is valid solution (using backtracking algo):
private final int N = 5;
// 2 rows in one array [0..N-1, N..2N-1]
private int[] board = new int[2 * N];
// found solution counter
int found = 0;
/*
* this method set next number to current position
* and recursively go to next position.
*/
public void check(int position) {
// if board is complete - check if valid
if (position == 2 * N) {
if (isValid()) {
System.out.println("foun : " + Arrays.toString(board));
found++;
}
return;
}
// if board is not complete - put all numbers (0..N) into current position
// and recursively go to next position
for (int v = 0; v <= N; v++) {
board[position] = v;
// if solution is already broken - step backwards
// see: backtracking algorithms
if (isBroken(position)) {
return;
}
check(position + 1);
}
}
public boolean isValid() {
// condition 1
int sum = 0;
for (int i = 0; i < board.length; i++) {
sum += board[i];
}
if (sum != N) {
return false;
}
// conditin 2
int prev = board[0];
for (int i = 1; i < N; i++) {
if (board[i] > prev) {
return false;
}
prev = board[i];
}
prev = board[N];
for (int i = N + 1; i < 2 * N; i++) {
if (board[i] > prev) {
return false;
}
prev = board[i];
}
// condition 3
for (int i = 0; i < N; i++) {
int top = board[i];
int bottom = board[i + N];
if (top < bottom) {
return false;
}
}
// valid
return true;
}
// simplified version of this method - but correct
public boolean isBroken(int current) {
int sum = 0;
for (int i = 0; i <= current; i++) {
sum += board[i];
}
return sum > N;
}
public void start() {
check(0);
System.out.println("found: " + found);
}
And program output for N = 5:
found : [1, 1, 1, 0, 0, 1, 1, 0, 0, 0]
found : [1, 1, 1, 1, 0, 1, 0, 0, 0, 0]
found : [1, 1, 1, 1, 1, 0, 0, 0, 0, 0]
found : [2, 1, 0, 0, 0, 1, 1, 0, 0, 0]
found : [2, 1, 0, 0, 0, 2, 0, 0, 0, 0]
found : [2, 1, 1, 0, 0, 1, 0, 0, 0, 0]
found : [2, 1, 1, 1, 0, 0, 0, 0, 0, 0]
found : [2, 2, 0, 0, 0, 1, 0, 0, 0, 0]
found : [2, 2, 1, 0, 0, 0, 0, 0, 0, 0]
found : [3, 0, 0, 0, 0, 2, 0, 0, 0, 0]
found : [3, 1, 0, 0, 0, 1, 0, 0, 0, 0]
found : [3, 1, 1, 0, 0, 0, 0, 0, 0, 0]
found : [3, 2, 0, 0, 0, 0, 0, 0, 0, 0]
found : [4, 0, 0, 0, 0, 1, 0, 0, 0, 0]
found : [4, 1, 0, 0, 0, 0, 0, 0, 0, 0]
found : [5, 0, 0, 0, 0, 0, 0, 0, 0, 0]
found: 16

I'm almost positive this has a solution in closed form, or its similar to another problem with a solution in closed form. I would do it programmatically with recursion.
So suppose you know a solution for N. You want N+1. So what you should do is take all the solutions for N and see where you can stick an extra 1 in there without breaking any constraints. That is, super impose the N solution(s) on the N+1 board then try in all 2N places to add 1 without breaking constraints. Then store all of them in a set so they will be deduped.
In any case, its similar to http://en.wikipedia.org/wiki/Partition_(number_theory)

Here's a brute force way: since this is a 2xN matrix and the sum of all numbers must be N, the simplest solution is to fill the first row with 1's, and the 2nd row with 0's. Now you will need a recursive algorithm that takes a valid board, and removes 1 from any "free" position and add it to any legal position. That board is also a solution. By "free" I mean a number n at position [i, j] where [i+1, j] <= n - 1 and [i, j + 1] <= n - 1. You then recursively invoke the algorithm on the new boards, and save everything.
All that's left is to deduplicate solutions.
Example of the algorithm on input 5:
Initial solution:
11111
00000
The only "free" number is [0, 4]. Remove 1, the only legal positions are [0, 0] and [0, 1]. This gives you 2 new solutions
21110
00000
and
11110
10000
Now apply same algorithm again on both these solutions. Notice that the 2nd board now has 2 "free" numbers. Repeat until you get to
50000
00000
EDIT: Just had a lot of fun coding this example. Didn't test it, but that's where my head is going:
public void TwoRowBoard()
{
var board = new int[2, N];
//Create initial, simplest solution.
for (int i = 0; i < N; i++)
{
board[0, i] = 1;
}
var solutions = new List<int[,]>();
RecursiveSolve(board, solutions);
}
private void RecursiveSolve(int[,] board, List<int[,]> solutions)
{
var freeNumbers = GetFreeNumbers(board);
foreach (var freeNumber in freeNumbers)
{
board[freeNumber.i, freeNumber.j] -= 1;
var legalPositions = GetLegalPositions(board);
foreach (var legalPosition in legalPositions)
{
var newBoard = Copy(board);
newBoard[legalPosition.i, legalPosition.j] += 1;
solutions.Add(newBoard);
RecursiveSolve(newBoard, solutions);
}
}
}
private List<Coordinates> GetLegalPositions(int[,] board)
{
//Position 0, 0 is always legal.
var results = new List<Coordinates> {new Coordinates {i = 0, j = 0}};
//Row 0
for (int j = 1; j < N; j++)
{
if (board[0, j - 1] > board[0, j])
{
results.Add(new Coordinates{i = 0, j = j});
}
}
//Row 1. Board[1, higher than N/2] are never legal positions.
for (int j = 0; j <= N /2; j++)
{
if (board[1, j - 1] > board[1, j]
&& board[0, j] > board[1, j])
{
results.Add(new Coordinates{i = 1, j = j});
}
}
return results;
}
private List<Coordinates> GetFreeNumbers(int[,] board)
{
var results = new List<Coordinates>();
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < N; j++)
{
if (i == 0 && j == 0)
{
continue;
}
if (i == 0)
{
if (j == N - 1 && board[0, j] > 0)
{
results.Add(new Coordinates {i = 0, j = j});
}
else if (board[0, j] > board[1, j]
&& board[0, j] > board[0, j + 1])
{
results.Add(new Coordinates {i = 0, j = j});
}
}
else
{
if (j > N/2 && board[1, j] > 0)
{
throw new Exception("Don't see how it's possible for board[1, N/2 or higher] to not be 0");
}
if (board[1, j] > board[1, j + 1])
{
results.Add(new Coordinates{i = 1, j = j});
}
}
}
}
return results;
}
public class Coordinates
{
public int i { get; set; }
public int j { get; set; }
}

Related

How to merge two elements in an array together?

For example you have the 2d array Board as shown below:
{0, 2, 4, 2}
{0, 0, 2, 2}
{2, 2, 0, 0}
{0, 5, 0, 2}
You want it to become:
{0, 2, 4, 2}
{0, 0, 4, 0}
{4, 0, 0, 0}
{0, 5, 0, 2}
When there are 2 elements next to each other you need to merge them to make 4 into the left-most place out of those two elements and then make the 2nd element to be 0.
You want to do this with java.
forgot to show my existing loop, this is it below:
for (int row = 0; row < Board.length; row++){
for (int col = 0; col <= Board.length; col++){
if ((Board[row][col] == Board[row][col +1])){
Board[row][col] = 2 * Board[row][col];
Board[row][col + 1] = 0;
}
}
}
Well, I guess that should work. In the loop, you must be careful not to refer to the wrong ( or non-existing) array element.
public static void main(String[] args) {
int[][] arr = new int[][]{{0, 2, 4, 2}, {0, 0, 2, 2}, {2, 2, 0, 0}, {0, 5, 0, 2}, {2, 2, 2, 2}, {2, 2, 2, 0}};
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length - 1; j++) {
if (arr[i][j] == arr[i][j + 1]) {
arr[i][j] = arr[i][j] + arr[i][j + 1];
arr[i][j + 1] = 0;
}
}
}
System.out.println(Arrays.deepToString(arr));
}
Here is one way, focusing only array values that equal 2.
iterate the 2D array.
then iterate over each linear array, checking adjacent values and making the changes.
for(int[] arr : v) {
for(int i = 0; i < arr.length-1; i++) {
if (arr[i] == 2 && arr[i+1] == 2) {
arr[i]+= arr[i+1];
arr[i+1] = 0;
}
}
}
for(int arr[]: v) {
System.out.println(Arrays.toString(arr));
}
prints
[0, 2, 4, 2]
[0, 0, 4, 0]
[4, 0, 0, 0]
[0, 5, 0, 2]
Well I assume that Board variable holds array (quick tip, common convention is to name variable in camelCase (first letter lowercase, then each letter of next work upper, if that variable is constant, then convention is SNAKE_UPPER_CASE)
Your first for is pretty okay, the second one too but it assumes that matrix will be always NxN and will fail if thats not the case or it will not work properly (depending if amount of cols is lower or greater than length of array)
Inside it you dont want to check if the values are equal, you want to check if these values are both equal to 2. And you should check if thats not processing of last column of the row, in that case youll get IndexOutOfBoundException because you want to get value of matrix that is not present.
So with small changes, you will achieve what you want. This code will hopefuly shows my thoughts better
public class MergingTwos {
public static void main(String args[]) {
// Init a matrix
int[][] array = new int[][] { { 0, 2, 4, 2 }, { 0, 0, 2, 2 }, { 2, 2, 0, 0 }, { 2, 2, 0, 0 }, { 0, 5, 0, 2 }};
// Iterating over each row of matrix, in veriable i, the current X index is stored
for(int i = 0; i < array.length; i++) {
// Iterating over each column of row, in variable n, the current Y index is stored
for(int n = 0; n < array[i].length; n++) {
// To prevent index out of bound exception, last element of row wont be processed so as we dont want to proceed if given and next value on row are not 2
if(n == array[i].length -1 || array[i][n] != 2 || array[i][n+1] != 2) {
continue;
}
// To value at given coordinates [i,n] you add values of value on coordinates [i, n+1]
array[i][n] = array[i][n] + array[i][n+1];
// And setting next element to 0
array[i][n+1] = 0;
}
}
// Printing the result
for (int[] x : array) {
for (int y : x) {
System.out.print(y + " ");
}
System.out.println();
}
}
}

Java array order

I have the following array:
int [] mi_array= {9,4,0,0,4,0,3,0,1,8,0};
I want to order the numbers other than 0 on the left, and the 0s on the right, but I find that the function steps on one of the numbers.
The output must be
{9,4,4,3,1,8,0,0,0,0,0}
public class Array {
public static void main(String[] args) {
int [] mi_array= {9,4,4,3,1,8,0,0,0,0,0};
int x=0;
int y=mi_array.length-1;
for (int i=0;i<mi_array.length;i++)
if(mi_array[i]!=0) {
mi_array[x]=mi_array[i];
x++;
}
else {
mi_array[y]=mi_array[i];
y--;
}
for (int i=0;i<mi_array.length;i++)
System.out.println(mi_array[i]);
System.out.println(x);
}
}
Try this.
int[] mi_array = {9, 4, 0, 0, 4, 0, 3, 0, 1, 8, 0};
for (int i = 0, j = i + 1, s = mi_array.length; j < s;)
if (mi_array[i] == 0) {
mi_array[i] = mi_array[j];
mi_array[j] = 0;
++j;
} else if (++i >= j)
j = i + 1;
System.out.println(Arrays.toString(mi_array));
// -> [9, 4, 4, 3, 1, 8, 0, 0, 0, 0, 0]
You can use filter and IntStream.concat to merge the parts of the array that are not 0 with the parts that are.
final int[] mi_array = { 9, 4, 0, 0, 4, 0, 3, 0, 1, 8, 0 };
final int[] result = IntStream.concat(Arrays.stream(mi_array).filter(i -> i != 0),
Arrays.stream(mi_array).filter(i -> i == 0)).toArray();
System.out.println(Arrays.toString(result));
Demo!
You can also do this:
final int[] mi_array = { 9, 4, 0, 0, 4, 0, 3, 0, 1, 8, 0 };
final int[] result = new int[mi_array.length];
final AtomicInteger idx = new AtomicInteger();
Arrays.stream(mi_array).filter(i -> i != 0).forEach(val -> result[idx.getAndIncrement()] = val);
System.out.println(Arrays.toString(result));
Your primary problem here is that you overwrite numbers you haven't already covered.
if (mi_array[i] != 0) {
mi_array[x] = mi_array[i];
x++;
}
x can never exceed i in this code; it starts at 0 just like i does, and increments at most by 1 every loop (and i increments by 1 every loop). So, no problem here; at 'worst' this is mi_array[i] = mi_array[i]; which does nothing.
however...
} else {
mi_array[y]=mi_array[i];
y--;
}
This is much more problematic. Given inputs {9,4,0,0,4,0,3,0,1,8,0};, when i is 2, then mi_array[i] is 0, thus this code runs. y is still 10, so this will end up running: mi_array[10] = 0;. The second 0 occurs when i is 3, and ends up running: mi_array[9] = 0;. And at that point, the 8 at index 9? You deleted it. It cannot be recovered.
The solution
The dumb solution is to make a copy of the array; edit the copy, refer to the original (which you won't change at all). You don't actually end up needing a copy; this code will write every number back, so just make a new array of the same size and write in that.
A slightly more elegant solution will not write 0s at all. Instead, it just writes the non-zeroes (as that code cannot overwrite anything, as shown before), and then at the end, overwrite the rest with zeroes. Now you don't need a copy.
O(n), two-pointer approach:
public static void shiftZeroesRight(int[] array) {
int notZeroPos;
for (int i = 0; i < array.length; i++) {
if (array[i] != 0)
continue;
notZeroPos = i + 1;
while (notZeroPos < array.length && array[notZeroPos] == 0)
++notZeroPos;
if (notZeroPos >= array.length)
break;
array[i] = array[notZeroPos];
array[notZeroPos] = 0;
}
}

Java: How to implement Conway's Game of Life?

I'm studying the Conway's Game of Life to implement it on my own, and came across the following implementation with the rules:
Given a board with m by n cells, each cell has an initial state live (1) or dead (0). Each cell interacts with its eight neighbors (horizontal, vertical, diagonal) using the following four rules (taken from the above Wikipedia article):
Any live cell with fewer than two live neighbors dies, as if caused by under-population.
Any live cell with two or three live neighbors lives on to the next generation.
Any live cell with more than three live neighbors dies, as if by over-population..
Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
And implementation (https://discuss.leetcode.com/topic/29054/easiest-java-solution-with-explanation):
public void gameOfLife(int[][] board) {
if (board == null || board.length == 0) return;
int m = board.length, n = board[0].length;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
int lives = liveNeighbors(board, m, n, i, j);
// In the beginning, every 2nd bit is 0;
// So we only need to care about when will the 2nd bit become 1.
if (board[i][j] == 1 && lives >= 2 && lives <= 3) {
board[i][j] = 3; // Make the 2nd bit 1: 01 ---> 11
}
if (board[i][j] == 0 && lives == 3) {
board[i][j] = 2; // Make the 2nd bit 1: 00 ---> 10
}
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
board[i][j] >>= 1; // Get the 2nd state.
}
}
}
public int liveNeighbors(int[][] board, int m, int n, int i, int j) {
int lives = 0;
for (int x = Math.max(i - 1, 0); x <= Math.min(i + 1, m - 1); x++) {
for (int y = Math.max(j - 1, 0); y <= Math.min(j + 1, n - 1); y++) {
lives += board[x][y] & 1;
}
}
lives -= board[i][j] & 1;
return lives;
}
And driver:
public static void main(String args[]) {
GameOfLife gl = new GameOfLife();
int[][] board = {
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 0, 0, 0, 0, 0},
{0, 1, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0}
};
gl.gameOfLife(board);
}
And my question is, what do the x and y in liveNeighbors() represent? Do not understand why the need for Math.min() and Math.max(). And also, does lives represent the amount of initialized lives on the board?
The given code is using the min and max functions to limit the search to valid entries in the array. If this is not done, the code will return an ArrayOutOfBoundsException when trying to use -1, m, or n as array indexes. (The loop doesn't "know" that given a square at the right edge of the map, it shouldn't search for living neighbors further to the right; these functions encode that fact.) x and y are simply the loop control variables which are used to iterate over valid squares surrounding the target square.
As for the lives variable, that's the placeholder to keep count of how many live neighbors have been found by the loops below. You might have guessed this by the fact that it's the return value of the liveNeighbors function.
Let's do an example. We'll call liveNeighbors(board,9,9,0,2), where board is the board given in the driver. Your board has dimensions 9x9, so those are the m and n we pass, and for our example we're investigating the square at 0,2, which is the first entry in the third row (which has a 1 to its right). Great, let's begin.
i=0, so x = Math.max(i - 1, 0) = Math.max(-1, 0) = 0 (this shows the reason for the max function: if we just said int x=i-1, we would end up with x = -1 which is out of the bounds of the array. Next we evaluate x <= Math.min(i + 1, m - 1) = Math.min(1, 8) = 1. If we were investigating a cell in the final column, this condition would have enforced the right edge of the array.
I'll leave the similar logic involving y and j to you.
The loop simplifies to:
for (int x = 0; x <= 1; x++) {
for (int y = 1; y <= 3; y++) {
lives += board[x][y] & 1;
}
}
The inner loop will run six times, with the following (x,y) pairs: (0,1),(0,2),(0,3),(1,1),(1,2),(1,3). Convince yourself that these are the neighbors of the square we're investigating, as well as the square itself.
Five of these six squares will return 0, with the one at (1,2) returning 1, so at the end of this loop, lives will equal 1. The final thing to do is lives -= board[i][j] & 1;, which reduces lives by 1 if the square we're investigating has a 1 in it. In our case it doesn't (board[i][j] = 0) so we subtract 0, leaving us with 1, which we return. liveNeighbors(board,9,9,0,2) = 1
I may have gotten x and y backwards once or twice, but hopefully that's enough so you can understand what's going on.

How to implement deleteValues (int values) method for a custom ArrayList?

I am implementing my custom ArrayList class for integers with the help of an array, and I would like to be able to delete a certain value from my array. My problem is when there are many same delete-able value next to each other, I am getting two 0s next to each other which leads to a bug. i tried to solve it for a couple of hours without luck. Here is my code:
int max=10;
public int[] a = new int[max];
#Override
public void deleteValues(int value) {
int tempIndex=0;
for (int i = 0; i <50 ; i++) {
if (a[tempIndex] == value) {
a[tempIndex] = a[tempIndex + 1];
a[tempIndex + 1] = 0;
} else if (a[tempIndex] == 0) {
a[tempIndex] = a[tempIndex + 1];
a[tempIndex + 1] = 0;
} else {
tempIndex++;
}
}
}
My array looks like that before deleting the value (4):
[4, 2, 3, 4, 4, 4, 4, 1, 2, 3]
This is the wrong result after running the code:
[2, 3, 0, 0, 4, 4, 4, 1, 2, 3]
What I would like to achieve:[2, 3, 1, 2, 3, 0, 0, 0, 0, 0]
My question is: What would be the best approach to make the code work, using as few loop as possible?
One of the problems in your code is that you're always copying the element at index tempIndex+1 into tempIndex: it's always the next element.
In fact, after deleting let's say 5 elements from the array, you'll have to copy tempIndex+5 into tempIndex.
I think this is a good way of doing it:
public void deleteValues(int[] a, int value) {
int j=0;
for(int i=0; i<a.length; i++) {
if(a[i]!=value) {
a[j] = a[i];
j++;
}
}
// fill the rest of the array with zeros
while(j<a.length) {
a[j] = 0;
j++;
}
}
Basically, you keep two indices: i and j.
The index i follows the "original" array, while index j follows the "new" array (after deletion).
Index i loops over all the elements: if a[i] is not equal to value, copy it into its new position j and increment both j and i. If a[i] is equal to value, skip it and increment i without incrementing j.
After all the elements have been copied or skipped, fill the end of the array with zeros.
Sample input:
a = {4, 2, 3, 4, 4, 4, 4, 1, 2, 3}
value = 4
Output:
a = {2, 3, 1, 2, 3, 0, 0, 0, 0, 0}
public static void deleteValues(int[] a, int value) {
int newSize = a.length;
int current = 0;
for (int i = 0; i < a.length; i++) {
if (a[i] != value) {
if (i != current) {
a[current] = a[i];
newSize--;
}
current++;
}
}
//use first newSize values, for example you can copy to new array
System.out.println("New size = " + newSize);
}
you can use iterator:
List<Integer> numbers = ....
Iterator<Integer> i = numbers.iterator();
while (i.hasNext()) {
Integer num = i.next();
// add here your custom code
i.remove();
}
int tempIndex,index;
for (index = 0, tempIndex = 0; index < valuesArray.length; index++) {
if (valuesArray[index] != valToDelete) {
valuesArray[tempIndex++]=valuesArray[index];
}
}
while(tempIndex<valuesArray.length){
valuesArray[tempIndex++]=0;
}

Divide and Conquer algorithm in java

I have to write an algorithm in Java that uses the
divide and conquer technique. Given an array V with n int elements
the algorithm should calculate the number of times that two consecutive
0's appear.
Example :If V = [3, 0, 0, 1, 0, 1, 3, 2, 0, 0, 0, 1, 2], the algorithm should return 3,
Note that 0, 0, 0 corresponds to having 2 pairs of consecutive zeros.
I have written the program as below but when I run it it gives me an ArrayIndexOutOfBoundsException.
What am I doing wrong ?
public class Test {
public static void main(String[] args){
int[] v = {3, 0, 0, 1, 0, 1, 3, 2, 0, 0, 0, 1, 2};
System.out.println(Conta_Zeri_Main(v));
}
public static int Conta_Zeri_Main(int[] v){
if (v.length == 0 || v.length == 1)
return 0;
else
return Conta_Zeri(v, 1, v.length);
}
public static int Conta_Zeri(int[] v, int i, int f){
int m,result,sx,dx;
if (i >= f)
return 0;
else{
m = (i + f)/2;
sx = Conta_Zeri(v, i, m);
dx = Conta_Zeri(v, m+1, f);
result = sx + dx;
if ((v[m] == v[m+1]) && (v[m] == 0))
result++;
return result;
}
}
}
Apart from the anomalies already pointed out,
In your code you do not check if v[m] = v[m+1] = 0. This will miss out some possibilities when the array is partitioned between 2 consecutive zeroes.
Change your if statement to:
if ( (m < v.length - 1 ) && (v[m] == v[m+1]) && (v[m] == 0) )

Categories