Sparse matrix (next element) - c#

I have to do a home project, but I can't do it with my current knowledge. I searched for it, but I haven't found any useful tips. Here is a sparse matrix, and I have to get the "Next elements" The next elements are the element who are the second in a 2d arrays column, if there is no second element, for that column the output is "-1" . In the output I need to write out the serial number of the element.
Here is the 2d array, the red numbers are the "serial numbers"
The output should be this : 8, -1, -1, 6, -1, -1, 9, -1, -1, -1, -1.
To clarify: if you scan left-to-right (and continue on the next row). Replace each value (greater than zero) with it's ordinal position (shown in red). Then scan again (left-to-right, top-to-bottom) when you find any number (greater than zero), search down in that column. If there is another number (red) (greater than zero) in that column, print that (red) number. Otherwise print -1.
Second-pass, finding "Next elements".
0 finds 8, 1 finds nothing, 2 finds nothing, 3 finds 6, etc.

I got the answer, i just overthinked the algorytm of the program.
for(int i = 0; i < oszlop.Length; i++)
{
kov[i] = Array.IndexOf(oszlop, oszlop[i], i + 1);
}
The "oszlop" array is an 1d array and contains the column indexes of the rare elements. If i got a rare element, i check if is there any other element with the same column index, if there is, i will save in the "kov" array, otherwise save "-1" in to the "kov" array.

Related

What is the logic behind the .. range selection operator?

I am trying to understand why the .. operator works the way it does, for example:
var data = new []{0,1,2,3,4,5,6,7,8,9,10};
var test = data[1..4]; // This returns array with 1,2,3
Logically, I would assume the result would be either 1,2,3,4 or 2,3 (if the last index isn't included then the first one shouldn't also)
or
var test = data[0..]; // This returns array with 0,1,2,3,4,5,6,7,8,9,10 (zero at index 0 is also included)
var test = data[^0..]; // This returns array with nothing, where i would expect 10, since 10 is at index zero if we traverse the array backwards
I know there must be a reason why it was designed to work like that, but I can't seem to figure it out, so what is the purpose of this behavior?
Thank you.
Why is the end index not included, but the start index is?
This is known as a half open range, and there are already questions asking about this in Python and C++. Essentially, the main advantage of this is that:
The length of the range is exactly (end - start).
You don't need to add/minus 1 as much in range-based algorithms
To slice something in half at an index, you can use the same index: x[..i] gives you the first half, and x[i..] gives you the second half. i.e. x[..i] concatenated with i[i..] is equal to x itself.
If a range's end is equal to another's start, the two ranges are immediately next to each other, and no overlapping.
Why is data[^0..] empty?
This is documented clearly. ^n means Length - n, so ^0 means data.Length - 0 here, which is just data.Length. data[data.Length..] is clearly empty.
It's simple enough. Consider the following:
var data = new []{0,1,2,3,4,5,6,7,8,9,10};
var test = data[0..10];
The 0 to 10, implies that it will select 11 items, if the last was inclusive. You have to start at 0, as C# indexes are zero based, and you'd need a -1 to include the first, if they were both exlusive.
As mentioned in the documentation:
A range specifies the start and end of a range. Ranges are exclusive, meaning the end isn't included in the range. The range [0..^0] represents the entire range, just as [0..sequence.Length] represents the entire range.
The data[^0..]; statements means, starting from the 0 position, bring whatever is below it. The ^ operator works inversly for the same reasons. (^0 is not inclusive of 0)

invert a specific part of a list C#

I need a program to reverse part of a list between two terminals.
Example :
List: 1, 2, 3, 3, 5, 4
Output: 1, 2, 3, 3, 4, 5 (Only the 4 and 5 are inverted)
I found this:
positionCrepe.Reverse(indexOfMaxToSearch, positionCrepe.Count);
But it doesn't work because I have a mistake:
System.ArgumentException: The offset and length were out of bounds for this table or the number is greater than the number of index elements at the end of the source collection.
However
indexOfMaxToSearch = 2
and
positionCrepe.count = 5
and so it does not exceed the index of the table
Anyone have a solution?
Thank you.
The second argument is how many elements you want to reverse, not how many elements there are in the list.
So if you want to reverse everything starting from indexOfMaxToSearch, you want to reverse positionCrepe.Count - indexOfMaxToSearch elements:
positionCrepe.Reverse(indexOfMaxToSearch, positionCrepe.Count - indexOfMaxToSearch);
The error message is actually saying that the first argument plus the second argument is out of range of the array.
if you look at the definition of Reverse,
index: The zero-based starting index of the range to reverse.
count: The number of elements in the range to reverse.
You can use the following to make it work. Count must be less then the remaining indecies
positionCrepe.Reverse(2, positionCrepe.Count - 2);

