Count number of comparison made by HeapSort in C# - c#

I would like to know how I can count the number of the comparisons made by the HeapSort I got on rosettacode? I tried to count it by adding a variable and each time the comparison method gets called this variable gets incremented. But somehow I dont get the right results. I think I have to override the comparison method somehow and use a getter and setter to increment a count variable. A hint will be highly appreciated...
using System;
using System.Collections.Generic;
using System.Text;
public class Program
{
public static void HeapSort<T>(T[] array)
{
HeapSort<T>(array, 0, array.Length, Comparer<T>.Default);
}
public static void HeapSort<T>(T[] array, int offset, int length, IComparer<T> comparer)
{
HeapSort<T>(array, offset, length, comparer.Compare);
}
public static void HeapSort<T>(T[] array, int offset, int length, Comparison<T> comparison)
{
int count = 0;
// build binary heap from all items
for (int i = 0; i < length; i++)
{
int index = i;
T item = array[offset + i]; // use next item
// and move it on top, if greater than parent
while (index > 0 &&
comparison(array[offset + (index - 1) / 2], item) < 0)
{
int top = (index - 1) / 2;
array[offset + index] = array[offset + top];
index = top;
}
count++;
array[offset + index] = item;
//Console.WriteLine(item);
}
for (int i = length - 1; i > 0; i--)
{
// delete max and place it as last
T last = array[offset + i];
array[offset + i] = array[offset];
int index = 0;
// the last one positioned in the heap
while (index * 2 + 1 < i)
{
int left = index * 2 + 1, right = left + 1;
if (right < i && comparison(array[offset + left], array[offset + right]) < 0)
{
if (comparison(last, array[offset + right]) > 0)
{
break;
}
array[offset + index] = array[offset + right];
index = right;
//Console.WriteLine("1st if ");
}
else
{
if (comparison(last, array[offset + left]) > 0)
{
break;
}
count++;
array[offset + index] = array[offset + left];
index = left;
//Console.WriteLine("2nd if ");
}
}
array[offset + index] = last;
//Console.WriteLine("\nRun");
//for (int j = 0; j <= 3; j++)
// Console.WriteLine(array[j]);
}
Console.WriteLine("\nThe case needed " + count + " comparisons!");
}
static void Main()
{
// hardcoded arrays according to the assignment
int[] arrOne = { 503, 087, 512, 061, 908, 170, 897, 275, 653, 426, 154, 509, 612, 677, 765, 703 };
int[] arrTwo = { 908, 897, 765, 703, 677, 653, 612, 512, 509, 503, 426, 275, 170, 154, 087, 061 };
int[] arrThree = { 4, 7, 2, 3 };
int[] arrFour = { 0, 1, 0, 0, 1, 1, 1, 0, 1, 0 };
int n = 0;
string c = String.Empty;
// the application runs until the user agrees to quit at the end of a sorting run
do
{
// displays the 4 arrrays
Console.WriteLine("Assignment: Given are 4 different arrays; You have the choice which one you want to sort.");
Console.WriteLine("\n1. Knuths entry sequence:\n 503,087,512,061,908,170,897,275,653,426,154,509,612,677,765,703");
Console.WriteLine("\n2. Knuths entry sequence descended:\n 908,897,765,703,677,653,612,512,509,503,426,275,170,154,087,061");
Console.WriteLine("\n3. Just one number:\n 300");
Console.WriteLine("\n4. A set of 0 and 1:\n 0,1,0,0,1,1,1,0,1,0");
Console.WriteLine("\n Which array do you want to sort?");
n = Convert.ToInt32(Console.ReadLine());
// creating an comparer instance
//var comp = new CountingComparer<int>();
Console.Clear();
switch (n)
{
case 1:
HeapSort(arrOne);
DisplayArray(arrOne);
break;
case 2:
HeapSort(arrTwo);
DisplayArray(arrTwo);
break;
case 3:
HeapSort(arrThree);
DisplayArray(arrThree);
break;
case 4:
HeapSort(arrFour);
DisplayArray(arrFour);
break;
default:
Console.WriteLine("\nArray does not exist!");
break;
}
//Console.WriteLine("\nThe case needed " + comp.Count + " comparisons!");
Console.WriteLine("\nDo you want to quit the application? (y/n) ");
c = Console.ReadLine();
Console.Clear();
}
while (c != "y");
}
public static void DisplayArray(int[] arr)
{
Console.WriteLine("\nSorted Array!\n");
for (int i = 0; i < arr.Length; i++)
Console.WriteLine(" " + arr[i]);
}
}

I think doing the count in the compare method is a good idea. Here's a quick and dirty way:
public class Program
{
public static int Count = 0;
public static int MyCompare<T>(T first, second)
{
Count++;
return Comparer<T>.Default.Compare(first, second);
}
// Update your first sort to use the new compare.
public static void HeapSort<T>(T[] array)
{
HeapSort<T>(array, 0, array.Length, MyCompare);
}
// Now all of the rest of your original code inside of Program.
}
Set Count to 0 before calling the sorts, then read count after the sorting is done. I confirmed that on the first sort, it does get set to 85, like you expect.

Related

Sorting Neighborhoods by Population Using Heap

