Java- Mapping multi-dimensional arrays to single - java

I am posting this in relation to another open question i have, however I thought that this deserved it's own question.
Alternate question (for reference): Java Proxy Discovering Bot
Basically, I need to store a very large amount of data and have it accessible very quickly. This would work ideally in an unlimited memory situation:
boolean[][][][] sets = new boolean[256][256][256][256];
boolean get(byte[] a) {
return sets[a[0]][a[1]][a[2]][a[3]];
}
However, this uses around 16gb of ram which is too much for my application. I figure that if using bits instead of booleans (stores as 4 bytes in Java) it would cut the memory usage to around 512MB. However, I can't seem to wrap my head around how to access the bits correctly. For example if you mapped each address something like this: position = a * b * c * d then it would map to the same bit as d * c * b * a etc.
I found this thread covering how to convert 2D arrays into 1D arrays, but I can't seem to wrap my head around how to extend that to a 4D array. Can anyone explain this?
Map a 2D array onto a 1D array C
The solution for 2D -> 1D arrays:
int array[width * height];
int SetElement(int row, int col, int value)
{
array[width * row + col] = value;
}
I am just not sure of how to extend it to 4D -> 1D
int array[256 * 256 * 256 * 256];
int setElement(int a, int b, int c, int d, boolean value)
{
array[?????????] = value;
}

To answer about mapping 4D to 1D, if you visualize, say, a chess board, you can come up with the formula for 2D to 1D by thinking if every row has width elements, and I first go down row number of rows and then move over to col, then I'm at width * row + col. Now imagine a stack of height number of chess boards and carry out the same exercise to extend it to three dimensions. Four dimensions is harder because you can't really visualize it, but by then you can see the pattern.
This program shows the formula for four dimensions. I ran it for very small numbers for posting here, but you can play with the dimensions and see how it works.
class Dim
{
// dimensions
static int d1 = 2 ; // "rows"
static int d2 = 2; // "cols"
static int d3 = 3; // "height"
static int d4 = 2; // the fourth dimension!
public static void main(String[] args) {
for (int i=0; i<d1; i++) {
for (int j=0; j<d2; j++) {
for (int k=0; k<d3; k++) {
for (int m=0; m<d4; m++) {
int oneD = fourDtoOneD(i, j, k, m);
System.out.printf("(%d, %d, %d, %d) -> %d\n", i, j, k, m, oneD);
}
}
}
}
}
static int fourDtoOneD(int i, int j, int k, int m) {
return ((d2*d3*d4) * i) + ((d2*d3) * j) + (d2 * k) + m;
}
}
$ java Dim
(0, 0, 0, 0) -> 0
(0, 0, 0, 1) -> 1
(0, 0, 1, 0) -> 2
(0, 0, 1, 1) -> 3
(0, 0, 2, 0) -> 4
(0, 0, 2, 1) -> 5
(0, 1, 0, 0) -> 6
(0, 1, 0, 1) -> 7
(0, 1, 1, 0) -> 8
(0, 1, 1, 1) -> 9
(0, 1, 2, 0) -> 10
(0, 1, 2, 1) -> 11
(1, 0, 0, 0) -> 12
(1, 0, 0, 1) -> 13
(1, 0, 1, 0) -> 14
(1, 0, 1, 1) -> 15
(1, 0, 2, 0) -> 16
(1, 0, 2, 1) -> 17
(1, 1, 0, 0) -> 18
(1, 1, 0, 1) -> 19
(1, 1, 1, 0) -> 20
(1, 1, 1, 1) -> 21
(1, 1, 2, 0) -> 22
(1, 1, 2, 1) -> 23

Related

Reverse "staircase" with for loop in java graphics (JFrame)

I have the code below, which makes a staircase in java with a for loop:
for (int i = 0; i < 10; i++) {
g.drawRect(5, 5 + 10 * i, 10 + 10 * i, 10);
}
But I want the same thing, but backwards, upside down, and reversed, like the image below:
Any ideas on the best way to achieve this?
You can represent a staircase as a 2d array of 0 and 1 in some of its corner. Then you can iterate over this array and for each number print a filled or hollow square.
For example, a 2d array with a staircase in the lower right corner:
int m = 5;
int[][] staircase = IntStream.range(0, m)
.mapToObj(i -> IntStream.range(0, m)
//.map(j -> i >= j ? 1 : 0) // lower left
//.map(j -> i <= j ? 1 : 0) // upper right
//.map(j -> i + j < m ? 1 : 0) // upper left
.map(j -> i + j >= m - 1 ? 1 : 0) // lower right
.toArray())
.toArray(int[][]::new);
// output
Arrays.stream(staircase).map(Arrays::toString).forEach(System.out::println);
[0, 0, 0, 0, 1]
[0, 0, 0, 1, 1]
[0, 0, 1, 1, 1]
[0, 1, 1, 1, 1]
[1, 1, 1, 1, 1]
See also: Display squares of asterisks, filled and hollow, side by side