Need to understand the behaviour of BinarySearch and IndexOf methods

I have List and its values is ("Brandenburg","Alabama" and "Alberta"). When i used BinarySearch("Brandenburg") method, it returns -4 instead of 0. but i can get the correct index, when sorted this list. Why it returns wrong value if I use the unsorted list?. And I have also get the correct index from IndexOf("Brandenburg") method. Which method is useful that i can use?.
Thanks in Advance,
Prithivi
It MUST be sorted, to use binary search. The reason you're getting -4 is;
Your collection isn't sorted and for binary search the list will 'cut' in half each iteration. So:
When it starts, the topIndex == 0 and bottom = 2
TopIndex -> (0) "Brandenburg",
(1) "Alabama"
BottomIndex -> (2) "Alberta
The binarysearch will check the item in the middle: (2-0) / 2 = 1. If you're searching for Brandenburg. It will compare Alabama with your search item. The letter B is 'bigger' than letter 'A'. So it moves the topIndex to index 1.
(0) "Brandenburg",
TopIndex -> (1) "Alabama"
BottomIndex -> (2) "Alberta
Then it will compare to the next 'middle' item. In this case again Alabama. (2-1) / 2 = 1. It will also be compare to the bottomIndex, but this is the last one.
When binarysearch returns a negative number, it means that the item cannot be found. The negative number is the Index where it should be inserten. (-result -1) So if you want the new item added, it should be inserted on index (--4 -1) == 3
Let me explain how binary search works.
Say you have this array:
{1, 3, 5, 7, 10, 15, 20}
And I want to find the index of 15. What binary search will do is that it looks at the middle of the array, 7. Is 7 greater or less than 15? If it is less than 15, do the same thing again on the second half of the array (10, 15, 20). If it is greater than 15, do it on the first half (1, 3, 5). If it is equal to 15, then that means 15 is found.
This means that the array must be sorted for binary search to work. This explains why doing a binary search on your array returns a negative number. Because obviously, the method can't find the string you requested using the binary search algorithm.
You can get the correct index with IndexOf. This is because IndexOf uses a linear search to find the item. It looks at each element in the array and compare to the one that you're finding. Therefore, whether the array is sorted doesn't matter.
Note: I have not read the source code of IndexOf. It might use a binary search if it finds that the array is sorted. This is only my guess.

Why does array-size declaration use "1" as the first index?

