C# Check for neighbours - c#

I have a function to check neighbors of an array and if that element is equal with 1. X is for each neighbor found and v[l] is the position for each 0. I have a problem with this code each time gives me "Index was outside the bounds of the array" and i don't know what to do else.
public int modificari(int i,int j,int n,int m)
{
int x = 0;
v = new int[n];
l=0;
if (mat[i, j] == 1)
{
if (j++ < m)
{
if (mat[i, j++] == 1)
x++;
else
{
v[l] = i * n + j + 2;
l++;
}
}
if (j++ < m && i++ < n)
{
if (mat[i++, j++] == 1)
x++;
else
{
v[l] = (i + 1) * n + j + 2;
l++;
}
}
if (i++ < n)
{
if (mat[i++, j] == 1)
x++;
else
{
v[l] = (i + 1) * n + j + 1;
l++;
}
}
if (j-- >= 0 && i++ < n)
{
if (mat[i++, j--] == 1)
x++;
else
{
v[l] = (i + 1) * n + j;
l++;
}
}
if (j-- >= 0)
{
if (mat[i, j--] == 1)
x++;
else
{
v[l] = i * n + j;
l++;
}
}
if (j-- >= 0 && i-- >= 0)
{
if (mat[i--, j--] == 1)
x++;
else
{
v[l] = (i - 1) * n + j;
l++;
}
}
if (i-- >= 0)
{
if (mat[i--, j] == 1)
x++;
else
{
v[l] = (i - 1) * n + j + 1;
l++;
}
}
if (j < n && i-- >= 0)
{
if (mat[i--, j++] == 1)
x++;
else
{
v[l] = (i - 1) * n + j + 2;
l++;
}
}
if (x < 2 && x > 3)
return 1;
else
return random();
}
return x;
}

That is a total mess. It is very hard to follow, even for an experienced coder. Use of one letter variable names and inline ++ operators is usually discouraged for the sake of readability.
I've quickly tried to rewrite your function from my best guess of what you're trying to achieve. I'm hoping you can see a different way to approach the problem that suits you better.
NOTE: I did not test this code at all, it probably has compile errors.
public struct Point
{
public int X;
public int Y;
public Point( int x, int y )
{
X = x;
Y = y;
}
}
public class Whatever
{
// ...
// Here is a list of the positions of all the neighbours whose values are
// zero.
List<Point> zeroPositions = new List<Point>();
// ...
public int Modificari(int pointX, int pointY)
{
// Determine dimensions of array.
int height = mat.GetLength(0);
int width = mat.GetLength(1);
// Find the minimum and maximum positions bounded by array size. (So we
// don't try to look at cell (-1, -1) when considering the neighbours of
// cell (0, 0) for instance.
int left = Math.Max( pointX - 1, 0 );
int right = Math.Min( pointX + 1, width );
int top = Math.Max( pointY - 1, 0 );
int bottom = Math.Min( pointY + 1, height );
// This is the number of neighbours whose value is 1.
int oneCount = 0;
zeroPositions.Clear();
for( int y = top; y <= bottom; y++ )
{
for( int x = left; x <= right; x++ )
{
if( mat[x, y] == 1 )
{
oneCount++;
}
else if( mat[x, y] == 0 )
{
zeroPositions.Add( new Point( x, y ) );
}
}
}
return oneCount;
}
//...
}
Also I'd really advise you to try not to do too many things in a function. Try making a different function for getting positions of ones and for returning the number of zeros.

Related

Binary Insertion Sort using recursion - working for one array and not another?