Best performance to search a number in a column of a 2d array without cloning the array

I am trying to search for a number in a particular column of a two dimensional array. I tried a few different approach and would like to use stream in Java 8. However, it doesn't seem to be the best performance. Wonder if someone can help?
boolean isInColumn(int col, int number) {
return IntStream.range(0, board.length)
.map(i -> board[i][col])
.filter(num -> num == number )
.findFirst()
.isPresent();
}
trying to search in a block as well. Any hints?
public boolean isInBlock(int row, int col, int number) {
int r = row - row % 3;
int c = col - col % 3;
for (int i = r; i < r + 3; i++) {
for (int j = c; j < c + 3; j++) {
if (board[i][j] == number)
return true;
}
}
return false;
}
the input data is the following array.
public static int[][] PUZZLE = {
{9,0,0,1,0,0,0,0,5},
{0,0,5,0,9,0,2,0,1},
{8,0,0,0,4,0,0,0,0},
{0,0,0,0,8,0,0,0,0},
{0,0,0,7,0,0,0,0,0},
{0,0,0,0,2,6,0,0,9},
{2,0,0,3,0,0,0,0,6},
{0,0,0,2,0,0,9,0,0},
{0,0,1,9,0,4,5,7,0},
};
This 'stream'-version seems a little bit optimzed, but I think searching for a hit in an array will always be faster the old fashioned way, see Java performance tutorial – How fast are the Java 8 streams?
boolean isInColumn(int col, int number) {
return IntStream.range(0, board.length)
.anyMatch(i -> (board[i][col] == number) );
}
I made a short attempt with a parallel stream, but the overhead made it far worse.
I think it would be different if the action wasn't a simple compare...
If it's only about speed for a Sudoku-solver/generator maybe you shouldn't loop at all but write the 9 conditions in one return statement
return board[0,col] == number || board[1,col] == number ...
Since this seems to be Sudoku what you could do is store the data redundantly. Don't only store the numbers in "normally" in a two dimensional array, but also have two-dimensional boolean arrays, where you store whether the row/column/block contains the number.
class Sudoku {
private final int[][] puzzle = new int[9][9];
private final boolean[][] rows = new boolean[9][9];
private final boolean[][] columns = new boolean[9][9];
private final boolean[][] blocks = new boolean[9][9];
public void setCell(int row, in column, int number) {
puzzle[row][column] = number;
rows[row][number - 1] = true;
columns[column][number - 1] = true;
blocks[calcBlockId(row, column)][number - 1] = true;
}
// returns a number (0 - 8) identifying a block
// 0 - 2 is first line, 3 - 5 second line, etc.
private int calcBlockId(int row, int column) {
// Left as an exercise to the reader
}
public boolean isInColumn(int col, int number) {
return columns[col][number - 1];
}
public boolean isInBlock(int row, int column, int number) {
return blocks[calcBlockId(row, column)][number - 1];
}
}
This code searches for an element in a 2d array and returns the coordinates of the first match, if such an element is present, or null otherwise:
public static int[] findElement(int[][] arr, int element) {
return IntStream
// iterate through the indexes
// of the rows of the array
.range(0, arr.length)
// for each row
.mapToObj(i -> {
// look for the element in this row
int j = IntStream
// iterate through the indexes
// of the elements of the row
.range(0, arr[i].length)
// filter a matching element
.filter(el -> arr[i][el] == element)
// take first match
.findFirst().orElse(-1);
// if element is present
if (j >= 0)
// return its coordinates
return new int[]{i, j};
else
// or null otherwise
return null;
})
// take first non-null coordinates, if they are present
.filter(Objects::nonNull).findFirst()
// or null otherwise
.orElse(null);
}
// test
public static void main(String[] args) {
int[][] puzzle = {
{9, 0, 0, 1, 0, 0, 0, 0, 5},
{0, 0, 5, 0, 9, 0, 2, 0, 1},
{8, 0, 0, 0, 4, 0, 0, 0, 0},
{0, 0, 0, 0, 8, 0, 0, 0, 0},
{0, 0, 0, 7, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 2, 6, 0, 0, 9},
{2, 0, 0, 3, 0, 0, 0, 0, 6},
{0, 0, 0, 2, 0, 0, 9, 0, 0},
{0, 0, 1, 9, 0, 4, 5, 7, 0}};
int[] coordinates = findElement(puzzle, 7);
System.out.println(Arrays.toString(coordinates)); // [4, 3]
}
See also:
• Difference between anyMatch and findAny in java 8
• First unique character in a string using LinkedHashMap

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) )