Something that I noticed about C#/Java is this seemingly (to me at the moment) inconsistent issue with array size declaration and the default first-index of array sizes.
When working with arrays, say you want to create a new integer array size 3, it would look like this:
int[] newArray = new int[3] {1, 2, 3};
Totally find and readable... Right?
The standard with programming languages seem to dictate that the "first" index is 0.
Using that logic, if I am interested in creating an array the size 3, I should really be writing this:
int[] newArray = new int[2] {1, 2, 3};
Wait a minute.. VS is throwing an error, saying an array initialize of length 2 is expected.
So there's an inconsistency with the first index in looping through an array and the array-size declaration? The former uses a 0-th based index, and the second a 1-th index.
It's not game-breaking/changing in any form or way, but I'm genuinely curious why there's a discrepancy here, or hell, if this is even an issue at all (like I say, it's not game-breaking in any way, but I'm curious as to why it's done this way).
I can at the moment think of reasons why 1-th based index would be used:
In a for-loop you would use < newArray.Length as opposed to < newArray.Length - 1 or < newArray.Length.
Working with Lists for awhile and then coming back to size-needs-to-be-declared-arrays caught me a bit off-guard.
Because you are declaring the array with the number of elements it will contain.
I am unsure how that is inconsistent.
How many times do you have to saw to cut a log in 3 pieces? Hint: not 3 times.
Also note how in your post title you incorrectly refer to the array size declaration as 'index'.
I think you are confusing the indexer with the length. You want to hold three elements (or variables) in your array, denoted by
...new int[3]...
and the elements in the curly brackets are the values, not the index. Index is still 0-based. Longform would look like this:
int[] newArray = new int[3];
newArray[0] = 1;
newArray[1] = 2;
newArray[2] = 3;
So in that, you can see where your zero-based index is as it relates to the values of your int[].
int[] newArray = new int[2] {1, 2, 3};
In English, this would translate you "I want a container that can hold 2 items but put 3 items in it". You are confusing the length of an array (how many items it can hold) with the index into the array which is 0-based in C-based languages (ex. C, C++, C#, Java, Javascript, Swift).
Also, consider what an array index really is (atleast with low level languages like C); it's an offset in memory from the base address of your array variable. So arr[n] translates to "take the address for arr, advance n * (the size of my type) bytes in memory, and give me the value at that calculated address. So when n = 0, you are referencing the value at the base memory address (the beginning of the array).
Answer provided by Wim Hollebrandse is absolutely great and correct, but wanted to expand on it a little bit to give OP a bit more understanding why indices start with 0 in most (but not all) languages.
As Wim stated, at declaration it is how many elements will be stored in an array, and that's quite palatable for human understanding. What confuses many is why 1st item is actually referred to as 0th (i.e. index 0)... The reason for this is the simple math that is needed to find seeked element in array.
All elements in array are stored sequentially in contiguous block. If the array is located for example at address 100 and hold integers (each integer of size 4 bytes), then when looking for the very first item, it would be located in the beginning of array, that is at address 100. The second item will be stored immediately after the first, or 100+4=104 address. 3rd item is stored after 2nd or at address 108.
So to calculate position of I-th element, if indices begin with 0, the math is simple:
I-th-address = address_of_array + I * sizeof(datatype)
e.g. for our example it is 100 + i * 4
if indices begin with 1, then math requires more operations:
Ith-address - address of array + (I-1) * sizeof(datatype)
... which is less efficient and unnecessary than the 0-based.
You are mixing the declaration of the array with the request of an array element. While declaring an array you specify the length of the array (number of elements), and this is 3, correct. When you request an element, the you specify the index, and the first index is 0. But you shouldn't mix the index and the length of the array.
In a for-loop, you should take < newArray.Length: If you have a length of 3, then the loop will start at 0 and go through index 0, 1 and 2. Then it stops, because 3 is not < 3.

Jumping segments in binary

My question is, is there a way in C# with a starting bit location to find the next binary digit within a byte that has a specified value of 0 or 1 without iteration (looking for the highest performance option).
As an example, if you had 10011 and started at the first bit (far right) and searched for the first 0, it would be the 3rd place going right to left. If you then started at the 3rd place and wanted to find the next 1, it would be at the 5th place (far left).
Thanks for any help and feel free to let me know if I need to provide anything further.
Edit: Here is my current code.
private int GetBinarySegment(uint uiValue, int iStart, int iMaxBits, byte bValue)
{
int r = 0; uiValue >>= iStart;
if (uiValue == 0) return iMaxBits - iStart;
while ((uiValue & 1) == bValue) { uiValue >>= 1; r++; }
return r;
}
There are ways, but they're ugly because there's no _BitScanForward or equivalent intrinsic. Still, you can actually compute this thing efficiently without needing a huge table.
First step: make a number that has a 1 at the position you're searching for and 0 everywhere else.
If searching for a 1, that means x & -x. If searching for a 0, use ~x & (x + 1).
Then, use one of the many ways to emulate either bitscan (there is only one set bit now, so it doesn't matter which side you search from). Some ways to do that are detailed here (not in C#, but you can convert them).
Use a lookup table. That is, precalculate a 2D array indexed by byte value and current position. You can do a separate table for zeros and ones, or you can combine it.
So for your example, you start at bit 0 of the number 19. That happens to be a 1. So if you lookup nextBit[19][0] it should return 1, and so on. Here's what a combined lookup table might look like. It shows the next bit for both 0s and 1s:
nextBit[19][0] = 1 // 1
nextBit[19][1] = 4 // 1
nextBit[19][2] = 3 // 0
nextBit[19][3] = 4 // 0
nextBit[19][4] = 0 // 1
nextBit[19][5] = 6 // 0
nextBit[19][6] = 7 // 0
Obviously there is no 'next' for bit 7, and if 'next' returns 0, there are no more of that particular bit.
I may have interpreted your question incorrectly, but this technique can be modified to suit your purposes. I initially thought you wanted to navigate through all 1-bits or 0-bits. If instead you want to skip over consecutive 1-bits, then you just arrange your table in that way. Or indeed, you can have a 'next' for both 0 and 1 at each position.

Categories

Resources