I am trying to sort the neighborhoods by their populations. I used heap sorting algorithm in C#. I created an Array which keeps the population of the neighborhoods named "arr". And created an array which keeps the name of the hoods . It works good but how can I get output of sorting with name of the neighborhoods?
My code is here:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace HoodSorting
{
public class example
{
static void heapSort(int[] arr, int n)
{
for (int i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i);
for (int i = n - 1; i >= 0; i--)
{
int temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
heapify(arr, i, 0);
}
}
static void heapify(int[] arr, int n, int i)
{
int largest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < n && arr[left] > arr[largest])
largest = left;
if (right < n && arr[right] > arr[largest])
largest = right;
if (largest != i)
{
int swap = arr[i];
arr[i] = arr[largest];
arr[largest] = swap;
heapify(arr, n, largest);
}
}
public static void Main()
{// arr REPRESENTS THE POUPLATION OF THE NEIGHBORHOODS
string[] neighborhoods = { "Bornova" ,"Westriver","Paradise","Goodman","McMountain","Rocker","Summerlin","Northcity","Greenhill","Sevenwaves"};
int[] arr = { 55, 25, 89, 34, 12, 19, 78, 95, 1, 100 };
int n = 10, i;
Console.WriteLine("Heap Sort");
Console.Write("Initial array is: ");
for (i = 0; i < n; i++)
{
Console.Write(arr[i] + " ");
}
heapSort(arr, 10);
Console.Write("\nSorted Array is: ");
for (i = 0; i < n; i++)
{
Console.Write(arr[i] + " ");
}
}
}
}
How can I get output like this:
Sorted Array is: Greenhill, McMountain,....,........, Northcity, Sevenwaves
Thanks a lot for the help
From an OOP perspective you would keep the two properties (name and population of a neighborhood) together in one object. Then when you sort the objects, you'll still have the associated data right there.
There are several ways to do this. For instance, you could create tuples.
Here is how that is applied to your code:
static void heapSort(Tuple<int, string>[] arr)
{
int n = arr.Length;
for (int i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i);
for (int i = n - 1; i >= 0; i--)
{
(arr[0], arr[i]) = (arr[i], arr[0]);
heapify(arr, i, 0);
}
}
static void heapify(Tuple<int, string>[] arr, int n, int i)
{
int largest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < n && arr[left].Item1 > arr[largest].Item1)
largest = left;
if (right < n && arr[right].Item1 > arr[largest].Item1)
largest = right;
if (largest != i)
{
(arr[i], arr[largest]) = (arr[largest], arr[i]);
heapify(arr, n, largest);
}
}
public static void Main()
{
Tuple<int, string>[] arr = {
Tuple.Create(55, "Bornova"),
Tuple.Create(25, "Westriver"),
Tuple.Create(89, "Paradise"),
Tuple.Create(34, "Goodman"),
Tuple.Create(12, "McMountain"),
Tuple.Create(19, "Rocker"),
Tuple.Create(78, "Summerlin"),
Tuple.Create(95, "Northcity"),
Tuple.Create(1, "Greenhill"),
Tuple.Create(100, "Sevenwaves")
};
Console.WriteLine("Initial array is: ");
foreach (var pair in arr)
{
Console.Write(pair.Item2 + " ");
}
Console.WriteLine();
heapSort(arr);
Console.WriteLine("Sorted Array is: ");
foreach (var pair in arr)
{
Console.Write(pair.Item2 + " ");
}
Console.WriteLine();
}

returns the smallest positive integer (greater than 0) that does not occur in Array

