Closed path in the two-dimensional array - c#

There is two-dimensional array of zeros and ones. Need algorithm (the implementation) that determines whether in this array closed path of ones, that surround the zeros
Example:
there EXISTS a closed path(center):
1 0 0 0 0
0 0 1 0 0
0 1 0 1 0
0 0 1 1 0
0 0 1 0 0
there is NO
0 0 0 0 1
0 1 0 1 0
0 0 1 0 0
0 0 1 0 1
0 1 0 1 0

You can look at Connected Components Labeling algorithms, e.g. in Wikipedia or google for them. These algorithms are used e.g. to separate foreground pixels from background pixels in a digital white/black image. To apply them to your specific problem, you can think of your matrix as a digital image where 0 means foreground and 1 means background (or vice versa according to your needs). The algorithm finds largest connected foreground regions (containing only 0) that are surrounded by the background (1's). So, if you found such a foreground region you know there is a cycle of 1's surrounding it. When the foreground region is at the boundary you can decide whether you consider it as surrounded or not.

It's homework so I'll just give a general sketch. Construct an undirected graph; each 1 is a node, adjacent 1s have an edge between them. Google for undirected graph cycle detection to find closed paths. Then you have to go back to the original matrix and make sure there's at least one 0 inside.

Another idea would be to flood-fill starting at each 0 bounded by 1s. If it doesn't reach an edge, it's surrounded.

Here is sample code i tried. test it through
Logic i tried is loop through all the rows except first and last row.
if you find 0 then check it neighbour to left,right,top and bottom if all the neighbours are 1 then closed.
private void Form1_Load(object sender, EventArgs e)
{
int[,] graph = new int[5, 5] {
{ 1, 0, 0, 0, 0 },
{ 0, 0, 1, 0, 0 },
{ 0, 1, 0, 1, 0 },
{ 0, 0, 1, 1, 0 },
{ 0, 0, 1, 0, 0 }
};
int[,] graph1 = new int[5, 5] {
{ 0, 0, 0, 0, 1 },
{ 0, 1, 0, 1, 0 },
{ 0, 0, 1, 0, 0 },
{ 0, 0, 1, 0, 0 },
{ 0, 1, 0, 1, 0 }
};
isClosed(graph1);
}
private bool isClosed(int[,] graph)
{
for (int i = 1; i < graph.GetUpperBound(0); i++)
{
for (int j = 1; j < graph.GetUpperBound(1); j++)
{
if (graph[i, j] == 0)
{
if (graph[i - 1, j] == 1 && graph[i + 1, j] == 1 && graph[i, j - 1] == 1 && graph[i, j + 1] == 1)
{
return true;
}
}
}
}
return false;
}

Related

C# locate value in a array and move it to right

My task is to find a element in the array that is the same as given value, and then take it to right while maintaining the order of other elements. An example (Test Case):
{1, 2, 0, 1, 0, 1, 0, 3, 0, 1} for value = 0 => {1, 2, 1, 1, 3, 1, 0, 0, 0, 0}
While my code could do that above example, what it could not do is a very specific case: if the element in array equals value and the next element also equals value it will not shift the element. Again a example:
{ 1, int.MinValue, int.MinValue, int.MaxValue, int.MinValue, -1, -3, -9, 1 }, value = int.MinValue
Expected result: { 1, int.MaxValue, -1, -3, -9, 1, int.MinValue, int.MinValue, int.MinValue }
Result with my code: { 1, int.MinValue ,int.MaxValue, -1, -3, -9, 1, int.MinValue, int.MinValue }
I thought shifting is the one solution, is it? I am having a lot of problems with it, I also tried Array.Copy but there were problems the result was always out of range.
How can I make it so that it will shifts/rotates correctly in all cases?
Code:
static void Main(string[] args)
{
int[] source = new int[] { 1, int.MinValue, int.MinValue, int.MaxValue, int.MinValue, -1, -3, -9, 1 };
int value = int.MinValue;
for (int i = 0; i < source.Length; i++)
{
if (source[i] == value)
{
LeftShiftArray(source, i);
}
}
for (int i = 0; i < source.Length; i++)
{
Console.WriteLine(source[i]);
}
}
public static void LeftShiftArray(int[] source, int i)
{
var temp1 = source[i];
for (var j = i; j < source.Length - 1; j++)
{
source[j] = source[j + 1];
}
source[source.Length - 1] = temp1;
}
Now this
I have a simple approach to solve this problem. Run a loop, You keep on counting the numbers which are not equal to your number. And keep assigning to arr[count]. Then increment the count. And then finally you will be left to assign all the remaining numbers with the given number.
static void MoveToEnd(int []arr, int n)
{
int count = 0;
    for (int i = 0; i < arr.Length; i++)
        if (arr[i] != n)
         arr[count++] = arr[i];
    while (count < arr.Length)
        arr[count++] = n;
}
Please note I have typed this answer from phone, so please avoid typing mistakes.
This is a classic off by one error. Think about it like this:
Let's say you are moving all 0s to the back (value = 0). When you find a zero at some position, let's say source[2], you turn your array from this:
1 1 0 0 1 1
source[2] ^
To this:
1 1 0 1 1 0
source[2] ^
Now that you've shifted the array, the next step in your code is to increase i by 1. That means the next comparison you make will be with source[3]. In the above array, that looks like this:
1 1 0 1 1 0
source[3] ^
Do you see the problem? Let me know if not and I can explain further.
PS. There are a couple of issues with the other code that was posted that will probably stop you from getting full points if you were to turn it in for an assignment :)

