Why I get index out of range? - c#

So I have a List with 9 elements inside but I get an index oute of range error when I am trying to Add the array[4] element in the "right" List. Can someone tell me what's wrong?
public static int dosomething(ref List<int> array, int n)
{
List<int> left = new List<int>();
List<int> right = new List<int>();
for (int i = 0; i < n; i++)
{
if (i < n/2)
{
left.Add(array[i]);
Console.WriteLine("Left[{0}] = {1}", i, left[i]);
}
else
{
Console.WriteLine("i = {0}", i);
right.Add(array[i]);
Console.WriteLine("Right[{0}] = {1}", i, right[i]);
}
}
}

You're using the wrong index for left and right. Since you're iterating through the array, and adding to left some of the time and right the rest of the time, you can't use i for the index into those to retrieve values. The error is actually happening in your Console.WriteLine() calls.
Instead, you can use:
left[left.Count - 1];
or:
right[right.Count - 1];

Related

c# implementing a bucket sort algorithm

Good evening everyone here! I created a bucket sort algorithm, but it throws me an error that index is out of range. Could you please tell me where is the problem? I can't find the solution by myself, that's why I'm asking for your help
public int[] Sort(int[] unsortedSequence)
{
List<List<int>> buckets = new List<List<int>>();
InitializeBuckets(buckets);
Scatter(unsortedSequence, buckets);
int i = 0;
foreach (List<int> bucket in buckets)
{
int[] arr = bucket.ToArray();
InsertionSort(arr);
foreach (int d in arr)
{
unsortedSequence[i++] = d;
}
}
return unsortedSequence;
}
private static void Scatter(int[] array, List<List<int>> buckets)
{
foreach (int value in array)
{
int bucketNumber = GetBucketNumber(value);
buckets[bucketNumber].Add(value);
}
}
private static void InsertionSort(int[] array)
{
int j;
int temp;
for (int i = 1; i < array.Length; i++)
{
j = i;
while (j > 0 && array[j] < array[j - 1])
{
temp = array[j];
array[j] = array[j - 1];
array[j - 1] = temp;
j--;
}
}
}
private static int GetBucketNumber(int value)
{
int val = value * 10;
return val;
}
private static void InitializeBuckets(List<List<int>> buckets)
{
for (int i = 0; i < 10; i++)
{
List<int> a = new List<int>();
buckets.Add(a);
}
}
I am not sure what logic you did for sorting this but I got why you are getting index out of range error.
Error in Code
You are creating 10 buckets and now you are trying to generate bucket number by multiplying current value or array with 10.
For example, if your current value of array is 2 then generated bucket number will be 20. You got only 10 buckets so Scatter() method will give you error.
private static void Scatter(int[] array, List<List<int>> buckets)
{
foreach (int value in array)
{
int bucketNumber = GetBucketNumber(value);
buckets[bucketNumber].Add(value); // ERROR HERE
}
}
SOLUTION
Actually, there is problem with GetBucketNumber() method. You should use remainder not multiplication. Change method with following.
private static int GetBucketNumber(int value)
{
int val = value % 10;
return val;
}
You must do
Try to solve your problem with hard attempts before you ask for help. Run your program on paper first I mean confirm your logic before you start coding. Have faith in you and give enough time to your attempts. Enjoy coding.
Before I answer, I want to strongly suggest that you always make a good faith attempt at solving a problem first before seeking outside help. I don't necessarily think you didn't try, but this problem was easily identified by stepping through the debugger.
If that's an aspect of coding you're not too familiar with, I strongly recommend making it a priority to learn - it will only make you a better developer in the long run.
The problem is occurring in the Scatter method at this point:
int bucketNumber = GetBucketNumber(value);
buckets[bucketNumber].Add(value);
The exception occurs because GetBucketNumber multiplies the input by 10, but you're using that multiplied value as the index for buckets.

C#, how to save frequency of elements from one array in another, two-dimensional array?