Doing a Binary Insertion Sort and my recursion is backfiring on me when I return my array. When I use the array : { 3, 1, 2, 4 } I get back 1,2,3,4.
When I use the array : { 3, 7, 2, 4 } the recursion causes a StackOverflow.
Where am I going wrong?
p.s Sorry about the console.writelines in my code it helps me check whats going on as I develop
The C# code is per the following snippet:
int[] a = new int[] { 3, 1, 2, 4 }; //Array to be sorted
int MiddlePointer = 0;
int LeftPointer = 0;
int RightPointer = 0;
int i = 1; //First number is 'sorted' so focus on second number
BinaryInsertSort(a, MiddlePointer, LeftPointer, RightPointer, i);
void BinaryInsertSort(int[] a, int MiddlePointer, int LeftPointer, int RightPointer, int i)
{
if (i == a.Length) //This should EXIT the algorithm once all of the numbers are sorted
{
return;
}
if (MiddlePointer == 0 & LeftPointer == 0 & RightPointer == 0) //If this is the first iteration, only the first number is 'sorted' and all of the pointers are the same
{
if (a[i] > a[MiddlePointer]) //If the next number is higher then just raise the RightPointer
{
RightPointer = i;
}
else //If the next number is lower, the 'sorted' values need to be 'shifted' one place to the right
{
RightPointer = i;
int temp = a[i];
for (int j = RightPointer; j > LeftPointer; j--)
{
a[j] = a[j - 1];
}
a[LeftPointer] = temp;
}
// i++; //At this point one number has been sorted
}
else
{
a = Testing(a, MiddlePointer, LeftPointer, RightPointer, i);
}
foreach (int x in a)
{
Console.WriteLine(x);
}
Console.ReadLine();
i++;
BinaryInsertSort(a, MiddlePointer, LeftPointer, RightPointer, i);
}
int[] Testing(int[] a, int MiddlePointer, int LeftPointer, int RightPointer,int i) //This method should find the space where the number should be inserted and return the updated array
{
if(MiddlePointer == RightPointer & RightPointer == LeftPointer)
{
Console.WriteLine($"{a[i]} has not been found");
if (a[i] > a[MiddlePointer])
{
RightPointer = i;
}
else
{
RightPointer = i;
int temp = a[i];
for (int j = RightPointer; j > 0; j--)//move up values
{
a[j] = a[j - 1];
}
a[LeftPointer] = temp;
}
}
else if (a[i] > a[MiddlePointer])
{
Console.WriteLine($"{a[i]} is greater than {a[MiddlePointer]}");
LeftPointer = MiddlePointer + 1;
MiddlePointer = (LeftPointer + RightPointer) / 2;
Testing(a, MiddlePointer, LeftPointer, RightPointer, i);
}
else if (a[i] < a[MiddlePointer])
{
Console.WriteLine($"{a[i]} is less than {a[MiddlePointer]}");
RightPointer = MiddlePointer - 1;
MiddlePointer = (LeftPointer + RightPointer) / 2;
Testing(a, MiddlePointer, LeftPointer, RightPointer, i);
}
return a;
}
Basically I went back to scratch and did a binary search first. This really helped in my previous attempt so I really made sure this worked before moving onto binary insertion sort. From this point I modified the code bit by bit and tried loads of different data sets to see if anything changed. Using breakpoints really helped. I needed to go through and 'follow' the changing variables to see where errors were being made. I also used Console.ReadLine and Console.WriteLine to follow where my logic was ending up. There are many loops in this code and the biggest problem was when I was using the recursion. I was using the recursion to find the 'gap' were the number should be inserted, this was the moment all of the pointers were the same. These pointers needed to constantly be updated and changed at the right moments. This was the most challenging part of the sort.
int i = 1;
int MiddlePointer = 0;
int LeftPointer = 0;
int RightPointer = 0;
BinaryInsertionSort.SortList(UnsortedNumberList, MiddlePointer, LeftPointer, RightPointer, i);
public void SortList(int[] a, int MiddlePointer, int LeftPointer, int RightPointer, int i)
{
if (i == a.Length)
{
Console.Write("Sorted list: ");
for (int x = 0; x < a.Length; x++) //output sorted list
{
if (x == a.Length - 1)
{
Console.Write($"{a[x]}");
}
else
{
Console.Write($"{a[x]}, ");
}
}
return;
}
if (a[MiddlePointer] == a[i])
{
RightPointer = i;
int temp = a[i];
for (int j = i; j > MiddlePointer + 1; j--)
{
a[j] = a[j - 1];
}
a[MiddlePointer + 1] = temp;
LeftPointer = 0;
MiddlePointer = i / 2;
i++;
SortList(a, MiddlePointer, LeftPointer, RightPointer, i);
}
else if (MiddlePointer == RightPointer & RightPointer == LeftPointer)
{
if (a[i] > a[MiddlePointer])
{
RightPointer = i;
int temp = a[i];
for (int j = i; j > MiddlePointer + 1; j--)
{
a[j] = a[j - 1];
}
a[MiddlePointer + 1] = temp;
}
else //If the next number is lower, the 'sorted' values need to be 'shifted' one place to the right
{
RightPointer = i;
int temp = a[i];
for (int j = i; j > MiddlePointer; j--)
{
a[j] = a[j - 1];
}
a[MiddlePointer] = temp;
}
LeftPointer = 0;
MiddlePointer = i / 2;
i++;
SortList(a, MiddlePointer, LeftPointer, RightPointer, i);
}
else if (a[i] > a[MiddlePointer])
{
LeftPointer = MiddlePointer + 1;
if (LeftPointer > RightPointer)
{
LeftPointer = RightPointer;
}
MiddlePointer = (LeftPointer + RightPointer) / 2;
SortList(a, MiddlePointer, LeftPointer, RightPointer, i);
}
else if (a[i] < a[MiddlePointer])
{
RightPointer = MiddlePointer - 1;
if (RightPointer < 0)
{
RightPointer = 0;
}
MiddlePointer = (LeftPointer + RightPointer) / 2;
SortList(a, MiddlePointer, LeftPointer, RightPointer, i);
}
}
}
UnsortedNumberList is an array of numbers. At first the pointers point at the first number at Array position 0. When the pointers are equal to each other then the position where the number is inserted has been found. From this point evaluate if the next number is higher or lower that this optimum position. Numbers will have to be juggled about hence the for loops with int j and variable temp. I hope this helps anyone else doing merge sort in the future.