constraint satisfaction in java

I am having a problem programming the below problem in java it is a constraint satisfaction problem:
If I have constraints like this:
x1 + x2 > x3
x2 - x4 = 2
x1 + x4 < x5
Each of x1 to x5 are in the domain {0,1,2}
How do I program the different combinations such that I will have a set of tuples as: {(0,0,0), (0,0,1), (0,1,0),(0,1,1),(1,0,0), ......} for each constraint
that is constraint 1 for instant has domain of tuple such as {(0,0,0), (0,0,1), (0,1,0),(0,1,1),(1,0,0),(0,1,2),(2,0,1) ......}
I need the reply in any language but preferably java please.
You could perhaps do this through the use of some helper methods from the google commons collect library. It would look something like this:
I'm assuming that the tuples (0,0,0) etc are tuples of the input to the constraint, (x0, x1, x2) for constraint1, (x2, x4) for constraint2 etc.
So, for constraint1, first we fill a list with all possible combinations:
final List<int[]> allCombos = new ArrayList<int[]>();
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 3; k++) {
allCombos.add(new int[] {i, j, k});
}
}
}
for (final int[] i : allCombos) {
System.out.println(i[0] + ", " + i[1] + ", " + i[2]);
}
Next, we want to filter so we'll be left with the tuples that are allowed by constraint1:
final List<int[]> constraint1 = ImmutableList.copyOf(Iterables.filter(allCombos, new Predicate<int[]>() {
#Override
public boolean apply(#Nullable final int[] input) {
return input[0] + input[1] > input[2];
}
}));
for (final int[] i : constraint1) {
System.out.println(i[0] + ", " + i[1] + ", " + i[2]);
}
This might need a little explanation.
ImmutableList.copyOf is a method that creates a copy of a given list. To this method, we pass the result of Iterables.filter(), which takes a list (the input to be filtered), and a Predicate, which has an overridden method apply(), where you decide which element of the input list that are supposed to be part of the result list. Here, we basically just code the constraint itself, and the cases where the apply method returns true will be part of the filtered list. (I've chosen to represent the tuples as an array, you could use the filter-strategy with any tuple-representation..)
The result of the last printouts (the filtered list) will be:
0, 1, 0
0, 2, 0
0, 2, 1
1, 0, 0
1, 1, 0
1, 1, 1
1, 2, 0
1, 2, 1
1, 2, 2
2, 0, 0
2, 0, 1
2, 1, 0
2, 1, 1
2, 1, 2
2, 2, 0
2, 2, 1
2, 2, 2
I'll leave it up to you to do the same for the other constraints..

how to reduce 2d array

I have a 2d array, let's say like this :
2 0 8 9
3 0 -1 20
13 12 17 18
1 2 3 4
2 0 7 9
How to create an array reduced by let's say 2nd row and third column?
2 0 9
13 12 18
1 2 4
2 0 9
Removing rows and columns in arrays are expensive operations because you need to shift things, but these methods do what you want:
static int[][] removeRow(int[][] data, int r) {
int[][] ret = new int[data.length - 1][];
System.arraycopy(data, 0, ret, 0, r);
System.arraycopy(data, r+1, ret, r, data.length - r - 1);
return ret;
}
static int[][] removeColumn(int[][] data, int c) {
for (int r = 0; r < data.length; r++) {
int[] row = new int[data[r].length - 1];
System.arraycopy(data[r], 0, row, 0, c);
System.arraycopy(data[r], c+1, row, c, data[r].length - c - 1);
data[r] = row;
}
return data;
}
You may want to investigate other data structures that allow for cheaper removals, though, i.e. doubly-linked lists. See, for example, Dancing Links.
public class TestMe {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int array[][] = {{2,0, 8, 9,},
{3, 0, -1, 20},
{13, 12, 17, 18},
{1, 2, 3, 4,},
{2, 0, 7, 9}};
for(int i=0; i<array.length;i++){
if(i == 1 ){
continue;
}
for(int j=0; j<array[i].length;j++){
if(j==2){
continue;
}
System.out.print(array[i][j]+" ");
}
System.out.println("");
}
}
}

Categories