Read a matrix from a text file in c#

I need to read a text file that contains the matrix, instead of having it on the code like I have, but I tried and I can't figure it out.
I have the matrix on a text file like I have on the code, but without the comas
This is a dijkstra program that reads the matrix in order to find the shortest path, thank you
{
private static int MinimumDistance(int[] distance, bool[] shortestPathTreeSet, int verticesCount)
{
int min = int.MaxValue;
int minIndex = 0;
for (int v = 0; v < verticesCount; ++v)
{
if (shortestPathTreeSet[v] == false && distance[v] <= min)
{
min = distance[v];
minIndex = v;
}
}
return minIndex;
}
private static void Print(int[] distance, int verticesCount)
{
Console.WriteLine("Vertex Distance from source");
for (int i = 0; i < verticesCount; ++i)
Console.WriteLine("{0}\t {1}", i, distance[i]);
}
public static void DijkstraAlgo(int[,] graph, int source, int verticesCount)
{
int[] distance = new int[verticesCount];
bool[] shortestPathTreeSet = new bool[verticesCount];
for (int i = 0; i < verticesCount; ++i)
{
distance[i] = int.MaxValue;
shortestPathTreeSet[i] = false;
}
distance[source] = 0;
for (int count = 0; count < verticesCount - 1; ++count)
{
int u = MinimumDistance(distance, shortestPathTreeSet, verticesCount);
shortestPathTreeSet[u] = true;
for (int v = 0; v < verticesCount; ++v)
if (!shortestPathTreeSet[v] && Convert.ToBoolean(graph[u, v]) && distance[u] != int.MaxValue && distance[u] + graph[u, v] < distance[v])
distance[v] = distance[u] + graph[u, v];
}
Print(distance, verticesCount);
}
static void Main(string[] args)
{
int[,] graph = {
{ 0, 6, 0, 0, 0, 0, 0, 9, 0 },
{ 6, 0, 9, 0, 0, 0, 0, 11, 0 },
{ 0, 9, 0, 5, 0, 6, 0, 0, 2 },
{ 0, 0, 5, 0, 9, 16, 0, 0, 0 },
{ 0, 0, 0, 9, 0, 10, 0, 0, 0 },
{ 0, 0, 6, 0, 10, 0, 2, 0, 0 },
{ 0, 0, 0, 16, 0, 2, 0, 1, 6 },
{ 9, 11, 0, 0, 0, 0, 1, 0, 5 },
{ 0, 0, 2, 0, 0, 0, 6, 5, 0 }
};
DijkstraAlgo(graph, 0, 9);
}
}
}
and here is the text file matrix:
0 6 8 12 0 0 0 0 0 0
6 0 0 5 0 0 0 0 0 0
8 0 0 1 0 0 0 0 0 0
12 5 1 0 9 10 14 16 15 0
0 0 0 9 0 0 3 0 0 0
0 0 0 10 0 0 0 0 13 0
0 0 0 14 3 0 0 3 0 6
0 0 0 16 0 0 3 0 1 4
0 0 0 15 0 13 0 1 0 7
0 0 0 0 0 0 6 4 7 0
If i understand you correctly.
You are after a way to read a space deliminated ints from a file and convert it into a multidimensional (square) array of int. e.g int[,]
You could do something like this
Given
public static class Extensions
{
public static T[,] ToRectangularArray<T>(this IReadOnlyList<T[]> arrays)
{
var ret = new T[arrays.Count, arrays[0].Length];
for (var i = 0; i < arrays.Count; i++)
for (var j = 0; j < arrays[0].Length; j++)
ret[i, j] = arrays[i][j];
return ret;
}
}
Usage
var someArray = File.ReadAllLines("myAwesomeFile") // read from File
.Select(x => x.Split(' ').Select(int.Parse).ToArray()) // split line into array of int
.ToArray() // all to array
.ToRectangularArray(); // send to multidimensional array

