system.IndexOutOfRange exception in C# [duplicate] - c#

This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed 5 years ago.
I know this kind of question is asked before, but I am a noob and cannot understand where the array is out of bounds.
P.S this is not the exact duplicate of the every " system.IndexOutOfRange exception in C# " as the situation and the context of the problem is totally different from each other.So please read the question first before reporting it as the " exact duplicate ".
class Program
{
static void Main(string[] args)
{
int highestcount = 0, e = 0, h = 0;
string highest = "", a = "", b = "", j = "";
int y = int.Parse(Console.ReadLine());
e = y - 1;
string[] savArray = new string[e];
for (int count = 0; count < y; count++)
{
var x = Console.ReadLine().Split(' ');
if (count+1 <= y)
{
j = x[count + 1];
savArray[count] = j;
}
}
for (int count1 = 0; count1 < y; count1++)
{
h = 0;
a = savArray[count1];
for (int count2 = 1; count2 < y; count2++)
{
b = savArray[ count2];
if (a == b)
{
h = h + 1;
if (highestcount <= h)
{
highestcount = h;
highest = a;
}
}
}
}
Console.Write(highest);
Console.Read();
}
}
The program is to find the most common sport.
First, the user has to enter how many no: of entries are there on the list.
After that, the user has to enter his name and then his favorite sport.
If you read the program what I meant to do is simply save the 2nd value of x in the array because every second value is the sport which the user has given, as I want to save the sport's name to check which sport is more common.
But the exception is ruining the simple idea and I am stuck with it, please help.

