Variable values update before I give that instruction - c#

I apologize in advance for this way to long post.
I'm working on a C# function to unify a mesh's triangles'orientation for a Unity3D project. I use Vector3 type, which is a struct composed by a float array [3].
In order to do so I take a first triangle and check if it points outwark or inward. After that I check for an adiacent one and check the order of the indices of the triangle. If I find couple of indices in order, I flip them.
here an example:
base triangle' indices: 1 2 3
second triangle' indices:
1 2 4 (1 2 are in the same order as the base triangle, need to flip to 2 1 4)
4 2 1 (2 1 are not in the same order, then do nothing)
The check returns me the next triangle to check if it finds; otherwise it returns a null vector.
if "next" isn't null I make the "next" triangle to "current", I store the fixed triangle in a variable, in order to avoid the program to keep checking the same indices and re-iterate the check.
The problem is that some variable seem to update their values before the instruction messing up my conditions.
As you can see in the code below I have a really complex If statement that tries to find if two triangles'indices are present in the same order (not necessary the same position) like:
1 2 3 (base)
all the following possible result need to be flipped to
1 2 4 -> 2 1 4
4 1 2 -> 1 4 2
2 4 1 -> 4 2 1
that minus before mesh.Index[] is needed because it seems to use IndexList values, instead of mesh.Index ones and I don't know why.
I'm using this custom struct to test the program outside Unity
public struct SimplifiedMesh
{
//this stores the order of the vertices needed to
//create all the triangles of the mesh.
public int[] Index;
it list all the vertices of the mesh
public Vector3[] Vertex;
};
IndexList is used to store the checked triangles. At first all values are positive, but when it check one, it turns its indices negative.
int[] IndexList = new int[Unimesh.Index.Length]; IndexList = Unimesh.Index;
First I check with a different method in order to determine if the face is pointing outward or inward
FirstCheck(Unimesh, CentreofMesh, currentIndices);
//this will tell the program this triad is already checked
IndexList[currentIndices[0]] *= -1;
IndexList[currentIndices[0] + 1] *= -1;
IndexList[currentIndices[0] + 2] *= -1;
The following now is the tough part. Here a legend of variables:
currentIndices is an Array[3] storing the position of thr three indices of the last checked triangle in the mesh.Index array. It's used to find an adiacent one;
next is the return variable that return the next vector to be considered for the check or null if he has found no adiacent triangles.
mesh.Index[currentIndices[0-1-2] are the current indices
FlipNormals get the mesh indices, go to the three indices pointed by "Flipvector" and swap the first two, inverting their order
and here the code
static int[] AdiacentFace(SimplifiedMesh mesh, int[] IndexList, int[] currentIndices)
{
int[] next = new int[3];
for (int i = 0; i < IndexList.Length; i += 3)
{
if (IndexList[i] > 0 || IndexList[i + 1] > 0)
{
if
// e restituisce la nuova terna modificata
((IndexList[i] == -mesh.Index[currentIndices[0]] && (IndexList[i + 1] == -mesh.Index[currentIndices[1]] || IndexList[i + 2] == -mesh.Index[currentIndices[2]])) ||
(IndexList[i + 1] == -mesh.Index[currentIndices[0]] && (IndexList[i + 2] == -mesh.Index[currentIndices[1]] || IndexList[i] == -mesh.Index[currentIndices[2]])) ||
(IndexList[i + 2] == -mesh.Index[currentIndices[0]] && (IndexList[i] == -mesh.Index[currentIndices[1]] || IndexList[i + 1] == -mesh.Index[currentIndices[2]])))
{
int[] Flipvector = new int[3];
Flipvector[0] = mesh.Index[i];
Flipvector[1] = mesh.Index[i+1];
Flipvector[2] = mesh.Index[i + 2];
FlipNormals(mesh, Flipvector);
// Elimina la terna per i successivi controlli
IndexList[i] *= -1;
IndexList[i + 1] *= -1;
IndexList[i + 2] *= -1;
// Ritorna gli indici del nuovo vettore
next[0] = i;
next[1] = i + 1;
next[2] = i + 2;
return next;
}
else if
((IndexList[i] == -mesh.Index[currentIndices[0]] && (IndexList[i + 2] == -mesh.Index[currentIndices[1]] || IndexList[i + 1] == -mesh.Index[currentIndices[2]])) ||
(IndexList[i + 1] == -mesh.Index[currentIndices[0]] && (IndexList[i] == -mesh.Index[currentIndices[1]] || IndexList[i + 2] == -mesh.Index[currentIndices[2]])) ||
(IndexList[i + 2] == -mesh.Index[currentIndices[0]] && (IndexList[i + 1] == -mesh.Index[currentIndices[1]] || IndexList[i] == -mesh.Index[currentIndices[2]])))
{
// Elimina la terna per i successivi controlli
IndexList[i] *= -1;
IndexList[i + 1] *= -1;
IndexList[i + 2] *= -1;
// Ritorna gli indici del nuovo vettore
next[0] = i;
next[1] = i + 1;
next[2] = i + 2;
return next;
}
}
}
next = null;
return next;
}

I found the solution.
I'm a beginner with C#, and I didn't know the operation "IndexList = Unimesh.Index" between arrays pass the reference, instead of the single values.
I managed to solve the problem in this way.
From:
int[] IndexList = new int[Unimesh.Index.Length]; Indexlist = Unimesh.Index;
to:
int[] IndexList = new int[Unimesh.Index.Length];
For (int i = 0; i < Unimesh.Index.Length; i++)
{
IndexList[i] = Unimesh.Index[i];
}
This way I copy just the values and not the reference to the array.

Related

System out of range in for loop

System is giving me out of range exception when p = 255. My understanding is that with "OR" operator, later part of if statement should come into affect. However, it is not. Please advise on how to fix it.
for (int p = 0; p < 256; p++)
{
if (buffer[p] == buffer[p + 1] || buffer[p] == buffer[p - 1])
{
//Code
}
}
In the first iteration p = 0;
With p = 0; the right side of the conditional expression is trying to access buffer[-1], which throws the Exception.
You should start the iteration with index 1 and end it one item before the last item in the buffer. Try something like this:
for (int p = 1; p < buffer.Length - 1; p++)
{
if (buffer[p] == buffer[p + 1] || buffer[p] == buffer[p - 1])
{
//Code
}
}
You have out of range error. It means that index p is out of buffer range,
which is
// buffer has Length items, starting from 0
[0 .. buffer.Length - 1]
Now, let's have a look at index usage: you have
if (buffer[p] == buffer[p + 1] || buffer[p] == buffer[p - 1])
and you address
buffer[p] where p can be in 0..buffer.Length - 1 range
buffer[p + 1] where p can be in -1..buffer.Length - 2 range
buffer[p - 1] where p can be in 1..buffer.Length range
combining all 3 ranges for index p together we get p in 1..buffer.Length - 2 range or
for (int p = 1; p < buffer.Length - 1; p++)
if (buffer[p] == buffer[p + 1] || buffer[p] == buffer[p - 1]) {
...
}
Note edge cases (first and last buffer items):
when p == 1 we have
(buffer[1] == buffer[2] || buffer[1] == buffer[0])
^
first item
when p == buffer.Length - 2
(buffer[buffer.Length - 2] == buffer[buffer.Length - 1] || buffer[buffer.Length - 2] == buffer[buffer.Length - 3])
^
last item
that's why no item is lost
You're comparing an item x to either the item before it or the item after it. Then you move along one, and you potentially make the same compare you just did, so you're wasting a lot of CPU:
var a= new []{1,2,3,4}
if(2 == 1 or 2 == 3)
...
if(3 == 2 or 3 == 4). //3==2 was already done above like 2==3
Just compare current with next, moving along by 1 each time, stopping 1 short of the end of the loop
If you want to duplicate messaging, print twice
for(int x=0; x<array.Length-1; x++){
if(array[x] == array[x+1]){
Console.WriteLine($"index {x} is same as {x+1}");
Console.WriteLine($"index {x+1} is same as {x}");
}
}
My understanding is that with "OR" operator, later part of if statement should come into affect.
Later part of statement comes into effect if first part of statement returns false. First part of statement is always done. your first part of statement is guaranteed to crash if the array is length 256
C# isn't some sort of AI that thinks "ooh, if I do the left part of the OR then I'll get a crash, so I'll just do the right part", it just does as you told it according to its "do left, then if false, do right" rules, which might mean you try access an array index that doesn't exist
Worth pointing out that if the first two bytes in your buffer are not the same (left part of OR returns false) then you'll get another crash, this time because C# is trying to evaluate the right side of the OR, and you make it do buffer[-1]

How to apply binary search in 2D Arrays?

I have to search a for a name from the array through binary search but, show the corresponding age of the person's name instead. Please no other suggestions, I have to do it with Binary search on 2D arrays.
string[,] persons = new string[4, 2];
persons[0, 0] = "Ana";
persons[0, 1] = "19";
persons[1, 0] = "Ammara";
persons[1, 1] = "20";
persons[2, 0] = "Marilyn";
persons[2, 1] = "40";
persons[3, 0] = "Zacharaia";
persons[3, 1] = "70";
string x = "Zacharia";
int upBound = persons.GetLength(0) - 1;
int lowBound = 0;
while (lowBound <= upBound)
{
int midpoint = lowBound + (upBound - lowBound) / 2;
int result = x.CompareTo(persons[midpoint, 1]);
if (result == midpoint)
{
Console.WriteLine("The value is present at:" + persons[midpoint, 1]);
break;
}
else if (result > midpoint)
{
lowBound = midpoint + 1;
Console.WriteLine("The value is present at:" + persons[lowBound, 1]);
break;
}
else if (result < midpoint)
{
upBound = midpoint - 1;
Console.WriteLine("The value is present at:" + persons[upBound, 1]);
break;
}
}
This code is showing the age of everyone 20. The CompareTo() method is not working.
You have 4 major problems in you code:
1- Use midpoint2, lowBound2 and upBound2 for unclear reason, you should use 0 and 1 instead.
2- As you depend on binary search the key elements must be sorted, so "Ana" must be after "Ammara" although she is younger, but you search with name not age, or change it to another name, like "Aca".
3- result should be compared to 0, < 0 and > 0, it has nothing to do with midpoint.
4- You should use Console.WriteLine and break in the first condition only to let the while continue if the name wasn't found yet.
string[,] persons = new string[4, 2];
persons[0, 0] = "Aca";
persons[0, 1] = "19";
persons[1, 0] = "Ammara";
persons[1, 1] = "20";
persons[2, 0] = "Marilyn";
persons[2, 1] = "40";
persons[3, 0] = "Zach";
persons[3, 1] = "70";
string x = "Aca";
int upBound = persons.GetLength(0) - 1;
int lowBound = 0;
while (lowBound <= upBound)
{
int midpoint = lowBound + (upBound - lowBound) / 2;
int result = x.CompareTo(persons[midpoint, 0]);
if (result == 0)
{
Console.WriteLine("The value is present at:" + persons[midpoint, 1]);
break;
}
else if (result > 0)
{
lowBound = midpoint + 1;
}
else
{
upBound = midpoint - 1;
}
}
There are several problems with your code.
A binary search depends on the data being ordered. Therefore to do a binary search on the names they must be in alphabetical order, however Ammara should come before Ana, not after. However, in this case, you would still be able to successfully search for Zacharaia because it is still after the name at the midpoint.
A problem in the processing code is at the line:
x.CompareTo(persons[midpoint, 1]);
You want to compare the name in x ("Zacharia") with the name at the midpoint position, however persons[##, 1] is the location of a number. You need to use
x.CompareTo(persons[midpoint, 0]);
The CompareTo method returns 0 if the values match, < 0 if the x precedes the value and > 0 if x is after the value. However, you are comparing the result to midpoint which has nothing to do with the relative location of the value. Instead use:
if (result == 0)
{...}
else
{
if(result > 0)
{...}
else//The only possibility is for result to be < 0 so you don't need another if here.
{...}
}
The only time that you have found the value is whe result == 0, however you are writing the answer and breaking out of the while loop for all 3 cases. Only break when you find a match (result ==0).
The name in your array ("Zacharaia") is NOT the same as the name in string x ("Zacharia") therefore you will never find a match.
Ideally, your code should handle never finding a match.
If I am not wrong, you want to search names from the Array/List by binary search. For string, you can use Trie data structure to find a name.
If you are asking the names of the person performing search on their age, then proceed with the ages. First, you need to sort the names according to the ages (increasing or decreasing order). Then perform the binary search.

Detect the local minimum in a one dimensional array

I have a one-dimensional array of integers. The array may look like something shown below. The BOLD is a subset showing the object, and I would like to detect those.
4806 4706 4686 4732 4644 4660 4618 4684 4722 4878 4872 4860 4840 4832
4828 4822 4814 4806 4792 4778 4782 4774 4766 4758 4758 4754 4738 4736
4786 4780 4772 4766 4764 1996 2006 2002 1994 1998 2002 4752 4756
4740 4762 4756 4766 4762 4772 4764 4664 4518 4564 4520 4420 4540 4550
4500 4494 4498 4584 4540 4550 0 0 0 3342 3352 3338 0 0 0 0 0 0 0 0 0
0 4762 4754 4640
Or:
4806 4708 4680 4732 4650 4658 4630 4688 4726 4878 4866 4856 4844 4836
4830 4824 4810 4794 4798 4788 4778 4766 4770 4764 4756 4750 4742 4732
4780 4776 4772 4772 4770 4760 4754 4760 4758 4758 3908 3768 3766
4804 4754 4764 4764 4766 4766 4764 4676 4520 4562 4534 4422 4540 4542
4498 4496 4502 4578 4540 4538 0 0 0 0 0 3338 0 0 0 0 0 0 0 0 0 0 4758
4752 4632
As the data indicates, I have a set of data that represent distance feed back from a sensors. I want to detect how far the object is from my sensors. The easiest way to tell is by looking at the data feedback profile and see that a uniform sub-set of data that may resemble the object is being picked up. Ideally, I am trying to detect the object which face directly in the center of my sensor's FOV. So, the near-center of the feedback data is where I am most interested.
Note: The sensors have noise.
I have some idea of how to approach this and I have already done it to test out. But, I believes there are better method to approach this problem and I am keen to learn new method.
So my ideas are as follow:
1: Pick a small subset of the center of the sensors and average them.
2: Find the lower bound and upper bound of the near-center subset data. Where, lower bound is where the objects first picked up and upper bound is where the object last detected.
static int[] rangeFromeCenter = new int[80];
private static void calculateAverage(object sender, EventArgs e)
{
count++;
/// average method
int sum = 0;
int average = 0;
for (int i = 189; i < 191; i++)
{
sum += responseLMS[i];
}
average = sum / 2;
Console.WriteLine("\nAverage method \t" + average);
// end average method
/// bound finder method
Array.Copy(responseLMS, 150, rangeFromeCenter, 0, 80);
int lowerbound = 0;
int lowerboundPreveius = 0;
int difference = 0;
int lowerboundi = 0;
int upperboundi = 0;
// find lower bound
for (int i = 0; i < rangeFromeCenter.Length/2; i++)
{
if (rangeFromeCenter[i] != 0 || rangeFromeCenter[i + 1] != 0)
{
difference = rangeFromeCenter[i + 1] - rangeFromeCenter[i];
lowerbound = difference;
if (lowerbound < lowerboundPreveius)
{
lowerboundPreveius = lowerbound;
lowerboundi = i + 1;
}
}
else
{
//Console.WriteLine(" Zero found Lowerbound");
}
}
for (int i = lowerboundi; i < rangeFromeCenter.Length -1; i++)
{
if (rangeFromeCenter[i] != 0 || rangeFromeCenter[i + 1] != 0)
{
difference = rangeFromeCenter[i + 1] - rangeFromeCenter[i];
if (difference > 10)
{
upperboundi = i;
break;
}
}
else
{
//Console.WriteLine(" Zero found upperbound");
}
}
}
Another method is: finding the big jumped up and the big jumped down like as follows:
for (int i = 0; i < rangeFromeCenter.Length; i++)
{
if (rangeFromeCenter[i] != 0 || rangeFromeCenter[i + 1] != 0)
{
difference = rangeFromeCenter[i] - rangeFromeCenter[i + 1];
if (difference > 200)
{
lowerboundi = i +1;
break;
}
}
else
{
//Console.WriteLine(" Zero found upperbound");
}
}
for (int i = lowerboundi; i < rangeFromeCenter.Length -1; i++)
{
if (rangeFromeCenter[i] != 0 || rangeFromeCenter[i + 1] != 0)
{
difference = rangeFromeCenter[i + 1] - rangeFromeCenter[i];
if (difference > 200)
{
upperboundi = i;
break;
}
}
else
{
//Console.WriteLine(" Zero found upperbound");
}
}
If you have any comments on my existing approach please input. I would love to hear your feedback. Or, if you have any other approach to find the local minimum please advise.
Here is a link to a picture that I drew for better viewing of the problem and what I am trying to do:

Find number of ways in a maze non recursively

Given a matrix[n,n] I want to find out how many ways we can reach from [0,0] to [n,n] non recursively.
My approach is to
Create a stuct Node to store row, col and path travelled so far
Add node to a Queue
Iterate thru queue till not empty . Increment row, increment col. Add to Queue
Print the path if row=n, col=n
Question
Is there a different way of storing row,col and path
If n is very large, storing nodes in Queue can be a problem. How can we avoid this?
Please not I am not looking for recursive solution.
I see such questions in many interview forums and so want to know if this would be the right approach.
Below is the structure of Node and the function
struct Node
{
public int row;
public int col;
public string path;
public Node(int r, int c, string p)
{
this.row = r;
this.col = c;
this.path = p;
}
}
public static void NextMoveNonRecursive(int max)
{
int rowPos;
int colPos;
string prevPath = "";
Node next;
while (qu.Count > 0)
{
Node current = qu.Dequeue();
rowPos = current.row;
colPos = current.col;
prevPath = current.path;
if (rowPos + 1 == max && colPos + 1 == max)
{
Console.WriteLine("Path = ..." + prevPath);
TotalPathCounter++;
}
if (rowPos + 1 < max)
{
if (prevPath == "")
prevPath = current.path;
prevPath = prevPath + ">" + (rowPos + 1) + "" + (colPos);
next = new Node(rowPos + 1, colPos, prevPath);
qu.Enqueue(next);
prevPath = "";
}
if (colPos + 1 < max)
{
if (prevPath == "")
prevPath = current.path;
prevPath = prevPath + ">" + (rowPos) + "" + (colPos+1);
next = new Node(rowPos, colPos+1, prevPath);
qu.Enqueue(next);
prevPath = "";
}
}
}
Let dp[i, j] be the number of paths from [0, 0] to [i, j].
We have:
dp[0, i] = dp[i, 0] = 1 for all i = 0 to n
dp[i, j] = dp[i - 1, j] + come down from all paths to [i - 1, j]
dp[i, j - 1] + come down from all paths to [i, j - 1]
dp[i - 1, j - 1] come down from all paths to [i - 1, j - 1]
for i, j > 0
Remove dp[i - 1, j - 1] from the above sum if you cannot increase both the row and the column.
dp[n, n] will have your answer.
Given a matrix [n,n], how many ways we can reach from [0,0] to [n,n] by increasing either a col or a row?
(n*2-2) choose (n*2-2)/2
If you can only go down or right (i.e., increase row or col), it seems like a binary proposition -- we can think of 'down' or 'right' as '0' or '1'.
In an nxn matrix, every path following the down/right condition will be n*2-2 in length (for example, in a 3x3 square, paths are always length 4; in a 4x4 square, length 6).
The number of total combinations for 0's and 1's in binary numbers of x digits is 2^x. In this case, our 'x' is n*2-2, but we cannot use all the combinations since the number of 'down's or 'right's cannot exceed n-1. It seems we need all binary combinations that have an equal number of 0's and 1's. And the solution is ... tada:
(n*2-2) choose (n*2-2)/2
In Haskell, you could write the following non-recursive function to list the paths:
import Data.List
mazeWays n = nub $ permutations $ concat $ replicate ((n*2-2) `div` 2) "DR"
if you want the number of paths, then:
length $ mazeWays n
Javascript solutions with sample
var arr = [
[1, 1, 1, 0, 0, 1, 0],
[1, 0, 1, 1, 1, 1, 0],
[1, 0, 1, 0, 1, 0, 0],
[1, 1, 0, 0, 1, 0, 0],
[1, 0, 0, 0, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1]
];
function sols2(arr){
var h = arr.length,
w = arr[0].length,
i, j, current, left, top;
for(i = 0; i < h; i++){
for(j = 0; j < w; j++){
current = arr[i][j];
top = i === 0 ? 0.5 : arr[i - 1][j];
left = j === 0 ? 0.5 : arr[i][j-1];
if(left === 0 && top === 0){
arr[i][j] = 0;
} else if(current > 0 && (left > 0 || top > 0)){
arr[i][j] = (left + top) | 0;
} else {
console.log('a6');
arr[i][j] = 0;
}
}
}
return arr[h-1][w-1];
}
sols2(arr);

Finding Consecutive repetition of Elements in C# Array and Altering the element

I was given this problem
Given an int array length 3, if there is a 2 in the array immediately followed by a 3,
set the 3 element to 0.
For Example ({1, 2, 3}) → {1, 2, 0}
({2, 3, 5}) → {2, 0, 5}
({1, 2, 1}) → {1, 2, 1}
And this is my implementation.
int[] x = { 1, 2, 1 };
for (int i = 0; i < x.Length; i++)
{
if (x[i] == 2 && x[i + 1] == 3)
{
for (int j = 0; j < x.Length; j++)
{
if (x[j]==3)
{
x[j] = 0;
}
}
}
}
foreach (int i in x)
{
Console.Write(i);
}
I got zero as result. Can you help me to find where I am at mistake. I can't figure it out because the lecturer didn't gave any explanation in details.
You do not need all these loops: with the length of 3, you need to perform only two checks, like this:
if (x[0]==2 && x[1]==3) x[1] = 0;
if (x[1]==2 && x[2]==3) x[2] = 0;
For arrays of arbitrary size, you could use a single loop:
for (var i = 0 ; i < x.Length-1 ; i++) {
if (x[i]==2 && x[i+1]==3) x[i+1] = 0;
}
In your code, you have a proper check: if (x[i] == 2 && x[i + 1] == 3) However, there are 2 things you could improve on.
1) If you're going to do x[i + 1] you need to make sure that i can never be the last element of the array, because the + 1 will overflow the array. So instead of i < x.Length in the for loop, try i < x.Length - 1. It seems like duct taping, but there isn't really a better way (none I know of).
2) If the condition is true, you then have a for that will find and replace EVERY 3 in the array with a 0, regardless of if the 3 is preceded by a 2. You already know that x[i] is 2 and x[i + 1] is 3 (as determined by the if that we know at this point must be true), so the index of the 3 to be replaced is i + 1, thus: x[i + 1] = 0; No loop needed.
You can do it with one loop.
// In the test part of the for loop, use ' i < x.Length - 1'
// so you don't evaluate the last element + 1 and get an IndexOutOfRangeException
for (int i = 0; i < x.Length - 1; i++)
{
if (x[i] == 2 && x[i + 1] == 3)
x[i + 1] = 0;
}

Categories

Resources