I have the following question:-
Write a function:
class Solution { public int solution(int[] A); }
that, given an array A of N integers, returns the smallest positive integer (greater than 0) that does not occur in A.
For example, given A = [1, 3, 6, 4, 1, 2], the function should return 5.
Given A = [1, 2, 3], the function should return 4.
Given A = [−1, −3], the function should return 1.
Write an efficient algorithm for the following assumptions:
N is an integer within the range [1..100,000];
each element of array A is an integer within the range [−1,000,000..1,000,000].
now i tried this code:-
using System;
// you can also use other imports, for example:
// using System.Collections.Generic;
// you can write to stdout for debugging purposes, e.g.
// Console.WriteLine("this is a debug message");
class Solution
{
public int solution(int[] A)
{
// write your code in C# 6.0 with .NET 4.5 (Mono)
int n = 1;
Array.Sort(A);
for (int i = 1; i <= 100000; i++)
{
for (int i2 = 0; i2 <= A.Length - 1; i2++)
{
if (A[i2] == i)
{
n = A[i2] + 1;
break;
}
}
}
return n;
}
}
where my code worked well for these test data:-
A = [1, 2, 3]
A = [−1, −3]
while failed for this one:-
A = [1, 3, 6, 4, 1, 2] where it return 7 instead of 5.
any advice why my code failed on the 3rd test?
Thanks
using System.Linq;
int smallestNumber = Enumerable.Range(1, 100000).Except(A).Min();
I would use following approach that uses a HashSet<int> to check if a given integer is missing:
public static int? SmallestMissing(int[] A, int rangeStart = 1, int rangeEnd = 100_000)
{
HashSet<int> hs = new HashSet<int>(A);
for (int i = rangeStart; i <= rangeEnd; i++)
if(!hs.Contains(i)) return i;
return null;
}
A HashSet is a collection if unique values and it's very efficient in lookup items(complexity is O(1)). So you get a very readable and efficient algorithm at the cost of some memory.
Maybe you could optimize it by providing another algorithm in case the array is very large, you don't want to risk an OutOfMemoryException:
public static int? SmallestMissing(int[] A, int rangeStart = 1, int rangeEnd = 100_000)
{
if(A.Length > 1_000_000)
{
Array.Sort(A);
for (int i = rangeStart; i <= rangeEnd; i++)
{
int index = Array.BinarySearch(A, i);
if(index < 0) return i;
}
return null;
}
HashSet<int> hs = new HashSet<int>(A);
for (int i = rangeStart; i <= rangeEnd; i++)
if(!hs.Contains(i)) return i;
return null;
}
If you're allowed to sort the array in-place, which means modifying the input parameter value, here's a simple linear probe for the missing value (on top of the sort of course).
Here's the pseudo-code:
Sort the array
Skip all negatives and 0's at the start
Loopify the following:
Expect 1, if not found at current location return 1
Skip all 1's
Expect 2, if not found at current location return 2
Skip all 2's
Expect 3, if not found at current location return 3
Skip all 3's
... and so on for 4, 5, 6, etc. until end of array
If we get here, return currently expected value which should've been at the end
Here's the code:
public static int FirstMissingValue(int[] input)
{
Array.Sort(input);
int index = 0;
// Skip negatives
while (index < input.Length && input[index] < 1)
index++;
int expected = 1;
while (index < input.Length)
{
if (input[index] > expected)
return expected;
// Skip number and all duplicates
while (index < input.Length && input[index] == expected)
index++;
expected++;
}
return expected;
}
Test-cases:
Console.WriteLine(FirstMissingValue(new[] { 1, 3, 6, 4, 1, 2 }));
Console.WriteLine(FirstMissingValue(new[] { 1, 2, 3 }));
Console.WriteLine(FirstMissingValue(new[] { -1, -3 }));
output:
5
4
1
Your alg won't work in case input array becomes like this: [1,2-1,1,3,5]. I did this based on your alg. Give it a try:
int[] a = new int[] { -1, -2};
IEnumerable<int> uniqueItems = a.Distinct<int>().Where(x => x > 0);
if (uniqueItems.Count() == 0)
{
Console.WriteLine("result: 1");
}
else
{
Array asList = uniqueItems.ToArray();
Array.Sort(asList);
for (int i = 1; i <= 100000; i++)
{
if ((int)asList.GetValue(i - 1) != i)
{
Console.WriteLine("result: " + i);
break;
}
}
}
you can try like this.
public static int solution(int[] A)
{
int smallest = -1;
Array.Sort(A);
if(A[0] > 1)
return 1;
for(int i = 0; i < A.Length; i++)
{
if(A.Length != i+1 && A[i] + 1 != A[i + 1] && A[i+1] > 0)
{
smallest = A[i]+1;
break;
}
else if(A[i] > 0 && A.Length == i+1)
{
smallest = A[i] + 1;
}
}
return smallest > 0 ? smallest:1;
}
Here's the approach that uses O(N) partitioning followed by an O(N) search. This approach does not use any additional storage, but it DOES change the contents of the array.
This code was converted from here. Also see this article.
I've added comments to try to explain how the second stage findSmallestMissing() works. I've not commented the partitioning method, since that's just a variant of a standard partition as might be used in a QuickSort algorithm.
static class Program
{
public static void Main()
{
Console.WriteLine(FindSmallestMissing(1, 3, 6, 4, 1, 2));
Console.WriteLine(FindSmallestMissing(1, 2, 3));
Console.WriteLine(FindSmallestMissing(-1, -3));
}
public static int FindSmallestMissing(params int[] array)
{
return findSmallestMissing(array, partition(array));
}
// Places all the values > 0 before any values <= 0,
// and returns the index of the first value <= 0.
// The values are unordered.
static int partition(int[] arr)
{
void swap(int x, int y)
{
var temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
int pIndex = 0; // Index of pivot.
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] > 0) // pivot is 0, hence "> 0"
swap(i, pIndex++);
}
return pIndex;
}
// This is the clever bit.
// We will use the +ve values in the array as flags to indicate that the number equal to that index is
// present in the array, by making the value negative if it is found in the array.
// This way we can store both the original number AND whether or not the number equal to that index is present
// in a single value.
//
// Given n numbers that are all > 0, find the smallest missing number as follows:
//
// For each array index i in (0..n):
// val = |arr[i]| - 1; // Subtract 1 so val will be between 0 and max +ve value in original array.
// if (val is in range) // If val beyond the end of the array we can ignore it
// and arr[val] is non-negative // If already negative, no need to make it negative.
// make arr[val] negative
//
// After that stage, we just need to find the first positive number in the array, which indicates that
// the number equal to that index + 1 is missing.
// n = number of values at the start of the array that are > 0
static int findSmallestMissing(int[] arr, int n)
{
for (int i = 0; i < n; i++)
{
int val = Math.Abs(arr[i]) - 1;
if (val < n && arr[val] >= 0)
arr[val] = -arr[val];
}
for (int i = 0; i < n; i++)
{
if (arr[i] > 0) // Missing number found.
return i + 1;
}
return n + 1; // No missing number found.
}
}
class Program
{
static void Main(string[] args)
{
int [] A = new int[] {1, 2, 3};
int n = 0;
bool found = false;
Array.Sort(A);
for (int i = 1; i <= 100000; i++) {
for (int x = 0; x <= A.Length - 1; x++) {
int next = (x + 1) < A.Length ? (x + 1): x;
if (A[x] > 0 && (A[next] - A[x]) > 0) {
n = A[x] + 1;
found = true;
break;
}
}
if(found) {
break;
}
}
Console.WriteLine("Smallest number: " + n);
}
}
int smallestNumber=Enumerable.Range(1,(int.Parse(A.Length.ToString())+1)).Except(A).Min();
Array.Sort(A);
for (int number = 1; number <= 100000; number++)
{
for (int num = number; i2 <= A.Length - 1; num++)
{
if (A[num] == number)
{
smallestNumber = A[num] + 1;
break;
}
}
}
return smallestNumber;
}
The easiest one :)
class Solution
{
public int solution(int[] array)
{
int[] onlyPositiveArray = array.Where(a => a > 0).OrderBy(a => a).Distinct().ToArray();
int smallestNumber = 1;
foreach (var number in onlyPositiveArray)
{
if (smallestNumber != number)
{
break;
}
smallestNumber ++;
}
if (!onlyPositiveArray.Contains(smallestNumber ))
{
return smallestNumber;
}
else
{
return smallestNumber + 1;
}
}
}
PHP Solution:
function solution($A) {
// write your code in PHP7.0
// sort array
sort($A);
// get the first
$smallest = $A[0];
// write while
while( in_array(($smallest),$A) || (($smallest) < 1 ) )
{
$smallest++;
}
return $smallest;
}
My solution, also if someone could test how performant it is?
public int solution(int[] N) {
if (N.Length == 0)
return 1;
else if (N.Length == 1)
return N[0] >= 0 ? N[0] + 1 : 1;
Array.Sort(N);
int min = Array.Find(N, IsUnderZero);
if (min ==
default)
return 1;
HashSet < int > hashSet = new HashSet < int > (N);
int max = N[N.Length - 1];
for (int i = min + 1; i <= max + 1; i++) {
if (!hashSet.Contains(i) && i > 0)
return i;
}
return max + 1;
bool IsUnderZero(int i) => i <= 0;
}
Try the below:
public static int MinIntegerGreaterThanZeroInArray(int[] A)
{
int minInt;
if (A.Length > 0)
{
Array.Sort(A);
for (minInt = 1; minInt <= A.Length; minInt++)
{
int index = Array.BinarySearch(A, minInt);
if (index < 0) return minInt;
}
return minInt;
}
//Array is empty.
throw new InvalidOperationException();
}
public static int Smallest(int[] A)
{
int maxPositiveInt = 1;
HashSet<int> NumDic = new HashSet<int>();
for (int i = 0; i < A.Length; i++)
{
if (A[i] <= 0)
{
continue;
}
if (!NumDic.Contains(A[i]))
{
NumDic.Add(A[i]);
}
maxPositiveInt = Math.Max(A[i], maxPositiveInt);
}
//All numbers are negative
if (NumDic.Count == 0)
{
return 1;
}
int smallestinteger = 1;
for (int i = 0; i < A.Length; i++)
{
if (A[i] <= 0)
{
continue;
}
if (!NumDic.Contains(smallestinteger))
{
return smallestinteger;
}
else
{
smallestinteger++;
}
}
return maxPositiveInt + 1;
}
static void Main(string[] args)
{
Console.WriteLine(solution(new int[]{1, 3, 6, 4, 1, 2}));
}
public static int solution(int[] A)
{
Array.Sort(A);
int smallest = A[0];
while (A.Contains(smallest+1)|| (smallest+1)<1)
{
smallest++;
}
return smallest +1;
}