Let's say that savArray has 1 element.
Then you do this:
var x = Console.ReadLine().Split(' ');
//Let's say x is "X" which is creates an array of size 1
if (count + 1 <= y) <----this is true (0+1<=1)
{
j = x[count + 1]; <----- BOOM x[1] when x has only one element.

for (int count = 0; count < y; count++)
{
var x = Console.ReadLine().Split(' ');
if (count+1 <= y)
{
j = x[count + 1];
savArray[count] = j;
}
}
Haven't double checked but...
[count + 1]
Given the for loop constraints (count < y)
the maximum possible value for count is y - 1...
but....
count + 1 when count = y -1... and thus is out of range... I think. Again. Haven't double checked.

Related

Why is bubble sort running faster than selection sort?

I am working on a project that compares the time bubble and selection sort take. I made two separate programs and combined them into one and now bubble sort is running much faster than selection sort. I checked to make sure that the code wasn't just giving me 0s because of some conversion error and was running as intended. I am using System.Diagnostics; to measure the time. I also checked that the machine was not the problem, I ran it on Replit and got similar results.
{
class Program
{
public static int s1 = 0;
public static int s2 = 0;
static decimal bubblesort(int[] arr1)
{
int n = arr1.Length;
var sw1 = Stopwatch.StartNew();
for (int i = 0; i < n - 1; i++)
{
for (int j = 0; j < n - i - 1; j++)
{
if (arr1[j] > arr1[j + 1])
{
int tmp = arr1[j];
// swap tmp and arr[i] int tmp = arr[j];
arr1[j] = arr1[j + 1];
arr1[j + 1] = tmp;
s1++;
}
}
}
sw1.Stop();
// Console.WriteLine(sw1.ElapsedMilliseconds);
decimal a = Convert.ToDecimal(sw1.ElapsedMilliseconds);
return a;
}
static decimal selectionsort(int[] arr2)
{
int n = arr2.Length;
var sw1 = Stopwatch.StartNew();
// for (int e = 0; e < 1000; e++)
// {
for (int x = 0; x < arr2.Length - 1; x++)
{
int minPos = x;
for (int y = x + 1; y < arr2.Length; y++)
{
if (arr2[y] < arr2[minPos])
minPos = y;
}
if (x != minPos && minPos < arr2.Length)
{
int temp = arr2[minPos];
arr2[minPos] = arr2[x];
arr2[x] = temp;
s2++;
}
}
// }
sw1.Stop();
// Console.WriteLine(sw1.ElapsedMilliseconds);
decimal a = Convert.ToDecimal(sw1.ElapsedMilliseconds);
return a;
}
static void Main(string[] args)
{
Console.WriteLine("Enter the size of n");
int n = Convert.ToInt32(Console.ReadLine());
Random rnd = new System.Random();
decimal bs = 0M;
decimal ss = 0M;
int s = 0;
int[] arr1 = new int[n];
int tx = 1000; //tx is a variable that I can use to adjust sample size
decimal tm = Convert.ToDecimal(tx);
for (int i = 0; i < tx; i++)
{
for (int a = 0; a < n; a++)
{
arr1[a] = rnd.Next(0, 1000000);
}
ss += selectionsort(arr1);
bs += bubblesort(arr1);
}
bs = bs / tm;
ss = ss / tm;
Console.WriteLine("Bubble Sort took " + bs + " miliseconds");
Console.WriteLine("Selection Sort took " + ss + " miliseconds");
}
}
}
What is going on? What is causing bubble sort to be fast or what is slowing down Selection sort? How can I fix this?
I found that the problem was that the Selection Sort was looping 1000 times per method run in addition to the 1000 runs for sample size, causing the method to perform significantly worse than bubble sort. Thank you guys for help and thank you TheGeneral for showing me the benchmarking tools. Also, the array that was given as a parameter was a copy instead of a reference, as running through the loop manually showed me that the bubble sort was doing it's job and not sorting an already sorted array.
To solve your initial problem you just need to copy your arrays, you can do this easily with ToArray():
Creates an array from a IEnumerable.
ss += selectionsort(arr1.ToArray());
bs += bubblesort(arr1.ToArray());
However let's learn how to do a more reliable benchmark with BenchmarkDotNet:
BenchmarkDotNet Nuget
Official Documentation
Given
public class Sort
{
public static void BubbleSort(int[] arr1)
{
int n = arr1.Length;
for (int i = 0; i < n - 1; i++)
{
for (int j = 0; j < n - i - 1; j++)
{
if (arr1[j] > arr1[j + 1])
{
int tmp = arr1[j];
// swap tmp and arr[i] int tmp = arr[j];
arr1[j] = arr1[j + 1];
arr1[j + 1] = tmp;
}
}
}
}
public static void SelectionSort(int[] arr2)
{
int n = arr2.Length;
for (int x = 0; x < arr2.Length - 1; x++)
{
int minPos = x;
for (int y = x + 1; y < arr2.Length; y++)
{
if (arr2[y] < arr2[minPos])
minPos = y;
}
if (x != minPos && minPos < arr2.Length)
{
int temp = arr2[minPos];
arr2[minPos] = arr2[x];
arr2[x] = temp;
}
}
}
}
Benchmark code
[SimpleJob(RuntimeMoniker.Net50)]
[MemoryDiagnoser()]
public class SortBenchmark
{
private int[] data;
[Params(100, 1000)]
public int N;
[GlobalSetup]
public void Setup()
{
var r = new Random(42);
data = Enumerable
.Repeat(0, N)
.Select(i => r.Next(0, N))
.ToArray();
}
[Benchmark]
public void Bubble() => Sort.BubbleSort(data.ToArray());
[Benchmark]
public void Selection() => Sort.SelectionSort(data.ToArray());
}
Usage
static void Main(string[] args)
{
BenchmarkRunner.Run<SortBenchmark>();
}
Results
Method
N
Mean
Error
StdDev
Bubble
100
8.553 us
0.0753 us
0.0704 us
Selection
100
4.757 us
0.0247 us
0.0231 us
Bubble
1000
657.760 us
7.2581 us
6.7893 us
Selection
1000
300.395 us
2.3302 us
2.1796 us
Summary
What have we learnt? Your bubble sort code is slower ¯\_(ツ)_/¯
It looks like you're passing in the sorted array into Bubble Sort. Because arrays are passed by reference, the sort that you're doing on the array is editing the same contents of the array that will be eventually passed into bubble sort.
Make a second array and pass the second array into bubble sort.

How to put char ('X') to int array?

Hi I have 2D array type of int where I have numbers, for example from 1 to 100.
It's a game - something like Tic-Tac-Toe - but I use bigger array. So I need to put a character 'X' or 'O' from user to this array. But problem is I can't (don't know) how to put these characters in that int array. I wan to use only the console.
I tried make the array type of char but then I can't fill the array with numbers.
I know how to do it if user would have want put some numbers but then It doesn't look good...
I would be happy for any advice how to do it.
public void Napln () { //filling the array
int poc = 1;
for (int i = 0; i < pole.GetLength(1); i++)
{
Console.Write(" ");
for (int j = 0; j < pole.GetLength(0); j++)
{
if (poc < 10)
Console.Write(" " + (pole[j, i] = poc++) + " | ");
else if ( poc < 100 )
Console.Write( (pole[j,i] = poc ++) + " | ");
else
Console.Write((pole[j, i] = poc++) + " | ");
}
Console.WriteLine();
for ( int v = 0; v < roz1; v ++ )
Console.Write("_____|");
Console.WriteLine();
}
Console.WriteLine();
public void Pozice (int vyber) //find the user choice
{
for ( int i = 0; i < pole.GetLength(1); i ++ )
{
for ( int j = 0; j < pole.GetLength(0); j ++ )
{
if (pole[i, j] == vyber)
{
pole[i, j] = 'X';
hraci.Vypis();
}
}
}
}
public void Vypis() //print the same with change of user choice
{
for ( int i = 0; i < pole.GetLength(1); i ++ )
{
Console.Write(" ");
for ( int j = 0; j < pole.GetLength(0); j ++ )
{
if (pole[j,i] < 10)
Console.Write(" " + pole[j, i] + " | ");
else if (pole[j,i] < 100)
Console.Write(pole[j, i] + " | ");
else
Console.Write(pole[j, i] + " | ");
}
Console.WriteLine();
for (int v = 0; v < roz1; v++)
Console.Write("_____|");
Console.WriteLine();
}
}
I am the new one in C# especially the OOP. So if you have any more advice I would be happy.
Just taking your question as it is, I can imagine two ways I'd do it without getting too fancy.
The first one would be to use two arrays. One for holding the numbers (and int array), one for holding the player input (a char array holding "x" and "o"). This could look like this:
public class Program
{
public static void Main()
{
int width = 10;
int height = 10;
char[,] playerBoard = new char[width, height];
int[,] numberedBoard = new int[width, height];
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
// Fill the numbered board with 1 to 100
numberedBoard[x, y] = x * width + y + 1;
// And the player board with emptyness
playerBoard[x, y] = ' ';
}
}
System.Console.WriteLine("Number at x = 3 / y = 5: " + numberedBoard[3, 5]);
System.Console.WriteLine("Current owner of x = 3 / y = 5: \"" + playerBoard[3, 5] + "\"");
// Let's change the owner of x = 3 and y = 5
playerBoard[3, 5] = 'X';
System.Console.WriteLine("New owner of x = 3 / y = 5: \"" + playerBoard[3, 5] + "\"");
}
}
A second solution could be to create an object to fit your needs, and have an array of this one. The benefit is that you only have one array, and each cell holds all the information relevant to this cell. Consider the following:
using System;
public class Program
{
struct BoardEntry {
public int number;
public char owner;
}
public static void Main()
{
int width = 10;
int height = 10;
BoardEntry[,] board = new BoardEntry[width, height];
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
// For each "cell" of the board, we create a new instance of
// BoardEntry, holding the number for this cell and a possible ownage.
board[x, y] = new BoardEntry() {
number = x * width + y + 1,
owner = ' '
};
}
}
// You can access each of those instances with `board[x,y].number` and `board[x,y].owner`
System.Console.WriteLine("Number at x = 3 / y = 5: " + board[3, 5].number);
System.Console.WriteLine("Current owner of x = 3 / y = 5: \"" + board[3, 5].owner + "\"");
// Let's change the owner of x = 3 and y = 5
board[3, 5].owner = 'X';
System.Console.WriteLine("New owner at x = 3 / y = 5: \"" + board[3, 5].owner + "\"");
}
}
It seems like you are new to programming, so the first solution might be easier to understand and use right now, but I suggest you read at some point a little bit into what structs and classes are, because they let you do some really powerful things, like in this case bundle the relevant information that belongs together.

