I heard about Counting Sort and wrote my version of it based on what I understood.
public void my_counting_sort(int[] arr)
{
int range = 100;
int[] count = new int[range];
for (int i = 0; i < arr.Length; i++) count[arr[i]]++;
int index = 0;
for (int i = 0; i < count.Length; i++)
{
while (count[i] != 0)
{
arr[index++] = i;
count[i]--;
}
}
}
The above code works perfectly.
However, the algorithm given in CLRS is different. Below is my implementation
public int[] counting_sort(int[] arr)
{
int k = 100;
int[] count = new int[k + 1];
for (int i = 0; i < arr.Length; i++)
count[arr[i]]++;
for (int i = 1; i <= k; i++)
count[i] = count[i] + count[i - 1];
int[] b = new int[arr.Length];
for (int i = arr.Length - 1; i >= 0; i--)
{
b[count[arr[i]]] = arr[i];
count[arr[i]]--;
}
return b;
}
I've directly translated this from pseudocode to C#. The code doesn't work and I get an IndexOutOfRange Exception.
So my questions are:
What's wrong with the second piece of code ?
What's the difference algorithm wise between my naive implementation and the one given in the book ?
The problem with your version is that it won't work if the elements have satellite data.
CLRS version would work and it's stable.
EDIT:
Here's an implementation of the CLRS version in Python, which sorts pairs (key, value) by key:
def sort(a):
B = 101
count = [0] * B
for (k, v) in a:
count[k] += 1
for i in range(1, B):
count[i] += count[i-1]
b = [None] * len(a)
for i in range(len(a) - 1, -1, -1):
(k, v) = a[i]
count[k] -= 1
b[count[k]] = a[i]
return b
>>> print sort([(3,'b'),(2,'a'),(3,'l'),(1,'s'),(1,'t'),(3,'e')])
[(1, 's'), (1, 't'), (2, 'a'), (3, 'b'), (3, 'l'), (3, 'e')]
It should be
b[count[arr[i]]-1] = arr[i];
I'll leave it to you to track down why ;-).
I don't think they perform any differently. The second just pushes the correlation of counts out of the loop so that it's simplified a bit within the final loop. That's not necessary as far as I'm concerned. Your way is just as straightforward and probably more readable. In fact (I don't know about C# since I'm a Java guy) I would expect that you could replace that inner while-loop with a library array fill; something like this:
for (int i = 0; i < count.Length; i++)
{
arrayFill(arr, index, count[i], i);
index += count[i];
}
In Java the method is java.util.Arrays.fill(...).
The problem is that you have hard-coded the length of the array that you are using to 100. The length of the array should be m + 1 where m is the maximum element on the original array. This is the first reason that you would think using counting-sort, if you have information about the elements of the array are all minor that some constant and it would work great.
Related
I wanted to use the recursive version of Heap's algorithm in order to get all permutations of a sequence of natural numbers from 1 to k inclusive, but ran into certain difficulties.
For k = 3, the program outputs 123, 213, 312, 132, but for some reason it does not take 231 and 321 into account. More specifically, according to the video with the implementation of the JavaScript version of the algorithm (https://www.youtube.com/watch?v=xghJNlMibX4), by the fifth permutation k should become equal to 3 (changing in the loop). I don't understand why in my case it reaches 1, and the loop stops executing.
int i, n, temp;
int[] a;
string str = "";
private void button1_Click(object sender, EventArgs e)
{
k = int.Parse(textBox1.Text);
a = new int[k];
for (i = 1; i <= k; i++)
a[i - 1] = i;
Generate(a, k);
}
private void Generate(int[] a, int k)
{
if (k == 1)
{
foreach (int digit in a)
str += digit.ToString();
listBox1.Items.Add(str);
str = "";
return;
}
Generate(a, k - 1);
for (i = 0; i < k - 1; i++)
{
if (k % 2 == 1) Swap(a, 0, k - 1);
else Swap(a, i, k - 1);
Generate(a, k - 1);
}
}
public void Swap(int[] a, int i, int j)
{
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
I focused on a variant of the algorithm found on the Wiki: https://en.wikipedia.org/wiki/Heap%27s_algorithm. Interestingly, the almost identical one which I took from here: https://www.geeksforgeeks.org/heaps-algorithm-for-generating-permutations/ works correctly.
It looks like I haven't been able to rewrite it correctly from a console application for forms.
I can try that version without recursion, but I still want to find out what my mistake was when building a recursive algorithm.
The problem is that your loop variable i is one global variable. This means that when you make a recursive call inside the loop's body, that recursion will alter the value of that loop variable. When the recursion comes back from where it was initiated, i will no longer have the same value, and the loop will exit prematurely.
So change:
for (i = 0; i < k - 1; i++)
to:
for (int i = 0; i < k - 1; i++)
It is good practice to avoid global variables, and to declare them with the smallest scope possible, there where you need them.
I'm trying to solve the below problem in C# which I was unable to answer within the time limit during a technical interview.
The provided code contains a bug and it can only be fixed by amending 2 lines of code at most.
The function takes 2 integer arrays as parameters.
All integers within both parameters will always be positive integers.
There may be multiple occurrences of the same integer in each array parameter.
The function should return the lowest positive integer that exists in both arrays.
The function should return -1 if no such integer exists
public int test(int[] A, int[] B)
{
int m = A.Length;
int n = B.Length;
Array.Sort(A);
Array.Sort(B);
int i = 0;
for (int k = 0; k < m; k++)
{
if (i < n - 1 && B[i] < A[k])
i += 1;
if (A[k] == B[i])
return A[k];
}
return -1;
}
I'm struggling to come up with a solution that only amends 1-2 lines of code. I thought I could replace i += 1; with i += 1; k = 0; but this is obviously adding a new line.
The original code will work for some inputs but not something like the below example because we don't want to increase k when B[i] < A[k]:
int[] A = { 3, 4, 5, 6 };
int[] B = { 2, 2, 2, 3 ,5 };
Considering you can only amend the code and not add new lines to it, I believe the following should be working:
public int test(int[] A, int[] B)
{
int m = A.Length;
int n = B.Length;
Array.Sort(A);
Array.Sort(B);
int i = 0;
for (int k = 0; k < m; k++)
{
while (i < n - 1 && B[i] < A[k])
{
i += 1;
}
if (A[k] == B[i])
return A[k];
}
return -1;
}
What changed is that the if that was checking for i is now a while
It's not exactly the prettiest code, but since those are the requirements...
I have a float array containing 1M floats
I want to do sampling: for each 4 floats I want to take only 1. So i am doing this :
for(int i = 0; i< floatArray.Length; i++) {
if(i % 4 == 0) {
resultFloat.Add(floatArray[i])
}
}
This works fine, but it takes much time to run through all the elements , is there any other methods to make it with better results (if there are any)
I can see two factors that might be slowing down performance.
As you have already been offered, you should set the step to 4:
for (int i = 0; i < floatArray.Length; i += 4)
{
resultFloat.Add(floatArray[i]);
}
Looks like resultFloat is a list of float. I suggest to use array instead of list, like this:
int m = (floatArray.Length + 3) / 4;
float[] resultFloat = new float[m];
for (int i = 0, k = 0; i < floatArray.Length; i += 4, k++)
{
resultFloat[k] = floatArray[i];
}
Just increment your loop by 4 each iteration instead of by 1:
for(int i = 0; i< floatArray.Length; i+=4)
{
resultFloat.Add(floatArray[i]);
}
If you really have an issue with performance, then you'd be even better off not using a dynamic container for the results, but a statically sized array.
float[] resultFloat = new float[(floatArray.Length + 3) >> 2];
for(int i = 0; i < resultFloat.Length; i++)
resultFloat[i] = floatArray[i << 2];
Usually performance isn't an issue thow, and you shouldn't optimize until a profiler gave you proof that you should. In all other cases the more readable code is preferrable.
Just to add another option, if you want this to be the fastest, use Parallel.For instead of a normal for loop.
int resultLength = (floatArray.Length + 3) / 4;
var resultFloat = new float[resultLength];
Parallel.For(0, resultLength, i =>
{
resultFloat[i] = floatArray[i * 4];
});
List<decimal> list = new List<decimal>();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
list.Add(5);
list.Add(6);
list.Add(7);
list.Add(8);
list.Add(9);
list.Add(10);
list.Add(11);
list.Add(12);
list.Add(13);
list.Add(14);
list.Add(15);
list.Add(16);
var sampleData = list.Where((x, i) => (i + 1) % (4) == 0).ToList();
I'm new here and sorry If my question is stupid, but I really need you help.
I need to sort that two dimensional string array by id (the first column):
string [,] a = new string [,]
{
{"2","Pena","pena"},
{"1","Kon","kon"},
{"5","Sopol","sopol"},
{"4","Pastet","pastet"},
{"7","Kuche","kuche"}
};
The problem is that I'm sorting only the number and I want after them to sort the words. That's what I did so far
static void Main(string[] args)
{
string [,] a = new string [,]
{
{"2","Pena","pena"},
{"1","Kon","kon"},
{"5","Sopol","sopol"},
{"4","Pastet","pastet"},
{"7","Kuche","kuche"}
};
int b = a.GetLength(0);
Console.WriteLine(b);
Console.WriteLine(a[0,0]);
Console.WriteLine(a[0,1]);
Console.WriteLine(a[1,0]);
InsertionSort(a, b);
Console.WriteLine();
Console.Write("Sorted Array: ");
printArray(a);
Console.WriteLine();
Console.Write("Press any key to close");
Console.ReadKey();
}
public static void InsertionSort(string[,] iNumbers, int iArraySize)
{
int i, j, index;
for (i = 1; i < iArraySize; i++)
{
for (int k = 0; k < iNumbers.GetLength(1); k++)
{
index = Convert.ToInt32(iNumbers[i, 0]);
j = i;
while ((j > 0) && (Convert.ToInt32(iNumbers[j - 1, 0]) > index))
{
iNumbers[j, k] = iNumbers[j - 1, k];
j = j - 1;
}
iNumbers[j, 0] = Convert.ToString(index);
}
}
}
static void printArray(string[,] iNumbers)
{
for (int i = 0; i < iNumbers.GetLength(0); i++)
{
for (int k = 0; k < iNumbers.GetLength(1); k++)
{
Console.Write(iNumbers[i, k] + " ");
}
}
Console.WriteLine();
}
Unfortunatelly as output I get
1 Pena pena 2 Kon kon 4 Sopol sopol 5 Pastet pastet 7 Kuche kuche
I would be really grateful if you could help me.
Based on the nature of the example and the question, I am guessing that this is a homework assignment and so must be implemented in a fashion that is a) not far from your current example, and b) actually demonstrates an insertion sort.
With that in mind, the following is a corrected version of your example that works:
public static void InsertionSort(string[,] iNumbers, int iArraySize)
{
int i, j, index;
for (i = 1; i < iArraySize; i++)
{
index = Convert.ToInt32(iNumbers[i, 0]);
j = i;
while ((j > 0) && (Convert.ToInt32(iNumbers[j - 1, 0]) > index))
{
for (int k = 0; k < iNumbers.GetLength(1); k++)
{
string temp = iNumbers[j, k];
iNumbers[j, k] = iNumbers[j - 1, k];
iNumbers[j - 1, k] = temp;
}
j = j - 1;
}
}
}
I made two key changes to your original code:
I rearranged the k and j loops so that the k loop is the inner-most loop, rather than the j loop. Your j loop is the one performing the actual sort, while the k loop is what should be actually moving a row for an insertion operation.
In your original example, you had this reversed, with the result that by the time you went to sort anything except the index element of a row, everything looked sorted to the code (because it's only comparing the index element) and so nothing else got moved.
With the above example, the insertion point is determined first, and then the k loop is used simply to do the actual insertion.
I added logic to actually swap the elements. In your original code, there wasn't really a swap there. You had hard-coded the second part of a swap, simply copying the index element to the target, so the swap did work for the index element. But it wouldn't have achieved the swap for any other element; instead, you'd just have overwritten data.
With the above, a proper, traditional swap is used: one of the values to be swapped is copied to a temp local variable, the other value to be swapped is copied to the location of the first value, and then finally the saved value is copied to the location of the second.
The above should be good enough to get you back on track with your assignment. However, I will mention that you can get rid of the k loop altogether if your teacher will allow you to implement this using jagged arrays (i.e. a single-dimensional array containing several other single-dimensional arrays), or by using a second "index array" (i.e. where you swap the indexes relative to the original array, but leave the original array untouched).
What are alternatives to this method
tmp = c[0];
c[0] = c[1];
c[1] = c[2];
c[2] = c[3];
c[3] = tmp;
to left rotate a char array with 4 elements
Using generics and rotating in place (thanks Jon Skeet for the suggestion):
static void Rotate<T>(T[] source)
{
var temp = source[0];
Array.Copy(source, 1, source, 0, source.Length - 1);
source[source.Length - 1] = temp;
}
These should work for any array of at least 2 length, and on any array.
If performance is critical and the arrays are always small, use this:
static void Rotate<T>(T[] source)
{
var temp = source[0];
for (int i = 0; i < source.Length - 1; i++)
source[i] = source[i + 1];
source[source.Length - 1] = temp;
}
The first method is the fastest with large arrays, but for 4 items, this one's almost as fast as your example method.
An alterantive to rotating the array, is to rotate the index when accessing the array, i.e you are creating a virtual ring
int origin = someValue;
int x = c[(i + origin) % c.Length];
I'm not sure if you're asking for a more efficient method or for an easier way to type that, but i'm going to try answering you assuming you want an easier way
so try:
int temp = c[0]
for(int i = 0; i < c.count; i++)
{
if (i == (c.count - 1))
{
c[i] = temp;
break;
}
c[i] = c[i + 1];
}
Do the job in single step.
Using System.Linq;
int[] ar = { 1,2,3,4,5};
int k = 1; //
int[] ar1= ar.Skip(k) // Start with the last elements
.Concat(ar.Take(k)) // Then the first elements
.ToArray();
Output-- 2,3,4,5,1
In ruby rotating array can be done in one line.
def array_rotate(arr)
i, j = arr.length - 1, 0
arr[j],arr[i], i, j = arr[i], arr[j], i - 1, j + 1 while(j<arr.length/2)
puts "#{arr}"
end