Why does this int array throw an IndexOutOfRangeException? - c#

I feel like an idiot for asking this but I can't for the life of me figure out why this IndexOutOfRangeException is happening. (I mean, i know WHY it's happening, I just don't know what is invalid about my code) Check the code below for where the error is being thrown:
public int[, ,] FindTablePairings(System.Text.RegularExpressions.MatchCollection mcBegin, System.Text.RegularExpressions.MatchCollection mcEnd)
{
int[,,] intTablePairs = new int[mcBegin.Count, 1, 1];
int[] intBegin = new int[mcBegin.Count];
int[] intEnd = new int[mcBegin.Count];
for (int q = 0; q < mcBegin.Count; q++)
{
intBegin[q] = mcBegin[q].Index;
}
for (int q = 0; q < mcEnd.Count; q++)
{
intEnd[q] = mcEnd[q].Index;
}
int intBeginCount = mcBegin.Count;
int intEndCount = mcEnd.Count;
int i = 0;
int j = 0;
int k = 0;
while (i < intBeginCount)
{
j = i;
while (j < intEndCount)
{
if (intBegin[i + 1] < intEnd[j])
{
j++;
}
else
{
intTablePairs[i, 0, 0] = intBegin[i];
intTablePairs[i, 1, 0] = intEnd[j];
intEnd[j] = -1; //EXCEPTION OCCURS HERE
break;
}
}
if (j == intEndCount)
{
intTablePairs[i, 0, 0] = intBegin[i];
intTablePairs[i, 1, 0] = intEnd[j - 1];
intEndCount--;
}
while (k < intEndCount)
{
if (intEnd[k] == -1)
{
k++;
}
else
{
intTablePairs[i,0,0] = intBegin[i];
intTablePairs[i,1,0] = intEnd[k];
intEnd[k] = -1;
k=0;
break;
}
}
}
return intTablePairs;
}
The code is just looking at character indexes of occurrences of beginning tags and ending tags. Nothing super complicated...but the worst part is that the exception is thrown at intEnd[j] = -1;, and in the Debugger, before that statement is executed, all the arrays and MatchCollections are properly initialized and populated, including intEnd[]! I've debugged to make sure the array exists and is initalized, and I've also cleaned the solution and rebuilt it.
Anybody have any suggestions as to what's going on here??

I believe the error is actually on this line
intTablePairs[i, 1, 0] = intEnd[j];
The problem here is that you've defined the length of last 2 dimensions to both be 1 on intTablePairs. Using the index 1 is hence invalid as it's equal to the length. It seems like you meant to define the bounds as
int[,,] intTablePairs = new int[mcBegin.Count, 2, 2];

Maybe look at this:
int[] intEnd = new int[mcBegin.Count];
Replace mcBegin on mcEnd and try it out.

I suppose intEnd should be set with mcEnd.Count capacity. So instead of:
int[] intEnd = new int[mcBegin.Count];
You should have:
int[] intEnd = new int[mcEnd.Count];
Hope it helps.

Related

How to solve time constraint with coding challenge