Handdrawing image and saving it as an array?

Question: What program / file format should I use?
I want to create an image (handdrawn pixel by pixel) and have it exported to text file formated as a pseudo-array of integers like this:
16 8
0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 9 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 11 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 12 0 0 256 0
I want every number to represent unique color (not actually matter what color as long as drawing program (the simpler, the better - MS Paint would do) itself can read it and I can distinguish it from others). Ultimately I want the ability to quickly draw an image with external program and use such exported data within my code. Can someone point me to the right direction?
I tried to export image to .c with GIMP, but the results:
/* GIMP RGB C-Source image dump (Bez nazwy.c) */
static const struct {
guint width;
guint height;
guint bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */
guint8 pixel_data[64 * 64 * 2 + 1];
} gimp_image = {
64, 64, 2,
"\377\377\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"...
though close to the point, are not exactly what I expect.
And here I see other possible solution: draw simply bmp image and try to translate it to an array of ints in my actual code (C#). But I would like to avoid this unless there is some simple and quick way / handy library to do this.
Or maybe some of You know any online converter that can take .bmp and return an array of ints?
#include "ui_mainwindow.h"
#include <QString>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
void generate(Ui::MainWindow* ui)
{
if (ui->pic_label->pixmap() != 0)
{
int cap = 1024 * 4;
int ct = 32; //color tolerance
//int number_of_colors_third = 256 / color_tolerance;//=256/32=8
int *uncompressedcolortable = new int[256*256*256];
for (int k=0; k<256; k++){
for (int j=0; j<256; j++){
for (int i=0; i< 256; i++){
uncompressedcolortable[k*256*256+j*256+i] = k*1000000+j*1000+i;
}
}
}
int width = ui->pic_label->pixmap()->width();
int height = ui->pic_label->pixmap()->height();
// int tiles = width * height;
if ( (width > cap || height > cap) && !(ui->actionSurpass_sanity_check->isChecked())){
ui->label->setText("File is too big to generate map. Check menu option if you want to process it anyway.");
return;
}
QImage image = ui->pic_label->pixmap()->toImage();
ui->lcdRED->setPalette(Qt::red);
ui->lcdGREEN->setPalette(Qt::green);
ui->lcdBLUE->setPalette(Qt::blue);
ui->progressBar->setMaximum(height);
QColor pixel_color;
ofstream outfile ("C:/Users/Niewzruszony/Desktop/map.map");
outfile << width << " " << height << std::endl;
for (int j = 0; j < height; j++ )
{
outfile << std::endl;
for (int i = 0; i < width; i++)
{
pixel_color = image.pixelColor(i,j);
outfile << uncompressedcolortable[pixel_color.red()*256*256 + pixel_color.green()*256 + pixel_color.blue()];
if(i != width-1) outfile << "\t";
ui->lcdRED->display(QString::fromStdString(to_string( pixel_color.red())));
ui->lcdGREEN->display(QString::fromStdString(to_string( pixel_color.green())));
ui->lcdBLUE->display(QString::fromStdString(to_string( pixel_color.blue())));
}
ui->progressBar->setValue(j+1);
}
ui->lcdRED->setPalette(Qt::lightGray);
ui->lcdGREEN->setPalette(Qt::lightGray);
ui->lcdBLUE->setPalette(Qt::lightGray);
ui->lcdRED->display(QString::fromStdString("0"));
ui->lcdGREEN->display(QString::fromStdString("0"));
ui->lcdBLUE->display(QString::fromStdString("0"));
ui->label->setText("Generated RGB map.");
return;
}
ui->pic_label->setText("First please choose image to process!");
}
Done it wit Qt. Just thougth I will share the code.
Note I've done some quick cleanup while posting, to not to include unimportant stuff (at least not all).

Copying a smaller array into a larger one

I'm struggling to think of the most elegant/simple way of doing this. Perhaps I'm overthinking it a little.
Lets say I've got a 5x5 array of integers that 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
And another 2x2 array of integers that looks like this:
5 1
2 3
I want to pick a location in the 5x5 array, say [2][2], and place the values from the second array into the first, so it looks like this:
0 0 0 0 0
0 0 0 0 0
0 0 5 1 0
0 0 2 3 0
0 0 0 0 0
My initial thought was to use a for loop after determining the number of rows/columns in the array to be copied, but I can't seem to puzzle out a way in my head to do that this morning.
Any suggestions?
Edit:
Sorry, here's the way I'm doing it currently. Just wondering if there's a better way.
This is actually part of a unity thing I'm doing - "RoomDoors" is our smaller array, and "map" is the larger array it's being moved into. It's part of a random map generator that needs to know which "edges" of tiles in rooms have doors on them that can connect to other rooms. RoomDoors stores 4 booleans, one for each direction telling me if there's a door there.
roomDoors = previousRoom.GetComponent<RoomDataInterface> ().rooms; //2d array of room/door arrangement in new room
sizeCol = roomDoors.GetLength (0);
sizeRow = roomDoors.GetLength (1);
map [10, 10] = roomDoors [0, 0]; // top left of the room goes in the spot
for (int i = 0; i < sizeCol; i ++){
for (int j = 0; j < sizeRow; j ++) {
map [i + 10,j + 10] = roomDoors[i,j];
}
I think you can't do much better, just remove the unnecessary assignment:
roomDoors = previousRoom.GetComponent<RoomDataInterface> ().rooms;
sizeCol = roomDoors.GetLength (0);
sizeRow = roomDoors.GetLength (1);
for (int i = 0; i < sizeCol; i ++)
for (int j = 0; j < sizeRow; j ++)
map [i + 10, j + 10] = roomDoors[i, j];
The line
map [10, 10] = roomDoors [0, 0];
is redundant, as the same assignment will be performed by the first iteration of the loop. Removal of the line will result in a solution that is smaller and more efficient.

Rotate 2D Array by 45 degrees

How can I rotate a 2D rectangular array of integers that has odd number of rows by 45 degrees?
So something like
int[] myArray = new int[,]
{
{1, 0 ,1},
{0, 1 ,0},
{0, 0 ,0},
}
into
int[] rotatedArray = new int[,]
{
{0, 1 ,0},
{0, 1 ,1},
{0, 0 ,0},
}
for any dimension (3x3, 5x5, 7x7, etc.).
5x5
0 0 0 0 0
2 0 0 0 0
1 1 1 1 1
0 0 0 0 0
0 0 0 0 0
into
1 2 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
5x5
0 0 0 3 0
0 0 0 3 0
0 0 0 3 0
0 0 0 3 0
0 0 0 3 0
into
0 0 0 0 0
0 0 0 0 3
0 0 0 3 0
0 0 3 3 0
0 3 0 0 0
This is a code written by me and a friend that solves this:
public static class ArrayExtensions
{
public static Point RoundIndexToPoint(int index, int radius)
{
if (radius == 0)
return new Point(0, 0);
Point result = new Point(-radius, -radius);
while (index < 0) index += radius * 8;
index = index % (radius * 8);
int edgeLen = radius * 2;
if (index < edgeLen)
{
result.X += index;
}
else if ((index -= edgeLen) < edgeLen)
{
result.X = radius;
result.Y += index;
}
else if ((index -= edgeLen) < edgeLen)
{
result.X = radius - index;
result.Y = radius;
}
else if ((index -= edgeLen) < edgeLen)
{
result.Y = radius - index;
}
return result;
}
public static T[,] Rotate45<T>(this T[,] array)
{
int dim = Math.Max(array.GetLength(0), array.GetLength(0));
T[,] result = new T[dim, dim];
Point center = new Point((result.GetLength(0) - 1) / 2, (result.GetLength(1) - 1) / 2);
Point center2 = new Point((array.GetLength(0) - 1) / 2, (array.GetLength(1) - 1) / 2);
for (int r = 0; r <= (dim - 1) / 2; r++)
{
for (int i = 0; i <= r * 8; i++)
{
Point source = RoundIndexToPoint(i, r);
Point target = RoundIndexToPoint(i + r, r);
if (!(center2.X + source.X < 0 || center2.Y + source.Y < 0 || center2.X + source.X >= array.GetLength(0) || center2.Y + source.Y >= array.GetLength(1)))
result[center.X + target.X, center.Y + target.Y] = array[center2.X + source.X, center2.Y + source.Y];
}
}
return result;
}
}
You can try this library:
Math.NET Project for matrices operations... http://numerics.mathdotnet.com/
This code appears to be useful too:
http://www.drunkenhyena.com/cgi-bin/view_net_article.pl?chapter=2;article=28#Rotation
Don't forget the DirectX managed and unmanaged namespaces and classes. Lots
and lots of good stuff there to check.
For example:
Matrix..::.Rotate Method (Single, MatrixOrder)
I think we have these rules:
Imagine the matrix as a set of "frames or boxes without centers" within each other like "Russian dolls".
Elements at the center of a side (top/left/right/bottom) move towards the nearest corner clockwise.
Corners move towards the next center clockwise.
Elements that are not corners nor centers move to the next spot (clockwise) that is the same distance from a corner as they currently are.
I've started writing some code but I don't think it's trivial and I haven't had time to test.
You can see my solution for the matrix rotation in codesignal

Categories

Resources