C# money exchange algorithm

I need to determine the given input into all possible banknote combinations.
int[] currency = new int[] { 5, 10, 20, 50, 100, 200, 500 };
int total = 20; // result is { {5,5,5,5} {5,5,10} {10,10} {20} }
int[][] result = GetCombinations(total, 0, currency); // should return the 4 combinations
Here is what I've tried so far.
public static int GetCombinations(int total, int index, int[] list)
{
total = total - list[index];
if (total < 0)
{
return 0;
}
else if (total == 0)
{
return 1;
}
else
{
return 1 + GetCombinations(total, index + 1, list);
}
}
QUESTION for Bounty:
I need a way to get all combinations - not just the count.
You are only calculating {5}, {5, 10}.
You are calculating "How many different coins can use if the cost <= 20?".
So, you have to count for this algorithm.
The correct code is:
public static int GetCombinations(int total, int index, int[] list)
{
if (total == 0)
{
return 1;
}
if(index == list.Length) {
return 0;
}
int ret = 0;
for(; total >= 0; total -= list[index])
{
ret += GetCombinations(total, index + 1, list);
}
return ret;
}
If you want to calculate the number of combinations, you can also solve dynamic programming and memorize for dp[total][index], because GetCombinations(total, index, list) value is same if total and index is same.
EDIT:
If you want ALL combinations, you can do like this:
using System;
using System.Collections.Generic;
class Program {
public static int GetCombinations(int total, int index, int[] list, List<int> cur) {
if (total == 0) {
foreach(var i in cur) {
Console.Write(i + " ");
}
Console.WriteLine();
return 1;
}
if(index == list.Length) {
return 0;
}
int ret = 0;
for(; total >= 0; total -= list[index]) {
ret += GetCombinations(total, index + 1, list, cur);
cur.Add(list[index]);
}
for(int i = 0; i < cur.Count; i++) {
while(cur.Count > i && cur[i] == list[index]) {
cur.RemoveAt(i);
}
}
return ret;
}
public static void Main() {
int[] l = { 5, 10, 20, 50, 100, 200, 500 };
GetCombinations(20, 0, l, new List<int>());
}
}
I improved my code and now you're able to enumerate ALL combinations using recursion.
In this code, it enumerates combinations in lexicographical order.
I verified for sum=20, 75 cases.

