here I have an array with a specific length and also a specific number of flags which have to be set. The length and number of flags can change from case to case, so they should be generic.
Example:
var array = new bool[] { false, false, false, false, false, false };
var numberOfFlags = 2;
I'd now like to get all permutations / combinations which are possible, when always 2 flags have to be set. Example:
1 1 0 0 0 0
0 1 1 0 0 0
0 0 1 1 0 0
But also for example:
0 1 0 0 0 1
Or:
0 0 0 1 0 1
I simply need a way to get all possible combinations where the predefined number of flags are set. No pattern or anything, just all possible combinations. Preferrably in C#.
I'm really looking forward to an answer and thanks a lot!
I found this on rosettacode.org. (I changed it a little bit). It's non-recursive. It just uses a Stack. It returns the same (modified) array every time, but that can be easily changed if needed.
public static IEnumerable<int[]> Combinations(int n, int k)
{
var result = new int[k];
var stack = new Stack<int>();
stack.Push(0);
while (stack.Count > 0) {
int index = stack.Count - 1;
int value = stack.Pop();
while (value < n) {
result[index++] = value++;
stack.Push(value);
if (index == k) {
yield return result;
break;
}
}
}
}
Combinations(6, 2) will give:
[0,1], [0,2], [0,3], [0,4], [0,5], [1,2], [1,3], [1,4], [1,5], [2,3], [2,4], [2,5], [3,4], [3,5], [4,5]
Just for numberOfFlags = 2 this is a simple sollution:
static void Main(string[] args)
{
var array = new bool[] { false, false, false, false, false, false };
var length = array.Length;
for (int i = 0; i < length; i++)
{
for (int j = i + 1; j < length; j++)
{
var arr = (bool[])array.Clone();
arr[i] = arr[j] = true;
arr.ToList().ForEach(s => Console.Write((s ? 1 : 0) + " "));
Console.WriteLine();
}
}
Console.Read();
}
Output:
1 1 0 0 0 0
1 0 1 0 0 0
1 0 0 1 0 0
1 0 0 0 1 0
1 0 0 0 0 1
0 1 1 0 0 0
0 1 0 1 0 0
0 1 0 0 1 0
0 1 0 0 0 1
0 0 1 1 0 0
0 0 1 0 1 0
0 0 1 0 0 1
0 0 0 1 1 0
0 0 0 1 0 1
0 0 0 0 1 1
The number of combinations can be calculed with:
P=(n!)/(a!·b!)
Where n is the lenght of the array, a is numberOfFlags and b is n - a.
This is a method of achieving what you want:
bool[] array = new bool[] { false, false, false,false};
int numberOfFlags = 1;
int n, a, b,_n,_a,_b;
n = array.Length;
_n = n;
a = numberOfFlags;
_a = a;
b = n - a;
_b = b;
//Calculate n!
for (int i = _n - 1; i >= 1; i--)
n = n * i;
//Calculate a!
for (int i = _a - 1; i >= 1; i--)
a = a * i;
//Calculate a!
for (int i = _b - 1; i >= 1; i--)
b = b * i;
int NumberOfPermutations = n / (a * b);
------EDIT------
This code works only for an array with only 2 possible values. Imagine that we have 3 possible values, then:
n = lenght of the array
a = repetitions of the first value
b = repetitions of the second value
c = n - (a+b) = repetitions of the third value
The number of permutations could be calculed with
P=(n!)/(a!·b!·c! ...)
In the code you should add only some variables, some loops...et voilà
I have two bool[5,5] arrays which look like this:
1st:
1 1 1 1 1
0 1 0 0 0
0 0 1 1 0
0 0 0 0 0
0 1 0 1 0
2nd:
0 0 0 0 1
0 1 1 1 0
0 0 0 0 0
0 0 1 1 0
1 0 0 0 0
What I have to do is simple calculating distance between 1 from 1st array and 1 from the 2nd one. I had multiple tries to solve this problem, but I can't solve this.
The result should looks like this:
4+3+2+1+0
0+0+0+0+0
0+0+0+0+0
0+0+0+0+0
0+1+0+3+0
Let me name arrays: first[,] and second[,]
There are fiew conditions:
if (first[i,j] == true && second[i,j] == true) distance[i,j] = 0
if (first[i,j] == false) distance[i,j] = 0
if (first[i,j] == true) then I have to calculate distance between closest 1 from second[,] eg. There are 1 in first[1,4] and first[3,4] and there is 1 in second[0,4] (there was mistake), so it means that distance[3,4] = 3 - 0 (because of second array's dimensions).
This is main method to calculate:
` static public int findPicture()
{
int[,] m = new int[testBitmap.GetLength(0),
testBitmap.GetLength(1)];
foreach (var picture in pictures)
{
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
if (testBitmap[i,j] == true)
{
do
{
i = i + 1;
} while (picture.Value[i,j] != true);
m[i,j] += 1;
}
}
}
var total = 0;
for (int a = 0; a < 5; a++)
{
for (int b = 0; b < 5; b++)
{
total += m[a, b];
}
}
return total;
}
return -1;
}`
It was my closest version to solve.
I would be very greatful if you could give some advices to solve this trivial problem.
I'd do something like this:
static int[,] BuildDistanceArray(bool[,] array1, bool[,] array2)
{
if (array1.GetLength(0) != array2.GetLength(0) || array1.GetLength(1) != array2.GetLength(1))
throw new Exception("Array sizes must match.");
int[,] distance = new int[array1.GetLength(0), array1.GetLength(1)];
for (int i = 0; i < array1.GetLength(0); ++i)
{
for (int j = 0; j < array1.GetLength(1); ++j)
{
distance[i, j] = array1[i, j] ? GetDistance(array2, i, j) : 0;
}
}
return distance;
}
static int GetDistance(bool[,] array, int row, int column)
{
int maxColumn = array.GetLength(1);
int distance = 0;
bool again;
do
{
again = false;
if (column - distance >= 0)
{
if (array[row, column - distance])
return distance;
again = true;
}
if (column + distance < maxColumn)
{
if (array[row, column + distance])
return distance;
again = true;
}
distance++;
} while (again);
return 0;
}
It gives the results you're looking for and it works for any size array.
This function calculates distance between 2 rows converted to int32. It's written in java, so some minor transformation will be required.
int distance(int x, int y) {
int count = Integer.bitCount(x);
int totalDist = 0;
for (int offset = 0; offset < 5 && x != 0; offset++) {
x = x ^ (x & (y << offset) & 0b11111);
x = x ^ (x & (y >>> offset));
int nextCount = Integer.bitCount(x);
totalDist += (count - nextCount) * offset;
count = nextCount;
}
return totalDist;
}
I need to find an efficient algorithm that does this:
byte[,] initialArray
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 5 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 5 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
To this:
byte[,] resultArray
0 0 0 1 2 1 0 0 0 0
0 0 1 2 3 2 1 0 0 0
0 1 2 3 4 3 2 1 0 0
1 2 3 4 5 4 3 2 1 0
0 1 2 3 4 3 2 1 0 0
0 1 2 2 3 2 1 0 0 0
1 2 3 2 2 1 0 0 0 0
2 3 4 3 2 1 0 0 0 0
3 4 5 4 3 2 1 0 0 0
2 3 4 3 2 1 0 0 0 0
What's happening
The initial array has two cells that are set to an initial value, the other cells are set to 0. The algorithm needs to "spread" that value to neighbor cells (no diagonals, just up/down/left/right). Each time the value spreads to a new cell, the value is decreased by 1 and spreads again, recursively. When the value reaches 0 it stops.
If the value is spreading to a cell with value > 0, the largest of the two values should be kept, instead of simply overwriting.
The example shows a 2D array but I'm actually working with a 3D array.
My attempt
I've managed to make a simple recursive algorithm in C#. It works but it must be terribly inefficient. It's way to slow on a large 3D array with 4 initial cells with value >= 10. There must be a much better way of doing this (for those who are familiar, this is the method the Minecraft game uses to determine light intensity of each cell in the game. Minecraft level arrays are massive and can contain many light sources)
I'm looking for the most efficient way of doing this. Here is my C# implementation for 3D arrays:
main ... {
List<int[]> toCheck = new List<int[]>();
// This list will keep a record of the initial cells that have a value > 0
// For loop over each cell to find those with initial value > 0
for (int x=0; x<worldX; x++){
for (int y=0; y<worldY; y++){
for (int z=0; z<worldZ; z++){
if (data[x,y,z].light > 0)
toCheck.Add (new int[] {x,y,z});
}
}
}
// For each cell w/ initial value > 0, spread the light
foreach (int[] i in toCheck)
SpreadLight(i[0],i[1],i[2],(byte)(data[i[0],i[1],i[2]].light - 1));
}
void SpreadLight(int x, int y, int z, byte light) {
try {
// Make sure this cells current value is smaller than the value we want to assign to it
if (data[x,y,z].light < light) {
data[x,y,z].light = (byte)light;
}
// If the value at this cell is > 0, get adjacent cells and spread the light to each of them
if (light > 0) {
int[][] adjBlocks = GetAdjacentBlocks(x,y,z);
for (int i = 0; i < 6; i++) {
SpreadLight(adjBlocks[i][0], adjBlocks[i][1], adjBlocks[i][2],(byte)(light-1));
}
}
}
catch { return; } // I'm not proud if this, it's the easiest way I found to avoid out of array bounds error
}
// This method simply returns an array with the 3D coordinates of each adjacent cell
int[][] GetAdjacentBlocks(int x, int y, int z) {
int[][] result = new int[6][];
// Top
result[0] = new int[] {x, y+1, z};
// North
result[1] = new int[] {x, y, z+1};
// East
result[2] = new int[] {x+1, y, z};
// South
result[3] = new int[] {x, y, z-1};
// West
result[4] = new int[] {x-1, y, z};
// Bottom
result[5] = new int[] {x, y-1, z};
return result;
}
Try this. In my experience 1D arrays work much faster than 2D arrays. Also implemented are several shortcuts for the calculations.
2D version
class Program
{
static void Main(string[] args)
{
Area A=new Area(10, 10);
A[3, 4]=5;
A[8, 2]=5;
Console.WriteLine(A);
//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 5 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 5 0 0 0 0 0 0 0
//0 0 0 0 0 0 0 0 0 0
bool spread1=A.CheckSpread();
Console.WriteLine();
Console.WriteLine("Spreading...");
A.Spread();
bool spread2=A.CheckSpread();
Console.WriteLine(A);
//0 0 0 1 2 1 0 0 0 0
//0 0 1 2 3 2 1 0 0 0
//0 1 2 3 4 3 2 1 0 0
//1 2 3 4 5 4 3 2 1 0
//0 1 2 3 4 3 2 1 0 0
//0 1 2 2 3 2 1 0 0 0
//1 2 3 2 2 1 0 0 0 0
//2 3 4 3 2 1 0 0 0 0
//3 4 5 4 3 2 1 0 0 0
//2 3 4 3 2 1 0 0 0 0
}
}
public struct Area
{
byte[] map;
int rows, columns;
public Area(int rows, int columns)
{
this.map=new byte[rows*columns];
this.columns=columns;
this.rows=rows;
}
public Area(Area other)
: this(other.rows, other.columns)
{
Array.Copy(other.map, this.map, other.map.Length);
}
public Area(byte[,] array)
{
this.rows=array.GetLength(0);
this.columns=array.GetLength(1);
this.map=new byte[rows*columns];
for (int i=0; i<rows; i++)
{
for (int j=0; j<columns; j++)
{
this.map[i*columns+j]=array[i, j];
}
}
}
public int Rows { get { return rows; } }
public int Columns { get { return columns; } }
public byte[] Map { get { return map; } }
public byte this[int index]
{
get { return map[index]; }
set { map[index]=value; }
}
public byte this[int row, int column]
{
get { return map[row*columns+column]; }
set { map[row*columns+column]=value; }
}
public byte[,] ToArray2()
{
byte[,] array=new byte[rows, columns];
for (int i=0; i<rows; i++)
{
for (int j=0; j<columns; j++)
{
array[i, j]=map[i*columns+j];
}
}
return array;
}
public void Spread()
{
bool changed;
do // CAUTION: This is not guaranteed to exit. Or is it?
{
changed=false;
for (int k=0; k<map.Length; k++)
{
byte x=map[k];
if (x<=1) continue; // cannot affect neighbors
int i=k/columns;
int j=k%columns;
int k_N=i>0?(i-1)*columns+j:-1;
int k_S=i<rows-1?(i+1)*columns+j:-1;
int k_E=j<columns-1?i*columns+j+1:-1;
int k_W=j>0?i*columns+j-1:-1;
if (k_N>=0&&map[k_N]+1<x) { map[k_N]=(byte)(x-1); changed=true; }
if (k_S>=0&&map[k_S]+1<x) { map[k_S]=(byte)(x-1); changed=true; }
if (k_E>=0&&map[k_E]+1<x) { map[k_E]=(byte)(x-1); changed=true; }
if (k_W>=0&&map[k_W]+1<x) { map[k_W]=(byte)(x-1); changed=true; }
}
} while (changed);
}
public bool CheckSpread()
{
for (int k=0; k<map.Length; k++)
{
byte x=map[k];
if (x<=1) continue; // cannot affect neighbors
int i=k/columns;
int j=k%columns;
int k_N=i>0?(i-1)*columns+j:-1;
int k_S=i<rows-1?(i+1)*columns+j:-1;
int k_E=j<columns-1?i*columns+j+1:-1;
int k_W=j>0?i*columns+j-1:-1;
if (k_N>=0&&map[k_N]+1<x) return false;
if (k_S>=0&&map[k_S]+1<x) return false;
if (k_E>=0&&map[k_E]+1<x) return false;
if (k_W>=0&&map[k_W]+1<x) return false;
}
return true;
}
public override string ToString()
{
string[] table=new string[rows];
for (int i=0; i<rows; i++)
{
string[] row=new string[columns];
for (int j=0; j<columns; j++)
{
row[j]= string.Format("{0,-3}", map[i*columns+j]);
}
table[i]= string.Join(" ", row);
}
return string.Join(Environment.NewLine, table);
}
}
3D version
public struct Area3
{
byte[] map;
int rows, columns, pages;
public Area3(int rows, int columns, int pages)
{
this.map=new byte[rows*columns*pages];
this.columns=columns;
this.rows=rows;
this.pages=pages;
}
public Area3(Area3 other)
: this(other.rows, other.columns, other.pages)
{
Array.Copy(other.map, this.map, other.map.Length);
}
public Area3(byte[, ,] array)
{
this.rows=array.GetLength(0);
this.columns=array.GetLength(1);
this.pages=array.GetLength(2);
this.map=new byte[rows*columns*pages];
for (int i=0; i<rows; i++)
{
for (int j=0; j<columns; j++)
{
for (int l=0; l<pages; l++)
{
this.map[(l*rows+i)*columns+j]=array[i, j, l];
}
}
}
}
public int Rows { get { return rows; } }
public int Columns { get { return columns; } }
public int Pages { get { return pages; } }
public byte[] Map { get { return map; } }
public byte this[int index]
{
get { return map[index]; }
set { map[index]=value; }
}
public byte this[int row, int column, int page]
{
get { return map[(page*rows+row)*columns+column]; }
set { map[(page*rows+row)*columns+column]=value; }
}
public byte[, ,] ToArray3()
{
byte[, ,] array=new byte[rows, columns, pages];
for (int i=0; i<rows; i++)
{
for (int j=0; j<columns; j++)
{
for (int l=0; l<pages; l++)
{
array[i, j, l]=map[(l*rows+i)*columns+j];
}
}
}
return array;
}
public void Spread()
{
bool changed;
do
{
changed=false;
for (int k=0; k<map.Length; k++)
{
byte x=map[k];
if (x<=1) continue; // cannot affect neighbors
int l=k/(rows*columns);
int i=(k%(rows*columns))/columns;
int j=(k%(rows*columns))%columns;
int k_N=i>0?(l*rows+i-1)*columns+j:-1;
int k_S=i<rows-1?(l*rows+i+1)*columns+j:-1;
int k_E=j<columns-1?(l*rows+i)*columns+j+1:-1;
int k_W=j>0?(l*rows+i)*columns+j-1:-1;
int k_U=l<pages-1?((l+1)*rows+i)*columns+j:-1;
int k_D=l>0?((l-1)*rows+i)*columns+j:-1;
if (k_N>=0&&map[k_N]+1<x) { map[k_N]=(byte)(x-1); changed=true; }
if (k_S>=0&&map[k_S]+1<x) { map[k_S]=(byte)(x-1); changed=true; }
if (k_E>=0&&map[k_E]+1<x) { map[k_E]=(byte)(x-1); changed=true; }
if (k_W>=0&&map[k_W]+1<x) { map[k_W]=(byte)(x-1); changed=true; }
if (k_U>=0&&map[k_U]+1<x) { map[k_U]=(byte)(x-1); changed=true; }
if (k_D>=0&&map[k_D]+1<x) { map[k_D]=(byte)(x-1); changed=true; }
}
} while (changed);
}
}
No visualization coded for 3D.
The following implementation (2D) should be faster - it keeps object creation and unnecessary function calls to the minimum. Extending to 3D would be quite straightforward:
class Program
{
class ArrayPoint { public int x; public int y;}
private static byte[,] startArray =
{
{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,5,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,5,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0}
};
private static int rows = startArray.GetLength(0);
private static int cols = startArray.GetLength(1);
static void Main(string[] args)
{
Spread(startArray);
}
static void Spread(byte[,] array)
{
var points = GetStartPoints(array);
foreach (var point in points.ToList())
SpreadPoint(array, point.x, point.y);
Display(array);
}
static void SpreadPoint(byte[,] array, int x, int y)
{
for (var i = x-1; i < x+2; i++)
for (var j = y-1; j < y+2; j++)
if ( (i==x || j==y) && !(i==x && j==y) && (i >= 0 && i < rows && j >= 0 && j < cols)
&& array[i, j] + 1 < array[x, y])
{
array[i, j] = (byte)(array[x, y] - 1);
SpreadPoint(array, i, j);
}
}
static void Display(byte[,] array)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
Console.Write("{0} ",array[i,j]);
Console.WriteLine();
}
Console.WriteLine();
}
static IEnumerable<ArrayPoint> GetStartPoints(byte[,] array)
{
for (var i = 0; i < rows; i++)
for (var j = 0; j < cols; j++)
if (array[i, j] != 0)
yield return new ArrayPoint {x = i, y = j};
}
}
Output is:
0 0 0 1 2 1 0 0 0 0
0 0 1 2 3 2 1 0 0 0
0 1 2 3 4 3 2 1 0 0
1 2 3 4 5 4 3 2 1 0
0 1 2 3 4 3 2 1 0 0
0 1 2 2 3 2 1 0 0 0
1 2 3 2 2 1 0 0 0 0
2 3 4 3 2 1 0 0 0 0
3 4 5 4 3 2 1 0 0 0
2 3 4 3 2 1 0 0 0 0
My two cents: consider expanding the points at the same time along wavefronts. Individual wavefronts could thus be terminated when done earlier than others.
A simplified JavaScript example:
var s = new Array(81)
for (var i=0; i<81; i++){
s[i] = i == 40 ? 5 : 0
}
var max = 5, m = 9, n = 9
function expand(wavefront){
while (wavefront.val > 0) {
//Southwest
var tmpLoc = wavefront.loc--
for (var i=0; i<max - 1 - wavefront.val; i++){
s[tmpLoc] = wavefront.val
tmpLoc += n + 1
}
//Southeast...
//...
wavefront.val--
}
}
expand({loc: 49, val: 4})
s now looks like this:
[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,5,0,0,0,0
,0,1,2,3,0,0,0,0,0
,0,0,1,2,0,0,0,0,0
,0,0,0,1,0,0,0,0,0
,0,0,0,0,0,0,0,0,0]