Does adding extra loop at the end of n(log n) algorithm affect the complexity?

I wrote an algorithm to find length of longest increasing sequence in an array.
The algorithm has an array m which will contain the sequence but in some conditions, it doesn't contain the exact sequence. So in such case, I record the index and value which needs to be changed.
This algorithm is n(log n)
Now, to find the actual sequence, I loop through the array m and replace the value recorded in another array. Will my algorithm now still have the complexity if n(log n) ?
Below is the code in C#:
int[] b = { 1, 8, 5, 3, 7, 2, 9 };
int k = 1;
int i = 1;
int N = b.Length;
List<int> m = new List<int>();
int[] lup = new int[b.Length];
m.Add(0);
m.Add(b[0]);
lup[0] = 0;
while (i < N)
{
if (b[i] >= m[k])
{
k = k + 1;
m.Add(b[i]);
}
else
{
if (b[i] < m[1])
{
m[1] = b[i];
}
else
{
int j;
j = Binary_Search(m, b[i], m.Count - 1);
//if the item to be replaced was not the last element, record it
if (m[j] > b[i] && j != k)
{
lup[j] = m[j];
}
m[j] = b[i];
}
}
i = i + 1;
}
Console.WriteLine("The Input Sequence is : " + string.Join("\t", b));
Console.WriteLine("Length of Longest Up Sequence is : " + k.ToString());
List<int> result = new List<int>();
// create result based on m and lup
//DOES THIS LOOP EFFECT PERFORMANCE??
for(int x = 1; x < m.Count; x++)
{
if (lup[x] == 0)
{
result.Add(m[x]);
}
else
{
result.Add(lup[x]);
}
}
Your intuition is correct. Adding this loop is n*(log(n)+1) so it's still n*log(n).