Implementing quicksort algorithm

I found quicksort algorithm from this book
This is the algorithm
QUICKSORT (A, p, r)
if p < r
q = PARTITION(A, p, r)
QUICKSORT(A, p, q-1)
QUICKSORT(A, q+1, r)
PARTITION(A, p, r)
x=A[r]
i=p-1
for j = p to r - 1
if A <= x
i = i + 1
exchange A[i] with A[j]
exchange A[i+1] with A[r]
return i + 1
And I made this c# code:
private void quicksort(int[] input, int low, int high)
{
int pivot_loc = 0;
if (low < high)
pivot_loc = partition(input, low, high);
quicksort(input, low, pivot_loc - 1);
quicksort(input, pivot_loc + 1, high);
}
private int partition(int[] input, int low, int high)
{
int pivot = input[high];
int i = low - 1;
for (int j = low; j < high-1; j++)
{
if (input[j] <= pivot)
{
i++;
swap(input, i, j);
}
}
swap(input, i + 1, high);
return i + 1;
}
private void swap(int[] ar, int a, int b)
{
temp = ar[a];
ar[a] = ar[b];
ar[b] = temp;
}
private void print(int[] output, TextBox tbOutput)
{
tbOutput.Clear();
for (int a = 0; a < output.Length; a++)
{
tbOutput.Text += output[a] + " ";
}
}
When I call function like this quicksort(arr,0,arr.Length-1); I get this error An unhandled exception of type 'System.StackOverflowException' occurred it pass empty array... when call function like this quicksort(arr,0,arr.Length); I get error Index was outside the bounds of the array. on this line int pivot = input[high]; but array passed successfully.
I also want to print it like this print(input,tbQuick); but where to place it so it would print when quicksort finished?
You did not properly implement the base case termination, which causes quicksort to never stop recursing into itself with sublists of length 0.
Change this:
if (low < high)
pivot_loc = partition(input, low, high);
quicksort(input, low, pivot_loc - 1);
quicksort(input, pivot_loc + 1, high);
to this:
if (low < high) {
pivot_loc = partition(input, low, high);
quicksort(input, low, pivot_loc - 1);
quicksort(input, pivot_loc + 1, high);
}
In addition to Deestan's answer, you also have this wrong:
for (int j = low; j < high-1; j++)
It should be:
for (int j = low; j < high; j++)
Just in case you want some shorter code for Quicksort:
IEnumerable<int> QuickSort(IEnumerable<int> i)
{
if (!i.Any())
return i;
var p = (i.First() + i.Last) / 2 //whichever pivot method you choose
return QuickSort(i.Where(x => x < p)).Concat(i.Where(x => x == p).Concat(QuickSort(i.Where(x => x > p))));
}
Get p (pivot) with whatever method is suitable of course.
This is the shortest implementation of Quick Sort algorithm (Without StackOverflowException)
IEnumerable<T> QuickSort<T>(IEnumerable<T> i) where T :IComparable
{
if (!i.Any()) return i;
var p = i.ElementAt(new Random().Next(0, i.Count() - 1));
return QuickSort(i.Where(x => x.CompareTo(p) < 0)).Concat(i.Where(x => x.CompareTo(p) == 0)).Concat(QuickSort(i.Where(x => x.CompareTo(p) > 0)));
}
A Simple Quick Sort Implementation.
https://github.com/bharathkumarms/AlgorithmsMadeEasy/blob/master/AlgorithmsMadeEasy/QuickSort.cs
using System;
using System.Collections.Generic;
using System.Linq;
namespace AlgorithmsMadeEasy
{
class QuickSort
{
public void QuickSortMethod()
{
var input = System.Console.ReadLine();
string[] sInput = input.Split(' ');
int[] iInput = Array.ConvertAll(sInput, int.Parse);
QuickSortNow(iInput, 0, iInput.Length - 1);
for (int i = 0; i < iInput.Length; i++)
{
Console.Write(iInput[i] + " ");
}
Console.ReadLine();
}
public static void QuickSortNow(int[] iInput, int start, int end)
{
if (start < end)
{
int pivot = Partition(iInput, start, end);
QuickSortNow(iInput, start, pivot - 1);
QuickSortNow(iInput, pivot + 1, end);
}
}
public static int Partition(int[] iInput, int start, int end)
{
int pivot = iInput[end];
int pIndex = start;
for (int i = start; i < end; i++)
{
if (iInput[i] <= pivot)
{
int temp = iInput[i];
iInput[i] = iInput[pIndex];
iInput[pIndex] = temp;
pIndex++;
}
}
int anotherTemp = iInput[pIndex];
iInput[pIndex] = iInput[end];
iInput[end] = anotherTemp;
return pIndex;
}
}
}
/*
Sample Input:
6 5 3 2 8
Calling Code:
QuickSort qs = new QuickSort();
qs.QuickSortMethod();
*/
Code Implemented with Iteration With last element as Pivot
<code>https://jsfiddle.net/zishanshaikh/5zxvwoq0/3/ </code>
function quickSort(arr,l,u) {
if(l>=u)
{
return;
}
var pivot=arr[u];
var pivotCounter=l;
for(let i=l;i<u;i++)
{
if(arr[i] <pivot )
{
var temp= arr[pivotCounter];
arr[pivotCounter]=arr[i] ;
arr[i]=temp;
pivotCounter++;
}
}
var temp2= arr[pivotCounter];
arr[pivotCounter]=arr[u] ;
arr[u]=temp2;
quickSort(arr,pivotCounter+1,u);
quickSort(arr,0,pivotCounter-1);
}
<code>https://jsfiddle.net/zishanshaikh/exL9cdoe/1/</code>
Code With first element as Pivot
//Logic For Quick Sort
function quickSort(arr,l,u) {
if(l>=u)
{
return;
}
var pivot=arr[l];
var pivotCounter=l+1;
for(let i=l+1;i<u;i++)
{
if(arr[i] <pivot )
{
var temp= arr[pivotCounter];
arr[pivotCounter]=arr[i] ;
arr[i]=temp;
pivotCounter++;
}
}
var j=pivotCounter-1;
var k=l+1;
while(k<=j)
{
var temp2= arr[k-1];
arr[k-1]=arr[k] ;
arr[k]=temp2;
k++;
}
arr[pivotCounter-1]=pivot;
quickSort(arr,pivotCounter,u);
quickSort(arr,0,pivotCounter-2);
}
A simple generic C# implementation of QuickSort, can use first or last value or any other intermediate value for pivot
using System;
namespace QuickSort
{
class Program
{
static void Main(string[] args)
{
int[] arInt = { 6, 4, 2, 8, 4, 5, 4, 5, 4, 5, 4, 8, 11, 1, 7, 4, 13, 5, 45, -1, 0, -7, 56, 10, 57, 56, 57, 56 };
GenericQuickSort<int>.QuickSort(arInt, 0, arInt.Length - 1);
string[] arStr = { "Here", "Is", "A", "Cat", "Really", "Fast", "And", "Clever" };
GenericQuickSort<string>.QuickSort(arStr, 0, arStr.Length - 1); ;
Console.WriteLine(String.Join(',', arInt));
Console.WriteLine(String.Join(',', arStr));
Console.ReadLine();
}
}
class GenericQuickSort<T> where T : IComparable
{
public static void QuickSort(T[] ar, int lBound, int uBound)
{
if (lBound < uBound)
{
var loc = Partition(ar, lBound, uBound);
QuickSort(ar, lBound, loc - 1);
QuickSort(ar, loc + 1, uBound);
}
}
private static int Partition(T[] ar, int lBound, int uBound)
{
var start = lBound;
var end = uBound;
var pivot = ar[uBound];
// switch to first value as pivot
// var pivot = ar[lBound];
while (start < end)
{
while (ar[start].CompareTo(pivot) < 0)
{
start++;
}
while (ar[end].CompareTo(pivot) > 0)
{
end--;
}
if (start < end)
{
if (ar[start].CompareTo(ar[end]) == 0)
{
start++;
}
else
{
swap(ar, start, end);
}
}
}
return end;
}
private static void swap(T[] ar, int i, int j)
{
var temp = ar[i];
ar[i] = ar[j];
ar[j] = temp;
}
}
}
Output:
-7,-1,0,1,2,4,4,4,4,4,4,5,5,5,5,6,7,8,8,10,11,13,45,56,56,56,57,57
A,And,Cat,Clever,Fast,Here,Is,Really
One important thing to notice here is that this optimized and simple code properly handles duplicates. I tried several posted quick sort code. Those do not give correct result for this (integer array) input or just hangs, such as https://www.w3resource.com/csharp-exercises/searching-and-sorting-algorithm/searching-and-sorting-algorithm-exercise-9.php and http://www.softwareandfinance.com/CSharp/QuickSort_Iterative.html. Therefore, if author also wants to use the code which handles duplicates this would be a good reference.