So here's my problematic code. When I try to pass an array with N arguments, let's say {2,1,2,2,5} in result I want to get two-dimensional secArray[element,frequency of the element]. The problem is I get more than that and in this particular case I get an array like this:
23
11
22
21
52
Console.WriteLine("Enter number of elements: ");
int n = int.Parse(Console.ReadLine());
int[] array = new int[n];
for (int i = 0; i < array.Length; i++)
{
Console.Write("Array[{0}]: ", i);
array[i] = int.Parse(Console.ReadLine());
}
//problematic code begins
int[,] secArray = new int[n,2];
for(int i = 0;i<n;i++)
{
for(int j = 0; j<n;j++)
{
if(array[i] == secArray[j,0])
{
secArray[j, 1] += 1;
}
else
{
secArray[i, 0] = array[i];
secArray[i, 1] = 1;
}
}
}
//problematic code ends
//printing - works good
Console.WriteLine("How many same elements?");
for (int row = 0; row < secArray.GetLength(0); row++)
{
for (int col = 0; col < secArray.GetLength(1); col++)
{
Console.Write(secArray[row, col]);
}
Console.WriteLine();
}
If anyone has a clue how to fix this I'll be really grateful. It frustrates me that I don't know where the actual problem lies.
The first problem concerns the very first statement.
int[,] secArray = new int[n,2];
You don't know how many unique elements you have in your array until you traverse it. You can't use n, because n is the total number of arguments, which can be greater than the number of unique elements.
Next, the nested for loops are very inefficient. Your algorithm traverses the array for every element in the array- so it will run in O(n^2) time.
Think: do you have to traverse the array more than once? Why not just use a hashtable (dictionary in C#) to keep track of counts as you traverse the array? A hashtable uses a very efficient lookup mechanism to tell you if you've already seen the element, and the value can be used to keep track of count.
Consider replacing your problematic code with the following, and understanding how it works.
Dictionary<int, int> elementCounts = new Dictionary<int, int>();
for(int i = 0; i < n; i++)
{
int element = array[i];
if (elementCounts.ContainsKey(element))
elementCounts[element]++;
else
elementCounts.Add(element, 1);
}
Console.WriteLine("How many same elements?");
foreach(KeyValuePair<int,int> count in elementCounts)
{
Console.WriteLine("Element: {0} Count: {1}", count.Key, count.Value);
}
Then, if you want to copy the results in the hashtable (Dictionary) to a two-dimensional array, you can do the following.
int numberOfUniqueElements = elementCounts.Count;
int[,] secArray = new int[numberOfUniqueElements, 2];
int j = 0;
foreach (KeyValuePair<int, int> count in elementCounts)
{
secArray[j, 0] = count.Key;
secArray[j, 1] = count.Value;
j++;
}
I would use Linq's GroupBy to do this
var array = new int[] { 2, 1, 2, 2, 5 };
var result = array.GroupBy(x => x).Select(x => new[] { x.Key, x.Count() }).ToArray();
Why don't you use a hash table. Let the number in the array be the hash entry key, and let the value of the hash entry be the count. Then just iterate through the array once. While iterating through the array check if hash entry exists if so add 1 to it, if not create it.
Something like
for(int i = 0; i<n;i++) {
if(hashTable.containsKey(array[i])) {
hashTable[array[i]]++];
} else {
hashTable.add(array[i],1);
}
}
Please note that this is quedocode and will require to lookup the methods and implement it correctly.

Counting sort in singly-linked list C#