C# Dynamic programming conversion

Hi I have a task to convert exponential code into linear, but I have no idea how to do it. Could you give me any tips or point me in the right direction?
Here's the code:
int F (int m, int n)
{
if(n == 0)
{
return m;
}
else if(m == 0 && n > 0)
{
return n;
}
else
{
int[] array = { 1 + F(m - 1, n), 1 + F(m, n - 1), D(m, n) + F(m - 1, n - 1) };
return array.Min();
}
}
int D(int i, int f)
{
if(x[i] == y[f])
{
return 1;
}
else
{
return 0;
}
}
Update:
Am I going in the right direction? So far it works only with m=0,1,2 and n=0,1,2. How do I fill all the values if let's say, I give m = 10 and n = 20?
int Fdp(int m, int n)
{
fdin[m, 0] = m;
for(int i = 0; i <= n; i++)
{
fdin[0, i] = n;
}
if (n == 0)
{
return m;
}
else if (m == 0 && n > 0)
{
return n;
}
else
{
int[] temp = { 1 + fdin[m-1, n], 1+ fdin[m,n-1], D(m,n) + fdin[m-1,n-1] };
fdin[m, n] = temp.Min();
return temp.Min();
}
}
Solved it.
static int Fdp(int m, int n)
{
for (int i = 0; i <= m; i++)
{
fdin[i, 0] = i;
for (int j = 1; j <= n; j++)
{
if(i == 0)
{
fdin[i, j] = j;
}
else
{
int[] temp = new int[] { 1 + fdin[i - 1, j], 1 + fdin[i, j - 1], D(i, j) + fdin[i - 1, j - 1] };
fdin[i, j] = temp.Min();
}
}
}
return fdin[m,n];
}

prim's algorithm generated maze missing walls