I was doing a coding test (for practice) that went something like this:
Input is a string with |'s and *'s.
E.g. **|*|*|**|***
Implement the function:
List<int> countItems(string line, List<int> startLocations, List<int> endLocations)
Count the number of * characters that are between an opening and closing pair of | characters.
Where the 2 locations are arrays with the start and end locations (indices) to consider withing the string line.
For example if line = *|*|* and startLocations = [1] and endLocations = [3] it means
I need to check the substring *|*.
And since there is only 1 pipe, the result is zero.
The location values seemed to be 1-based and not 0-based for some reason.
If the range was 1 and 5, for example, the result would be 1 because there is only 1 * between pipes.
The code I came up with that did manage to solve about half the test cases is as follows:
List<int> countItems(string line, List<int> startLocations, List<int> endLocations)
{
var results = new List<int>();
if (String.IsNullOrWhiteSpace(line) || startLocations.Count == 0)
{
return results;
}
for (var i = 0; i < startLocations.Count; i++)
{
var startIndex = startLocations[i] - 1;
var endIndex = endLocations[i] - 1;
var start = false;
var total = 0;
var tempTotal = 0;
for (var j = startIndex; j < endIndex; j++)
{
if (!start && line[j] == '|')
{
start = true;
tempTotal = 0;
}
else if (start && line[j] == '*')
{
tempTotal++;
}
else if (line[j] == '|')
{
total += tempTotal;
tempTotal = 0;
}
}
if (line[endIndex] == '|')
{
total += tempTotal;
}
results.Add(total);
}
return results;
}
All the test cases either passed or failed because it ran out of time.
The error said it exceeded a time of 3 seconds.
Now I couldn't see the actual data being passed into the tests, so I'm not able to test it more.
But I suspect the solution was some kind of temporary list or dictionary so as to only iterate over the string 1 time instead of many times as in my code.
I want to learn what kind of solution to use in cases like this, but not really sure if this is a common type of question where the solution has some kind of name or common concept.
I would appreciate any obvious pointers to solving this type of question or even links to similar programming challenges where I can practice more.
In this case I think the best option would be to use stack theory.
It is a variation of the parenthesis balancing problem. You can find more about it here
Article parenthesis balancing problem
I managed to redo the test and I found the answer and problem type.
This is a "plates between candles" type of problem.
I was trying to solve it myself but almost ran out of time and eventually just copy/pasted an answer I found.
This was a practice run, not an actual test or application.
This was the solution that worked... I'll be studying it to better understand it...
List<int> numberOfItems(string s, List<int> startIndices, List<int> endIndices)
{
int q = startIndices.Count;
int l = s.Length;
for (var i = 0; i < startIndices.Count; i++)
{
startIndices[i]--;
endIndices[i]--;
}
var ans = new List<int>();
var prev = new int[l];
var next = new int[l];
var preSum = new int[l];
int p = -1, nxt = -1;
// calculating prev candle up to this index.
for (int i = 0; i < l; i++)
{
if (s[i] == '|')
{
p = i;
}
prev[i] = p;
}
//Calculating next candle from this index.
for (int i = l - 1; i >= 0; i--)
{
if (s[i] == '|')
{
nxt = i;
}
next[i] = nxt;
}
int c = 0;
// calculating the number of stars between these indices.
for (int i = 0; i < l; i++)
{
if (s[i] == '*')
{
c++;
}
preSum[i] = c;
}
// calculating ans.
for (int k = 0; k < q; k++)
{
int i = startIndices[k];
int j = endIndices[k];
int right = prev[j];// position of left candle.
int left = next[i];// position of right candle.
//cout<<right<<left;
if (left == -1 || right == -1 || left > right)
{
ans.Add(0);
}
else
{
ans.Add(preSum[right] - preSum[left]);
}
}
return ans;
}

how to clear Hackerank Dynamic array Runtime error?