What is the best way to route paths in a large grid?

I'm working on an algorithm to find a set of non intersected paths in a grid for a
given pairs of points..
Like this for these pairs:
(9,4) and (12,13)
The output should be something like this:
9,10,11,7,3,4
13,14,15,16,12
and print "Blocked" if it can't route all paths
First I searched for an already made algorithm to find all simple paths between 2
points in a graph or a grid. and I found this one by #Casey Watson and #svick here..
It works really well but for small graphs only.
I converted it to C#.NET and enhanced it a little bit to be able to find paths of
maximum length X. and build on it my total algorithm.
The one I built works fine in small graphs..
Here is routes 9 pairs in a 8x8 grid..
but it takes a huge time in larger ones like the 16x16 or even the final one I intended to do which is a 3D model of 16x16x2
Like this
The algorithm was developed to be a depth first search RECURSIVE algorithm, but it
took a huge time to return value to the user. so I decided to convert it to loops instead of the recursive calls so that I can benefit from yield return feature in .NET
but still it didn't help any better.
The loops version of the algorithm find a route for a pair of points in less than a second but the recursive one took more than 90 seconds.
when I tried with 2 pairs, the loops version took around 342 seconds but the recursive one took around 200..
So I can't know which is faster..!? the recursive or the loops one..
I really want to know the best way to do this..
Note : the first digit in the number of the node determine the layer (Starts at 1)..
Here is the code
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
namespace AlgorithmTest
{
struct Connection
{
public int FirstNode;
public int SecondNode;
public Connection(int N1,int N2)
{
FirstNode = N1;
SecondNode = N2;
}
}
enum Algorithm
{ Recursion, Loops }
public class Search
{
private const int MAX = 15;
private const int Width = 16;
private const int Length = 16;
private const int Height = 2;
private static void Main(string[] args)
{
var graph = new Graph();
var str = new int[Height,Length, Width];
var level = ((int)Math.Pow(10, (Length * Width).ToString().Length) >= 100) ? (int)Math.Pow(10, (Length * Width).ToString().Length) : 100;
for (var i = 0; i < Height; i++)
{
int num = 0;
for (var j = 0; j < Length; j++)
for (var k = 0; k < Width; k++)
{
str[i, j, k] = ++num + level;
}
level += level;
}
for (var i = 0; i < Height; i++)
{
for (var j = 0; j < Length; j++)
{
for (var k = 0; k < Width; k++)
{
if (i < Height - 1) graph.addEdge(str[i, j, k], str[i + 1, j, k]);
if (i > 0) graph.addEdge(str[i, j, k], str[i - 1, j, k]);
if (k < Width - 1) graph.addEdge(str[i, j, k], str[i, j, k + 1]);
if (k > 0) graph.addEdge(str[i, j, k], str[i, j, k - 1]);
if (j < Length - 1) graph.addEdge(str[i, j, k], str[i, j + 1, k]);
if (j > 0) graph.addEdge(str[i, j, k], str[i, j - 1, k]);
}
}
}
var wt = new Stopwatch();
wt.Start();
var connectedNodes = new List<Connection>()
{
new Connection(1030, 1005),
// new Connection(1002, 1044),
// new Connection(1015, 1064),
// new Connection(1041, 1038),
// new Connection(1009, 1027),
// new Connection(1025, 1018),
// new Connection(1037, 1054),
// new Connection(1049, 1060),
// new Connection(1008, 1031),
// new Connection(1001, 1035),
};
wt.Start();
Console.WriteLine("Using Loops:");
Console.WriteLine();
var allPaths = new Search().FindAllPaths(connectedNodes, graph, MAX, Algorithm.Loops);
wt.Stop();
foreach (var path in allPaths)
{
PrintPath(path);
}
Console.WriteLine("Total Seconds: " + wt.Elapsed.TotalSeconds + ", Number of paths: " + allPaths.Count());
Console.WriteLine("***************************************************************************************************");
Console.WriteLine("Using Recursion:");
Console.WriteLine();
wt.Reset();
wt.Start();
allPaths = new Search().FindAllPaths(connectedNodes, graph, MAX, Algorithm.Recursion);
wt.Stop();
foreach (var path in allPaths)
{
PrintPath(path);
}
Console.WriteLine("Total Seconds: " + wt.Elapsed.TotalSeconds + ", Number of paths: " + allPaths.Count());
Console.WriteLine();
}
private IEnumerable<List<int>> FindAllPaths(List<Connection> connectedNodes, Graph graph, int max, Algorithm algorithm)
{
var paths=new Stack<List<int>>();
var blocked=new List<int>();
for (var i = 0; i < connectedNodes.Count; i++)
{
if (!blocked.Contains(connectedNodes[i].FirstNode)) blocked.Add(connectedNodes[i].FirstNode);
if (!blocked.Contains(connectedNodes[i].SecondNode)) blocked.Add(connectedNodes[i].SecondNode);
}
if (algorithm == Algorithm.Recursion)
{
if (FindAllPaths(connectedNodes, 0, max, graph, paths, blocked))
{
Console.WriteLine("BLOCKED");
return new List<List<int>>();
}
}
else if(algorithm==Algorithm.Loops)
{
if (!FindAllPaths2(connectedNodes, 0, max, graph, paths, blocked))
{
Console.WriteLine("BLOCKED");
return new List<List<int>>();
}
}
return paths;
}
private static bool FindAllPaths(List<Connection> connectedNodes,int order,int max, Graph graph, Stack<List<int>> allPaths, List<int> blocked)
{
if (order >= connectedNodes.Count) return false;
var paths = SearchForPaths(graph, connectedNodes[order].FirstNode, connectedNodes[order].SecondNode, max, blocked);
if (paths.Count == 0) return true;
int i;
for (i = 0; i < paths.Count; i++)
{
var path = paths[i];
allPaths.Push(path);
blocked.AddRange(path);
if (!FindAllPaths(connectedNodes, order + 1,max, graph, allPaths, blocked)) break;
allPaths.Pop();
foreach (var j in path)
{
blocked.RemoveAll(num => num==j);
}
paths.RemoveAll(list => IsListsSimilar(list,path));
i--;
}
if (i == paths.Count) return true;
return false;
}
private static bool IsListsSimilar(List<int> L1,List<int> L2)
{
if (L2.Count > L1.Count) return false;
for (int i = 0; i < L2.Count - 1; i++)
{
if (L1[i] != L2[i]) return false;
}
return true;
}
private static List<List<int>> SearchForPaths(Graph graph, int start, int end, int max, List<int> blocked)
{
blocked.Remove(start);
blocked.Remove(end);
var nodePaths = new List<List<int>>();
var visited = new LinkedList<int>();
visited.AddLast(start);
DepthFirstSearch(graph, visited, end, max, blocked, nodePaths);
nodePaths = nodePaths.OrderBy(list => list.Count).ToList();
return nodePaths;
}
private static void DepthFirstSearch(Graph graph, LinkedList<int> visited, int end, int max, List<int> blocked, List<List<int>> paths)
{
var nodes = graph.adjacentNodes(visited.Last.Value);
// examine adjacent nodes
var nodeCount = blocked.Count;
for (int i = 0; i < nodeCount; i++)
{
if (visited.Contains(blocked[i])) return;
}
if (visited.Count > max) return;
nodeCount = nodes.Count;
for (var i = 0; i < nodeCount; i++)
{
if (visited.Contains(nodes[i]) || nodes[i] != end) continue;
visited.AddLast(nodes[i]);
{
paths.Add(new List<int>(visited));
}
visited.RemoveLast();
break;
}
nodeCount = nodes.Count;
for (var i = 0; i < nodeCount; i++)
{
if (visited.Contains(nodes[i]) || nodes[i] == end) continue;
visited.AddLast(nodes[i]);
DepthFirstSearch(graph, visited, end, max, blocked, paths);
visited.RemoveLast();
}
}
private static bool FindAllPaths2(List<Connection> connectedNodes, int order, int max, Graph graph, Stack<List<int>> allPaths, List<int> blocked)
{
if (order >= connectedNodes.Count) return false;
foreach (var path in SearchForPaths2(graph, connectedNodes[order].FirstNode, connectedNodes[order].SecondNode, max, blocked))
{
allPaths.Push(path);
blocked.AddRange(path);
if (!FindAllPaths2(connectedNodes, order + 1, max, graph, allPaths, blocked)) break;
allPaths.Pop();
foreach (var j in path)
{
blocked.RemoveAll(num => num == j);
}
}
return true;
}
private static IEnumerable<List<int>> SearchForPaths2(Graph graph, int start, int end, int max, List<int> blocked)
{
blocked.Remove(start);
blocked.Remove(end);
var visited = new LinkedList<int>();
visited.AddLast(start);
foreach (var VARIABLE in DepthFirstSearch(graph, visited, end, max, blocked))
{
yield return VARIABLE;
}
}
private static IEnumerable<List<int>> DepthFirstSearch(Graph graph, LinkedList<int> visited, int end, int max, List<int> blocked)
{
var nodes = graph.adjacentNodes(visited.Last.Value);
var nodeCount = blocked.Count;
for (int i = 0; i < nodeCount; i++)
{
if (visited.Contains(blocked[i])) yield break;
}
if (visited.Count > max) yield break;
nodeCount = nodes.Count;
for (var i = 0; i < nodeCount; i++)
{
if (visited.Contains(nodes[i]) || nodes[i] != end) continue;
visited.AddLast(nodes[i]);
yield return (new List<int>(visited));
visited.RemoveLast();
break;
}
nodeCount = nodes.Count;
for (var i = 0; i < nodeCount; i++)
{
if (visited.Contains(nodes[i]) || nodes[i] == end) continue;
visited.AddLast(nodes[i]);
foreach (var P in DepthFirstSearch(graph, visited, end, max, blocked))
{
yield return P;
}
visited.RemoveLast();
}
}
private static void PrintPath(List<int> visited)
{
for (int i = 0; i < visited.Count()-1; i++)
{
Console.Write(visited[i]);
Console.Write(" --> ");
}
Console.Write(visited[visited.Count() - 1]);
Console.WriteLine();
Console.WriteLine();
}
}
public class Graph
{
private readonly Dictionary<int, HashSet<int>> map = new Dictionary<int, HashSet<int>>();
public void addEdge(int node1, int node2)
{
HashSet<int> adjacent = null;
map.TryGetValue(node1, out adjacent);
if (adjacent == null)
{
adjacent = new HashSet<int>();
map.Add(node1, adjacent);
}
adjacent.Add(node2);
}
public List<int> adjacentNodes(int last)
{
HashSet<int> adjacent = null;
map.TryGetValue(last, out adjacent);
if (adjacent == null)
{
return new List<int>();
}
return new List<int>(adjacent);
}
}
}
I think the answer lies in how you have numbered the nodes in your grid. For a simple 2-dimensional grid, 4 nodes by 4, you would number them : 00, 01, 02, 03, 10, 11, 12 ... 30, 31, 32, 33. Think of them as composite number strings (not decimal values) acting as dimension-based node addresses.
In a 3-dimensional grid, they would be numbered 000, 001, 002, etc. up to 330, 331, 332, 333.
If you want to find all routes between two points 10 and 22 you can quickly calculate their distance by adding the dimensional differences: 1y is one away from 2y, and x0 is two away from x2. Therefore the node distance is 3, you will need to travel over 3 edges (connecting 4 nodes in total) to reach the destination.
The solution space (the only nodes that could ever be involved in a solution route) can be enumerated by creating a set of embedded FOR/NEXT loops, one for each dimension. In this case, the start and end values of 10 and 22 would produce: 10, 11, 12, 20, 21 and 22.
Now comes the clever bit. You can precompute (prepare) a table of 'forwarding' connections between the nodes in your array. Node 10 connects to 20 and 11 (both 1 dimensional difference away). From that you can generate a sequence of valid pathways from 10 to 22 by adding one to a dimension difference in which ever direction you plan to move (in a 2-D array you only get to choose one of two ways. In 3-D you get three choices).
Each answer should be the shortest possible distance. The computation time for this approach should be milliseconds. On a steam powered ZX81!

Categories

Resources