So I'm implementing a maze generator using prim's algorithm.
the maze itself generates pretty much fine, however two (touching) walls would always be missing.
the mazes I'm generating (the right and bottom walls are missing):
Maze 1
here the left and top walls are missing:
Maze 2
The code I use to generate the maze:
int _height = 50;
int _width = 50;
private bool[,] maze = new bool[_height, _width];
private void generateMaze()
{
//_height = 50
//_width = 50
List<MazeCell> walls = new List<MazeCell>();
int randX = genRand(1, _height-1);
int randY = genRand(1, _width-1);
maze[randX, randY] = true;
MazeCell start = new MazeCell(randX, randY, null);
for (int i = -1; i <= 1; i++)
{
for(int j = -1; j <= 1; j++)
{
if ((i == 0 && j == 0) || (i != 0 && j != 0))
continue;
try
{
if (maze[randX + i, randY + j])
continue;
}
catch(Exception e)
{
continue;
}
walls.Add(new MazeCell(randX + i, randY + j, start));
}
}
while (walls.Count > 0)
{
int index = genRand(0, walls.Count - 1);
MazeCell cur = walls[index];
MazeCell op = cur.opposite();
walls.RemoveAt(index);
try
{
if(!maze[cur.x, cur.y])
{
if(!maze[op.x, op.y])
{
maze[cur.x, cur.y] = true;
maze[op.x, op.y] = true;
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
if (i == 0 && j == 0 || i != 0 && j != 0)
continue;
try
{
if (maze[op.x + i, op.y + j])
continue;
}
catch (Exception e)
{
continue;
}
walls.Add(new MazeCell(op.x + i, op.y + j, op));
}
}
}
}
}
catch (Exception e) { }
}
}
private int genRand(int min, int max)
{
Random rnd = new Random();
return rnd.Next(min, max);
}
And the mazeCell class:
public class MazeCell
{
public int x;
public int y;
public bool passage = false;
MazeCell parent;
public MazeCell(int x, int y, MazeCell parent)
{
this.x = x;
this.y = y;
this.parent = parent;
}
public MazeCell opposite()
{
if (x.CompareTo(parent.x) != 0)
return new MazeCell(x + x.CompareTo(parent.x), y, this);
if (y.CompareTo(parent.y) != 0)
return new MazeCell(x, y + y.CompareTo(parent.y), this);
return null;
}
}
the code is an adaptation of java code I found here: http://jonathanzong.com/blog/2012/11/06/maze-generation-with-prims-algorithm
I can't find where it suddenly decides to remove walls.
Any help is greatly appreciated!
I tried your code and if you move the new Random outside the method to a member variable (so it's created just once), then it seems to work just fine.
There is no code to ensure that there is a boundary around the edge of the whole maze: the maze will happily wander right up to any edge. What you are seeing is an artifact of non-randomness caused by resetting Random every time.
If set Random to the same seed over and over in that method I see long runs down two sides also.
Here's sample output for 15x15 with proper random values:
XXXXXXXXX X X X
X X X X
X X XXXXXXXXXXX
X X X X X
XXXXXXXXX X X X
X X X X
X XXX XXXXXXX X
X X X X
XXXXX X X XXX X
X X X
XXXXXXX X XXXXX
X X X X X X
X XXX XXXXXXX X
X X X X
XXX X X XXXXXXX
I would suggest to tackle this more from a graph-based perspective and not from some specific representation of a "maze".
See also my answer to this question.

Word search generator

I'm writing a Word search puzzle in c# and I'm almost done, only missing one thing.
I have a char[,] matrix that I fill up with words I read from a txt file, and if there's no available places for a word left, I fill up the remaining spots with random letters. My problem is that I don't know how to make words that contains the some letter cross eachother. Here's my code for the word placing:
private bool PlaceWord(string word, int _row, int _col, int x, int y)
{
if(x > 0)
{
if (_row + word.Length > row)
return false;
}
if(x < 0)
{
if (_row - word.Length < 0)
return false;
}
if(y > 0)
{
if (_col + word.Length > col)
return false;
}
if(y < 0)
{
if (_col - word.Length < 0)
return false;
}
for(int i = 0; i < word.Length; i++)
{
if (matrix[(i * x) + _row, (i * y) + _col] != ' ')
return false;
}
for (int i = 0; i < word.Length; i++)
{
matrix[(i * x) + _row, (i * y) + _col] = word[i];
answers[(i * x) + _row, (i * y) + _col] = word[i];
}
return true;
}
In your first for-loop
if ((matrix[i*x+_row, i*y+_col] != ' ') && (matrix[i*x+_row, i*y+_col] != word[i]))
return false

How to process an array correctly

Here's the part 1 of my question, if you wanna check the background of this question :
Detecting brackets in input string
Forgive me if the title doesn't match, since I also confused how to name it appropriately to picture my problem. If anyone knows a more appropriate title, feel free to edit.
So, given below code (my own code) :
private const int PARTICLE_EACH_CHAR = 4;
/*ProcessBarLines : string s only contains numbers, b, [, and ]*/
private int ProcessBarLines(Canvas canvas, string s, int lastLineAboveNotation)
{
List<int> bracket = new List<int>();
List<int> other = new List<int>();
int currentCloseNumber = 0;
int currentOpenNumber = 0;
for (int i = 0; i < s.Length; i++)
{
if (s[i] == '[')
{
bracket.Add(i);
currentOpenNumber++;
if (i - 1 > 0 && s[i - 1] != '[')
{
currentOpenNumber = 1;
}
}
else if (s[i] == ']')
{
bracket.Add(i);
currentCloseNumber++;
if (i + 1 >= s.Length || s[i + 1] != ']' || currentOpenNumber == currentCloseNumber)
{
int min = bracket.Count - (currentCloseNumber * 2);
int max = bracket[bracket.Count - 1];
List<int> proc = new List<int>();
int firstIndex = -1;
int lastIndex = -1;
for (int ii = 0; ii < other.Count; ii++)
{
if (other[ii] > min && other[ii] < max)
{
proc.Add(other[ii]);
if (firstIndex == -1)
{
firstIndex = ii;
lastIndex = ii;
}
else
{
lastIndex = ii;
}
}
}
double leftPixel = firstIndex * widthEachChar;
double rightPixel = (lastIndex * widthEachChar) + widthEachChar;
DrawLine(canvas, currentCloseNumber, leftPixel,
rightPixel, lastLineAboveNotation * heightEachChar / PARTICLE_EACH_CHAR);
lastLineAboveNotation += currentCloseNumber - 1;
currentOpenNumber -= currentCloseNumber;
currentCloseNumber = 0;
}
}
else
{
other.Add(i);
}
}
return lastLineAboveNotation + 1;
}
Here's the test cases :
Picture 1 & 2 is the correct answer, and picture 3 is the wrong answer. Picture 3 should have a line, just like inverted from number 2, but, apparently, (if you look closely) the line is drawn on the right, but it should be on the left to be correct (above 0).
I figured, the problem is, I'm quite sure on the "min". Since it doesn't give the correct starting value.
Any idea on this? Feel free to clarify anything. It's used for writing numeric musical scores.
Btw, DrawLine() just meant to draw the line above the numbers, it's not the problem.
Finally! I found it!
private int ProcessBarLines(Canvas canvas, string s, int lastLineAboveNotation)
{
List<int> bracket = new List<int>();
List<int> other = new List<int>();
int currentCloseNumber = 0;
int currentOpenNumber = 0;
int space = 0;
for (int i = 0; i < s.Length; i++)
{
if (s[i] == '[')
{
bracket.Add(i);
currentOpenNumber++;
if (i - 1 > 0 && s[i - 1] != '[')
{
currentOpenNumber = 1;
}
}
else if (s[i] == ']')
{
bracket.Add(i);
currentCloseNumber++;
if (i + 1 >= s.Length || s[i + 1] != ']' || currentOpenNumber == currentCloseNumber)
{
int min = bracket[Math.Max(bracket.Count - ((currentCloseNumber * 2) + space), 0)];
int max = bracket[bracket.Count - 1];
space = max - min - 1;
List<int> proc = new List<int>();
int firstIndex = -1;
int lastIndex = -1;
for (int ii = 0; ii < other.Count; ii++)
{
if (other[ii] > min && other[ii] < max)
{
proc.Add(other[ii]);
other[ii] = -1;
if (firstIndex == -1)
{
firstIndex = ii;
lastIndex = ii;
}
else
{
lastIndex = ii;
}
}
}
double leftPixel = firstIndex * widthEachChar;
double rightPixel = (lastIndex * widthEachChar) + widthEachChar;
DrawLine(canvas, currentCloseNumber, leftPixel,
rightPixel, lastLineAboveNotation * heightEachChar / PARTICLE_EACH_CHAR);
lastLineAboveNotation += 1;
currentOpenNumber -= currentCloseNumber;
currentCloseNumber = 0;
}
}
else
{
other.Add(i);
}
}
return lastLineAboveNotation + 1;
}
If someone got a more efficient code, please let us know!

Categories

Resources