Avoid IndexOutOfRangeException by looping back to start of array

I have a array [4,4] that I am looping through and printing values.
trainingpatterns.array = new int[4, 4];
for (int i = 0; i < 4; i++)
{
var element1 = x + array.coordinates[0];
var element2 = x + array.coordinates[2];
var element3 = x + array.coordinates[4];
var element4 = x + array.coordinates[6];
for (int j = 0; j < 4; j++)
{
var element1 = y + array.coordinates[1];
var element2 = y + array.coordinates[3];
var element3 = y + array.coordinates[5];
var element4 = y + array.coordinates[7];
Console.WriteLine(trainingpatterns.array[element2, element6]);
However my loop requires me to go over the index. So when it gets to [5,4] for example the exception will be thrown.
What I want to do is if the x value goes out of bounds, for it to loop back to the start. So for example [5,4] will print [0,4] or [6,4] will print [2,4].
I have tried using a try catch but I cannot make the function universal for all values.
Thank you.
I suspect you just want to use the % operator:
int length0 = inputArray.GetUpperBound(0);
int length1 = inputArray.GetUpperBound(1);
...
var value = inputArray[x % length0, y % length1];
Note that this will not wrap negative numbers, however - the range of a % b is (-b, +b), whereas you want [0, +b). Taking account of this is a bit more longwinded, but let me know if you need it. If your index values will always be non-negative, you don't need to worry about it.

Sort String Array using Levenstein Algorithm results

I've been working on an Access file editor in C#, and i've been trying to get a search feature added to my program. So far, I have the database file populate a 2D array, which i then use to populate a ListView box in another window. From this new window, I would like to be able to search each entry by Model Number. So far, i've managed to incorporate the Levenstein Algorithm, which seems to have much use. I can get the algorithm to assign the distance value between each entry and the search keyboard, and assign that value to another integer array. I can also sort the results in increasing order.
However, my current problem is that i'd would like to have the Model numbers sorted with the same respect to the distance values from the Levenstein Algorithm, so that the most relevant result becomes the first choice in the ListView box. Any ideas anyone??!?!
Here's what i've got so far:
private void OnSearch(object sender, System.EventArgs e)
{
string a;
string b;
int[] result = new int[1000];
int[] sorted = new int[1000];
for (int i = 0; i < rowC; i++)
{
a = PartNum[i]; // Array to search
b = SearchBox1.Text; // keyword to search with
if (GetDistance(a, b) == 0)
{
return;
}
result[i] = GetDistance(a, b); //add each distance result into array
}
int index;
int x;
for (int j = 1; j < rowC; j++) //quick insertion sort
{
index = result[j];
x = j;
while ((x > 0) && (result[x - 1] > index))
{
result[x] = result[x - 1];
x = x - 1;
}
result[x] = index;
}
}
public static int GetDistance(string s, string t)
{
if (String.IsNullOrEmpty(s) || String.IsNullOrEmpty(t))
{
MessageBox.Show("Please enter something to search!!");
return 0;
}
int n = s.Length;
int m = t.Length;
if (n == 0)
{
return m;
}
else if (m == 0)
{
return n;
}
int[] p = new int[n + 1];
int[] d = new int[n + 1];
int[] _d;
char t_j;
int cost;
for (int i = 0; i <= n; i++)
{
p[i] = i;
}
for (int j = 1; j <= m; j++)
{
t_j = t[j - 1];
d[0] = j;
for (int i = 1; i <= n; i++)
{
cost = (s[i - 1] == t_j) ? 0 : 1;
d[i] = Math.Min(Math.Min(d[i - 1] + 1, p[i] + 1), p[i - 1] + cost);
}
_d = p;
p = d;
d = _d;
}
return p[n];
}
Do you have LINQ available to you? If so:
var ordered = PartNum.OrderBy(x => GetDistance(x, SearchBox1.Text))
.ToList();
// Do whatever with the ordered list
Note that this has the disadvantage of not aborting early if you find an exact match, as well as not making the actual distances available - but it's not entirely clear how you're using the results anyway...
Another option would be:
var ordered = (from word in PartNum
let distance = GetDistance(word, SearchBox1.Text))
orderby distance
select new { word, distance }).ToList();
Then you've got the distance as well.
In order to sort your array by Levenstein distance you need to include the model numbers as part of your array so that, when you sort the array by Levenstein number, the model numbers will go along for the ride.
To do this, create a class representing each part:
public class Part
{
public string PartNumber;
public int LevensteinDistance;
}
and then create an array of Part:
Part[] parts;
You can then reference each element like so:
parts[n].LevensteinDistance
parts[n].PartNumber

Categories