I have done the coding and my few test cases got passed but the test case 2 and few more did not pass. When I ran the same code in local, I got the desired result but on HackerRank, it shows Runtime error.
Here is the question - https://www.hackerrank.com/challenges/dynamic-array/problem
Here is my solution:-
public static List dynamicArray(int n, List> queries) {
List<List<int>> seqList = new List<List<int>>();
for (int j = 0; j < n ; j++)
{
seqList.Insert(j, new List<int>(n-1)) ;
}
List<int> seqList2 = new List<int>();
int lastAnswer = 0;
int index;
for (int i = 0; i < queries.Count ; i++)
{
index = ((queries[i][1] ^ lastAnswer) % n);
if (queries[i][0] == 1)
{
seqList[index].Add(Convert.ToInt32(queries[i][2]));
}
else
{
int value = queries[i][2] % seqList[index].Count ;
lastAnswer = seqList[index][value];
Console.WriteLine(lastAnswer);
seqList2.Add(lastAnswer);
}
}
A runtime error on Hackerrank can be because of uninitialized variables or because of trying to access an element in an array which is not there (ArgumentOutOfRangeException)
I'm guessing in your case because of the latter.

Microsoft.Office.Interop IndexOutOfRangeException

The below IndexOutOfRangeException is not letting my code run (it compiles). While I understand this kind of exception (array indexes etc) the issue is, what I am trying to do is simply update the String subsection2 with the value in cell B[excelrow]. For some reason, there is an index out of bounds exception which to me does not make sense. Neither subsection2 or excelrow is part of an array. The only array I can think of is the excel array, but excelrow is an integer with value of 3, it should updated to row B3, and so on. (I've even tried updating with B3 directly and I get the same error).
To help you out further with context, this method called createsource takes as input the excel spreadsheet and the total rows in that sheet. It does the below code to output a 2D array containing in the first dimension the excel index of each new order (each different customer), and the 2nd dimension is the number of items ordered per customer.
The method for the code is below:
private int[,] createsource(Microsoft.Office.Interop.Excel.Worksheet xlWorksheet, int totalRows)
{
String subsection = "";
object subsection2 = "";
int orders = 0;
//figures out how many different pages there are going to be
for (int n = 3; n < totalRows + 1; n++)
{
if (!(xlWorksheet.get_Range("B" + n.ToString()).Text == subsection))
{
subsection = xlWorksheet.get_Range("B" + n.ToString()).Text;
orders++;
}
}
MessageBox.Show(orders.ToString());
int[,] source = new int[orders, 2];
int excelrow = 3;
subsection2 = xlWorksheet.get_Range("B" + excelrow.ToString()).Text;
int i;
for (i = 0; i < orders + 1; i++)
{
int j = 1;
if (excelrow == totalRows + 1)
{
break;
}
//Out of bounds exception is found in the below if statement updating subsection2:
if (!(xlWorksheet.get_Range("B" + excelrow.ToString()).Text == subsection2))
{
source[i, 0] = excelrow;
//MessageBox.Show(xlWorksheet.get_Range("B" + excelrow.ToString()).Text.ToString());
subsection2 = xlWorksheet.get_Range("B" + excelrow.ToString()).Text;
excelrow++;
}
for (int iter = 0; iter < 1;)
{
if (excelrow == totalRows + 1)
{
break;
}
if (xlWorksheet.get_Range("B" + excelrow.ToString()).Text == subsection2)
{
excelrow++;
j++;
}
if (!(xlWorksheet.get_Range("C" + excelrow.ToString()).Text == subsection2))
{
subsection2 = xlWorksheet.get_Range("C" + excelrow.ToString()).Text;
iter = 1;
}
}
source[i, 1] = j;
}
MessageBox.Show(source[2, 0].ToString());
return source;
}
I see the problem. You're declaring source as:
int[,] source = new int[orders, 2];
... okay, but look at your loop:
for (i = 0; i < orders + 1; i++)
... which later feeds into:
source[i, 0] = excelrow;
Okay, so if orders = 100, you've declared a 100 long array, going from 0-99. Then your loop, you go from 0 to "less than 100+1", aka 0-100. When you get to the last loop, you're using a value of i=100, and trying to put it into the array spot that doesn't exist.
You need to either decrease your loop by one, or increase your array size by 1.

System.IndexOutOfRangeException when forming list

I am trying to form a list with the help of multi-dimensional array that should look like this.
[validatorKey][counter]
1453 10
1231 12
6431 7
1246 1
1458 2
however, I couldn't cope with it. this is my method by the way. and also the array size should be incremented at the very end of the method. I know I should use Array.Resize(ref array, 2); but since my array is multi dimensional, in this case what should be the appropriate method.
private int AracaAitSeferSayisiDondur(int pValidatorKey)
{
int iSeferSayisi = 0;
int[,] iSeferListesi = (int[,])ViewState["SeferListesi"];
if (iSeferListesi == null)
iSeferListesi = new int[1,1];
bool aynisiVarmi = false;
for (int i = 0; i < iSeferListesi.Length; i++)
{
if (iSeferListesi[i,0] == pValidatorKey)
{
aynisiVarmi = true;
iSeferListesi[i,1]++;
iSeferSayisi = iSeferListesi[i,1]++;
break;
}
}
if (!aynisiVarmi)
{
int arrayLength = iSeferListesi.Length;
iSeferListesi[arrayLength--, 0] = pValidatorKey;
iSeferListesi[arrayLength--, 1] = 1;
//IN THIS PART ARRAY SIZE SHOULD BE INCREASED
iSeferSayisi = iSeferListesi[arrayLength--, 1];
}
ViewState["SeferListesi"] = iSeferListesi;
return iSeferSayisi;
}
I think you need sonmething like:
// not tested
private int AracaAitSeferSayisiDondur(int pValidatorKey)
{
var iSeferListesi = (Dictionary<int,int>)ViewState["SeferListesi"];
if (iSeferListesi == null)
iSeferListesi = new Dictionary<int,int>;
int iSeferSayisi;
if ( iSeferListesi.TryGetValue(pValidatorKey, out iSeferSayisi)
{
iSeferSayisi += 1;
iSeferListesi[pValidatorKey] = iSeferSayisi;
iSeferSayisi += 1; // is this OK ??
}
else
{
iSeferSayisi = 1;
iSeferListesi[pValidatorKey] = iSeferSayisi;
}
ViewState["SeferListesi"] = iSeferListesi;
return iSeferSayisi;
}
The double increment of iSeferListesi (derived from your code) is probably not what you want, without it the if/else logic becomes even simpler.
The Length proprety returns the total number of elements in the array.
Use the GetLength(dimension) method to get the size of a dimension:
for (int i = 0; i < iSeferListesi.GetLength(0); i++)
and:
int arrayLength = iSeferListesi.GetLength(0);

Reverse an array without using Array.Reverse()

How to reverse an array (in C#) without using Array.Reverse() method?
For example,
int[] arr = {1,3,4,9,8};
// some code here
Console.WriteLine(string.Join(",", arr));
should result in
8,9,4,3,1
I got this as an interview task.
The code to be substituted in place of // some code here in the question is:
for (int i = 0; i < arr.Length / 2; i++)
{
int tmp = arr[i];
arr[i] = arr[arr.Length - i - 1];
arr[arr.Length - i - 1] = tmp;
}
You should iterate only through the first half of the array (arr.Length / 2). If you iterate through the whole array (arr.Length), it will be reversed twice, yielding the same element order as before it started.
Basically, you are asked to reimplement Array.Reverse(Array). If you look at how it is implemented in the framework itself and ignore many technical details around, you’ll find that it just calls its three-parameter version (which reverses specified part of an array) on the whole array.
Array.Reverse(Array,Int32,Int32) is a while-loop that swaps elements and maintains two indexes:
i points to the first element of the reversed part, and
j points to the last element of the reversed part.
Rewritten to be substituted in place of // some code here in the question:
int i = 0;
int j = arr.Length - 1;
while (i < j)
{
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
This is easier to grasp than the implementation using for-loop, does less arithmetic and elegantly evades the gotcha with double reversion.
That is So Simple Start loop from Array legth and so on watch code and you will get understand :)))
int[] arr = new int[5] { 1, 2, 3, 4, 5 };
for (int i = arr.Length-1; i >= 0; i--)
{
Console.WriteLine(arr[i]);
}
int[] arr1 = {1,3,4,9,8};
int[] arr2 = new int[5];
int j = 0;
for(int i = arr1.Length - 1; i >= 0; i--)
{
arr2[j] = arr1[i];
j++;
}
for (int i = 0; i < array.Length - i; i++)
{
var value = array[array.Length - i - 1];
array[array.Length - i - 1] = array[i];
array[i] = value;
}
Well, obviously you can just copy to a new array, in reverse order.
To do the operation "in place", you can work from both ends towards the middle: Load the first and last elements, then store them back, the first into the last location, and the last into the first location. Then do the second and the next-to-last, etc. If you have an even number of elements you do N/2 iterations. If an odd number you do (N-1)/2 iterations and leave the middle element where it was.
There are probably other algorithms that would be marginally faster when considering cache line size and other memory characteristics, but they wouldn't be worth it unless you were in a really performance-critical situation.
// without using Reverse method and without using additional array
// try yield operator starting from the last element
public IEnumerable<int> Reverse (int[] array)
{
for (int i = array.Length - 1; i >= 0; i--) {
yield return array [i];
}
}
char[] strx = { '1','2','3','4','5','6','7','8','9' };
int i = strx.Length;
string ktr ="";
while (i>0)
{
i--;
ktr += strx[i];
if (i==0)
{
i = strx.Length;
while (i > 0)
{
i--;
strx[i] = ktr[i];
}
}
}
int j;
Console.WriteLine("Array strx in reverse order: ");
for (j = 0; j < strx.Length; j++ )
{
Console.Write("{0}", strx[j]);
}
try something like:
var counter = 1;
var newArr = new int[arr.length];
for(int i = 0; i < arr.length; i++)
{
newArr[i] = arr[arr.length - counter];
counter++;
}
I didn't test that but it should be on the right track. Any reason you dont want to use Array.Reverse? Its probably a well-optimized version of the algorithm.
You can do this in many ways, from the most fast to the most stupid like:
int[] arr = new int[] { 1,2,3 };
arr = (from a in arr orderby a descending select a).ToArray();
But I cannot understand why are you pursuing such a futile quest, if that is to impress someone somewhere then use this instead of the for loops :)
I am not good at loops at all. But this is what seems simple to me -
int[] array1 = { 1, 2, 3, 4, 5 };
int[] reverseArray = new int[array1.Length];
for (int i = 0; i <= array1.Length - 1; i++)
{
reverseArray[i] = array1[array1.Length - i - 1];
}
This is the dynamic solution for reversing the array of any datatype.Some of the key points in my algorithm is first calculate the half of array length and add check to stop iteration when array indexes have same value.The stage having same indexes depict that it start the reverse operation again.So at this stage break the outer loop by using "goto Statement".
string[] unreversed = {"A","B","C","D","E","F","G","H","I","J","K"};
int q=unreversed.Length;
int t = q / 2;
var temp1 = "A";
for(int i = 0;i<unreversed.Length;i++)
{
q = q - 1;
for(int k=q;k<=q;k++)
{
if (unreversed[k] != unreversed[i] && i!=t)
{
temp1 = unreversed[i];
unreversed[i] = unreversed[k];
unreversed[k] = temp1;
}
else
{
goto printarray;
}
}
}
printarray:
foreach (var k in unreversed)
{
Console.WriteLine(k);
}
//Create temp array with the same size.
int[] arrTemp = new int[arr.Length];
int i = 0;
//Assign last value of arr to first value of arrTemp
for (int j = arr.Length - 1; j >= 0; j--)
{
arrTemp[i] = arr[j];
i++;
}
arr = arrTemp;
I prefer a LINQ expression that uses an index:
using System.Linq;
int[] arr = { 1, 3, 4, 9, 8 };
arr = arr.Select((n, idx) => new {n, idx})
.OrderByDescending(r => r.idx)
.Select(r => r.n).ToArray();
public int[] Reverse(params int[] numbers)
{
for (int i = 0; i < numbers.Length / 2; i++)
{
int tmp = numbers[i];
numbers[i] = numbers[numbers.Length - i - 1];
numbers[numbers.Length - i - 1] = tmp;
}
return numbers;
}
Here is an example of reversing an array using the Length() function and a simple for loop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
int[] arr = new int[] {4, 8, 2, 9, 5, 5};
int length = arr.Length;
for(int i = 0; i < arr.Length; i++)
{
Console.WriteLine(arr[length-1] + " ");
length = length - 1;
}
}
}
}
You can try this, Without using additional temporary variable:
for(int i = left; i < right/2; i++)
{
(nums[i], nums[right - i - 1]) = (nums[right - i - 1], nums[i]);
}
Stack stack=new Stack;
var newArr = new int[arr.length];
for(int i = 0; i < arr.length; i++)
{
stack.push(arrr[i])
}
for(int i = 0; i < arr.length; i++)
{
newarr[i]= stack.pop()
}
int[] array1 = { 1, 2, 3, 4, 5 };
for (int x = 4; x < array1.Length && x != -1; x--)
{
int tmp;
tmp=array1[x];
Console.Write("{0} ", tmp);
}
That's my solution for this.
It is better to use Array.Reverse method
int[] arr ={1,3,4,9,8};
Array.Reverse(arr);
You can read more description Here
int[] triangles = new int[]{0,1,2,3}
for (int j = triangles.Length; j > (triangles.Length / 2); j--)
{
var temp = triangles[j - 1];
triangles[j - 1] = triangles[triangles.Length - j];
triangles[triangles.Length - j] = temp;
}
I would prefer to reverse an array from the end of it. My solution's above.
Console.WriteLine("Enter a string");
string input = Console.ReadLine();
string s = "";
for (int i = input.Length-1 ; i >= 0; i--)
{
s = s + input[i];
}
Console.WriteLine(s);
function printReverse(arr) {
for(var i = arr.length - 1; i >= 0; i--){
console.log(arr[i]);
}
}
printReverse([1, 2, 3, 6, 47, 88]);
function printReverse(arr) {
for (var i = arr.length - 1; i >= 0; i--) {
console.log(arr[i]);
}
}
printReverse([1, 2, 3, 6, 47, 88])
Can do this with single for loop..
int[] arr ={1,3,4,9,8};
for(int i=arr.length-1;i>=0;i--)
{
Console.Write(arr[i]);
}
You can just loop backwards:
int[] arr= new int[] {1, 2, 3, 4, 6};
for(int i=arr.Length-1 ;i>= 0 ; i--)
{
Console.WriteLine(arr[i].ToString());
}

Categories