Is there any way to make a counting sort in singly-linked list? I haven't seen any examples and it's quite hard to make it without them. I have example of it in array and would like to do it in singly-linked list.
Has anybody did it in singly-linked list?
public static int[] CountingSortArray(int[] array)
{
int[] aux = new int[array.Length];
// find the smallest and the largest value
int min = array[0];
int max = array[0];
for (int i = 1; i < array.Length; i++)
{
if (array[i] < min) min = array[i];
else if (array[i] > max) max = array[i];
}
int[] counts = new int[max - min + 1];
for (int i = 0; i < array.Length; i++)
{
counts[array[i] - min]++;
}
counts[0]--;
for (int i = 1; i < counts.Length; i++)
{
counts[i] = counts[i] + counts[i - 1];
}
for (int i = array.Length - 1; i >= 0; i--)
{
aux[counts[array[i] - min]--] = array[i];
}
return aux;
}
I found one that works on an array at: http://www.geeksforgeeks.org/counting-sort/
I think with minimal effort it could be changed to a linked list, the only problem is that you'll end up traversing the linked list many many times since you don't have random access eg.[] making it rather inefficient. Since you seem to have found the same thing i did before I could finish typing I think my answer is kinda pointless. However, I'm still a bit curious as to where you're having problems.
Heres a hint if figuring out where to start is the problem: Every time you see array[i] used, you will need to traverse your linked list first instead to get the i'th item first.
Edit: The only reason you would need to create a 2nd linked list of frequencies is if you needed to actually do work on the resulting linked list. If you just need a sorted list of the values inside the linked list for display purposes an array holding the frequencies would work (i suppose at the same time you could just create an array of all the values then do the counting sort you already have on it). I apologize if i have confused my c, c++, c++/cx, somewhere along the way (i don't have a compiler handy right now), but this should give you a good idea of how to do it.
public static node* FindMin(node* root){ //FindMax would be nearly identical
node* minValue = root;
while(node->Next){
if(node->Value < minValue->Value)
minValue = node;
}
return minValue;
}
public static node* CountingSortArray(node* linklist){
node* root = linkedlist
node* min = FindMin(linklist);
node* max = FindMax(linklist);
int[] counts = new int[max->Value - min->Value + 1];
while(root != NULL){
counts[root->Value] += 1;
root = root->Next;
}
int i = 0;
root = linkedlist;
while(ptr != NULL){
if(counts[i] == 0)
++i;
else{
root->Value = i;
--count[i];
root = root->Next;
}
}
}
void push(node** head, int new_data){
node* newNode = new node();
newNode->Value = new_data;
newNode->Next = (*head);
(*head) = newNode;
}
void printList(node* root){
while(root != NULL){
printf(%d ", root->Value);
root = root->Next;
}
printf("\n");
}
int main(void){
node* myLinkedList = NULL;
push(&head, 0);
push(&head, 1);
push(&head, 0);
push(&head, 2);
push(&head, 0);
push(&head, 2);
printList(myLinkedList);
CountingSortArray(myLinkedList);
printList(myLinkedList);
}
The example code is more like a radix sort with base (max-min+1). Usually a counting sort looks like the code below. Make a pass over the list to get min and max. Make a second pass to generate the counts. Make a pass over the counts to generate a new array based on the counts (instead of copying data). Example code fragment:
for (size_t i = 0; i < array.Length; i++)
counts[array[i]-min]++;
size_t i = 0;
for(size_t j = 0; j < counts.Length); j++){
for(size_t n = counts[j]; n; n--){
aux[i++] = j+min;
}
}

c# - Binary search algorithm random generated array items not working

I have implemented binary search algorithm in a console window application in C#. I am generating random values to the array and sorting them using Random() and Array.Sort() functions respectively.
The Problem - No matter what Key(item to be searched in the array) I give, the program is returning Key not found when the array items are generated using Random function
This does not happen if I enter the array elements manually using Console.ReadLine().
TLDR: Binary Search algorithm works fine when array items are entered manually, but does not work when array items are generated using Random function.
Can anyone point out what is the mistake I am doing?
My code - Random Generated array items.
namespace BSA
{
class Program
{
static void Main(string[] args)
{
var arr = new int[10];
Random rnd = new Random();
for (int i = 0; i < arr.Length; i++)
{
arr[i] = rnd.Next(1, 1000);
}
Array.Sort(arr);
for (int i = 0; i < arr.Length; i++)
{
Console.Write("{0}\n", i);
}
while (true)
{
Console.WriteLine("Enter the number to be searched in the array.");
var searchItem = Convert.ToInt32(Console.ReadLine());
var foundPos = Search(arr, searchItem);
if (foundPos > 0)
{
Console.WriteLine("Key {0} found at position {1}", searchItem, foundPos);
}
else
{
Console.WriteLine("Key {0} not found", searchItem);
}
}
}
public static int Search(int[] arr, int item)
{
var min = 0;
var N = arr.Length;
var max = N - 1;
int basicOperations = 0;
basicOperations++;
do
{
var mid = (min + max)/2;
if (arr[mid] == item)
return mid;
if (item < arr[mid])
max = mid - 1;
else
min = mid + 1;
basicOperations++;
} while (min <= max);
return basicOperations;
}
}
}
Please let me know if I am doing any silly mistake or I am committing a blunder in the above code. Any help would be really helpful.
Your search code works fine as far as I can see. However when you list the contents of the random array, you should write arr[i] rather than i to see what's in the array so you can pick a search value in it. Alternatively, pass arr[x] as the search item. It should return x.
Your code works correctly. You're just not looking for the right keys. The function that prints the values generated into the array prints the loop counter instead:
for (int i = 0; i < arr.Length; i++)
{
Console.Write("{0}\n", i);
}
You need to change it to:
for (int i = 0; i < arr.Length; i++)
{
Console.Write("{0}\n", arr[i]);
}
This will show you the values actually generated.
Comment too short for this so added answer to show how to set basicOperations and still return search position. You declare basicOperations as an out parameter which means the method can change it so the caller can see it when method returns.
public static void Main(string[] args)
{
... ... ...
int basicOperations;
int searchPos = IntArrayBinarySearch(arr, arr[5], out basicOperations);
Console.WriteLine("Found at {0} basic ops={1}", searchPos, basicOperations);
}
public static int IntArrayBinarySearch(int[] data, int item, out int basicOperations)
{
var min = 0;
var N = data.Length;
var max = N - 1;
basicOperations = 0;
basicOperations++;
and at bottom, you don't need to return out parameters, just return -1 to indicate failure as you did before
return -1;

How to multiply all values in an array?

I have an assignment where I need to find the product of all of the numbers in an array, I'm not sure how to do this.
int[] numbers = new int[SIZE];
Console.WriteLine("Type in 10 numbers");
Console.WriteLine("To stop, type in 0");
for (int input = 0; input < SIZE; input++)
{
userInput = Console.ReadLine();
numberInputed = int.Parse(userInput);
if (numberInputed == ZERO)
{
numberInputed = ONE;
break;
}
else
{
numbers[input] = numberInputed;
}
}
This is where I'm trying to find the product of all of the numbers in the array.
foreach (int value in numbers)
{
prod *= value;
}
Console.WriteLine("The product of the values you entered is {0}", prod);
What am I doing wrong in the foreach statement? Thanks in advance
Edit, left out my declared values
const int SIZE = 10;
const int ZERO = 0;
string userInput;
int numberInputed;
int prod = 1;
It now works when I type in all ten values but if I put a 0 in order to break the loop then everything equals 0. How do I prevent a 0 from being entered into the array?
It's possible you initialize prod to 0, which means no matter what numbers are in your array, prod will remain 0. Make sure you initialize it to 1 to get the correct result:
int prod = 1;
foreach (int value in numbers)
{
prod *= value;
}
You could also use Linq's Aggregate extension method to do the same thing:
using System.Linq; // put with other using directives
int prod = numbers.Aggregate(1, (a, b) => a * b);
Update
The real problem (which I failed to notice before) is that your array isn't being fully populated if you break out of your loop early. So any array entries you didn't set are still initialized to 0. To fix this, use a List<int> instead of an int[]:
using System.Collections.Generic; // put with other using directives
List<int> numbers = new List<int>(SIZE); // Capacity == SIZE
...
for (int input = 0; input < SIZE; input++)
{
...
if (numberInputed == ZERO)
{
break;
}
else
{
numbers.Add(numberInputed);
}
}
The problem is that you don't keep track of how many items there are in the array that actually are assigned a value. If you exit from the loop using a zero input, then the rest of the items are unchanged. As they are zero by default, you will be using those zeroes in your second loop, and when you have a zero somewhere in the array, the total product becomes zero.
Keep track of how many items there are by keeping the loop variable outside the loop:
int input = 0;
while (input < SIZE)
{
userInput = Console.ReadLine();
numberInputed = int.Parse(userInput);
if (numberInputed == ZERO) {
break;
}
numbers[input] = numberInputed;
input++;
}
Now you can use only the items that are actually assigned:
for (int i = 0; i < input; i++) {
prod *= numbers[i];
}
Multiply all numbers inside an Array
int[] array = { 1, 2, 3, 4, 5 };
int sum = array[0];
for (int i = 1; i != array.Length; i++)
{
sum *= array[i];
}
If your array is somehow populated with zeroes (0), then use List instead of an array.

Categories

Resources