I created the pair class and array class, but I'm lost on how to implement the quicksort algorithm.
I want to do it if ints are same then I should sort by double. I was able to implement quicksort with one value per index of array, but with this I just can't find any resources.
Maybe you guys have some resources or maybe you had the same problem?
By the way I'm trying to implement it with c#.
This is my pair class:
class Pair
{
public int integer = 0;
public double doubl = 0.0;
public Pair(int integer, double doubl)
{
this.integer = integer;
this.doubl = doubl;
}
public Pair()
{
}
public int Integer() { return integer; }
public double Doubl() { return doubl; }
}
And my data array class
class MyDataArray : DataArray
{
Pair[] data;
int operations = 0;
public MyDataArray(int n, int seed)
{
data = new Pair[n];
Random rand = new Random(seed);
for (int i = 0; i < n; i++)
{
data[i] = new Pair(rand.Next(1,100), rand.NextDouble());
}
}
public override int integer(int index)
{
return data[index].integer;
}
public override double doubl(int index)
{
return data[index].doubl;
}
public override void Swap(int i, int j)
{
Pair temp = data[i]; // c3 1
data[i] = data[j]; // c3 1
data[j] = temp; // c3 1
}
Your Pair class could implement IComparable<T>, and your quick sort algorithm could be implemented using the CompareTo method.
The IComparable<T> interface:
Defines a generalized comparison method that a value type or class implements to create a type-specific comparison method for ordering or sorting its instances.
You can see the documentation on the CompareTo method to see what the return values mean.
public class Pair : IComparable<Pair>
{
public int integer = 0;
public double doubl = 0.0;
public Pair(int integer, double doubl)
{
this.integer = integer;
this.doubl = doubl;
}
public Pair()
{
}
public int CompareTo(Pair other)
{
if (other == null)
{
return 1;
}
int result = integer.CompareTo(other.integer);
if (result == 0)
{
result = doubl.CompareTo(other.doubl);
}
return result;
}
public int Integer() { return integer; }
public double Doubl() { return doubl; }
}
If you prefer to use the comparison operators, you can implement them in terms of the CompareTo method. The documentation I liked has examples on how to do that.
//sort for integer
var SortedIntegerList = data.OrderBy(x=>x.integer);
//sort for double
var SortedDoubleList = data.OrderBy(x=>x.doubl);
OrderBy for objects uses Quicksort - What Sorting Algorithm Is Used By LINQ "OrderBy"? - so you can use that.
To avoid creating IComparer<Pair> interface you can construct it using Comparer<T>.Create from just comparison delegate:
var sorted = source.OrderBy(x => x, Comparer<Pair>.Create(
(p1, p2) => p1.Integer() - p2.Integer() != 0 ?
p1.Integer() - p2.Integer() :
Math.Sign(p1.Doubl() - p2.Doubl()))).ToList();
Related
I have two classes
class CSparseMatrix:
{
public int NumberOfDimensions { get; set;}
public int DefaultNumber { get; set; }
List<int> dimensionsRanges = new List<int>(); // that's specify dimension of ranges, f.e. {100, 100, 100, 120..}
List<CSparseCell> cells = new List<CSparseCell>(); // contains only values different from default for this matrix
}
class CSparseCell {
public int Value { get; set; }
public List<int> coordinates = new List<int>();
}
And the problem is: how to loop through this CSparseMatrix and output all ranges with values in format like: [0, 0, 0, 0] - *value*, [0, 0, 0, 1] - *value*, [0, 0, 0, 2] - *value*, ...[dimensionsRanges[0]-1, dimensionsRanges[1]-1, dimensionsRanges[2]-1, dimensionsRanges[3]-1] - *value* so through all ranges and output all values (we can have any number of this dimensions).
That means that in program we had to to output all values of matrix, which can have any number of dimensions and ranges could be different. But we don't know what this number of dimensions will be so can't use n-nested loops, and actually I have no idea of algorithm or method how to iterate through all values from List<int> dimensionsRanges
The way, we get the specific value from this "matrix" is
public int GetValueFromCell(List<int> coordinate)
{
foreach(CSparseCell cell in cells)
{
if(cell.coordinates.All(coordinate.Contains)) {
return cell.Value;
}
}
return DefaultNumber;
}
Since you say your matrix is large, avoid returning CSparseCell by pushing the Value lookup to the answer computation.
You create a method to return all the coordinates in the sparse matrix, using a helper method to increment coordinates. NOTE: I changed the coordinate increment method to use a for loop instead of do which might be easier to understand (?).
void IncCoord(ref List<int> aCoord) { // ref not needed, just for documentation
for (var curDim = NumberOfDimensions - 1; curDim >= 0; --curDim) {
if (aCoord[curDim] == dimensionsRanges[curDim] - 1) // handle carry
aCoord[curDim] = 0;
else {
++aCoord[curDim];
break;
}
}
}
public IEnumerable<List<int>> AllCoords() {
var curCellCoord = Enumerable.Repeat(0, NumberOfDimensions).ToList();
var numCells = dimensionsRanges.Product();
for (int j1 = 0; j1 < numCells; ++j1) {
yield return curCellCoord.ToList();
IncCoord(ref curCellCoord);
}
}
Now you can use this method to get all Values and you can format the output however you like. Assuming t is a CSparseMatrix:
var ans = t.AllCoords().Select(c => $"[{c.Join(",")}] - {t.GetValueFromCell(c)}");
A couple of helper extension methods are used:
public static class IEnumerableExt {
public static int Product(this IEnumerable<int> src) => src.Aggregate(1, (a,n) => a * n);
}
public static class StringExt {
public static string Join<T>(this IEnumerable<T> items, string sep) => String.Join(sep, items);
}
I'd make a couple suggestions. First tying the coordinate and the value together complicate things. It'd be much better to separate those two.
Secondly, having to search the entire array to find a single cell makes it very inefficient. You can create a simple sparse matrix out of a dictionary. This not at all the best way but with the unknown key requirements you have given it's at least better than the array. (is it really a matrix if the key is 1..n ?)
Here's an example. First we make the coordinates their own type.
readonly struct SparseCoord : IEquatable<SparseCoord>
{
public static SparseCoord ToCoordinate(params int[] coords)
{
return new SparseCoord(coords);
}
public SparseCoord(int[] c)
{
this.Coordinate = new int[c?.Length ?? 0];
if (null != c)
c.CopyTo(this.Coordinate, 0);
}
public int[] Coordinate { get; }
public bool Equals([AllowNull] SparseCoord other)
{
return Enumerable.SequenceEqual(this.Coordinate, other.Coordinate);
}
public override bool Equals(object obj)
{
if (obj is SparseCoord c)
return this.Equals(c);
return false;
}
public override int GetHashCode()
{
var hash = new HashCode();
foreach (var i in this.Coordinate)
hash.Add(i);
return hash.ToHashCode();
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append('(');
foreach (var i in this.Coordinate)
{
sb.Append(i);
sb.Append(',');
}
sb.Length = sb.Length - 1;
sb.Append(')');
return sb.ToString();
}
}
Then we create a sparse matrix using a dictionary as the storage. Note this is incomplete obviously as there's no way to clear it partially or completely but again it's just an example.
class SparseMatrix : IEnumerable<KeyValuePair<SparseCoord, int>>
{
Dictionary<SparseCoord, int> cells = new Dictionary<SparseCoord, int>();
public int this[SparseCoord coord]
{
get
{
if (this.cells.TryGetValue(coord, out var ret))
return ret;
return 0;
}
set
{
this.cells[coord] = value;
}
}
public IEnumerator<KeyValuePair<SparseCoord, int>> GetEnumerator()
{
return this.cells.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
Then you can add values and iterate over the contents:
static void Main(string[] _)
{
SparseMatrix matrix = new SparseMatrix();
matrix[SparseCoord.ToCoordinate(1, 2, 3)] = 1;
matrix[SparseCoord.ToCoordinate(5, 6, 7)] = 2;
foreach (var value in matrix)
Console.WriteLine(value);
}
Finally I would reiterate that if your matrix really is going to get "big" as you said in a comment then you should invest some time in looking at some well known implementations of sparse matrix.
Here is example of how to sort array of objects by it's fields. I need to create function which will do same thing but WITHOUT Linq, Generics or any other classes.
p.s You can add methods in Test class to compare fields.
using System;
using System.Linq;
class Test {
public int Count;
public int Sum;
}
class Program {
static void Main() {
Test a1 = new Test() {
Count = 1 ,
Sum = 20
};
Test a2 = new Test() {
Count = 2 ,
Sum = 10
};
Test a3 = new Test() {
Count = 3 ,
Sum = 30
};
var arr = new Test[] { a1, a2, a3};
var result = arr.OrderBy(n => n.Count).ToList();
foreach (var item in result) {
Console.WriteLine(item.Count);
}
}
static void MyOrder() {
//function which will sort passed array of objects by fields
}
}
One method is to use Array.Sort() static method. But if you want to use it, you class must implement IComparable interface, for example:
class Test : IComparable
{
public int Count;
public int Sum;
public int CompareTo(object obj)
{
if (!(obj is Test))
throw new ArgumentException("You can't compare two objects of different types!");
var test = (Test)obj;
if (test.Count < this.Count) return 1;
else if (test.Count > this.Count) return -1;
else return 0;
}
}
And then code would become:
var arr = new Test[] { a1, a3, a2 };
Array.Sort(arr);
EDIT:
If you want to change ordering field at runtime, you can use IComparer interface as folloing:
public class Test
{
public int Count;
public int Sum;
}
public class TestComparerBySum : IComparer<Test>
{
public int Compare(Test x, Test y)
{
if (x.Sum > y.Sum) return 1;
else if (x.Sum < y.Sum) return -1;
else return 0;
}
}
public class TestComparerByCount : IComparer<Test>
{
public int Compare(Test x, Test y)
{
if (x.Count > y.Count) return 1;
else if (x.Count < y.Count) return -1;
else return 0;
}
}
And use it in code like this:
var arr = new Test[] { a3, a2, a1 };
Array.Sort(arr, new TestComparerBySum());
Array.Sort(arr, new TestComparerByCount());
I was attempting to solve the running median problem (on hackerrank) using a sorted set. Only it's elements don't appear properly sorted.
See it in action here: http://rextester.com/NGBN25779
public class RunningMedian{
List<int> list = new List<int>();
SortedSet<int> sorted = new SortedSet<int>();
public void Add(int num){
list.Add(num);
sorted.Add(num);
}
public double MedianNotWorking(){
return GetMedian(sorted.ToArray());
}
public double MedianWorking(){
int[] arr = list.ToArray();
Array.Sort(arr);
return GetMedian(arr);
}
public double GetMedian(int[] arr){
int idx = list.Count / 2;
if(arr.Length % 2 == 0){
return (double)((double)(arr[idx] + arr[idx-1]) / 2);
}else{
return arr[idx];
}
}
}
static void Main(String[] args) {
int n = Convert.ToInt32(Console.ReadLine());
int[] a = new int[n];
RunningMedian heap = new RunningMedian();
for(int i = 0; i < n; i++){
a[i] = Convert.ToInt32(Console.ReadLine());
heap.Add(a[i]);
//double median = heap.GetMedian();
double median = heap.MedianNotWorking();
Console.WriteLine(median.ToString("F1"));
}
}
For the most part the sorted set does work. However at larger input sizes it begins to give wrong answers. It may not be the optimal solution to the problem but I'm curious as to why it fails at all. C# doesn't have a min-heap / priority queue so why can't sorted sets be used as a substitute?
*Edited to include full code from hackerrank.
Here is an input file.
Input
http://textuploader.com/dovni
Expected
http://textuploader.com/dovnb
Output
http://textuploader.com/dovwj
Conflicts appear near the end
Expected
(Skipping 1-364)
54240.0
54576.5
54913.0
54576.5
54240.0
Results
(Skipping 1-364)
54240.0
54576.5
54913.0
54963.0
54576.5
SortedSet collections contain by definition only unique values. However your input file contains the number 21794 twice, which means that the second 21794 entry doesn't get added to your SortedSet. So your sorted set will contain fewer values than your list and your whole algorithm doesn't work anymore.
In general, this could be achieved by definition of new IComparator behavior for the SortedSet comparison. For the min priority queue it would be smth like this:
public class PriorityQueue<K,V> where K : IComparable
where V : IComparable
{
private SortedSet<Node<K,V>> _set;
private readonly int _amount;
public PriorityQueue(int amount)
{
_set = new SortedSet<Node<K,V>>(new PriorityComparer<K,V>());
_amount = amount;
}
public void Add(Node<K,V> value)
{
if (_amount > _set.Count)
_set.Add(value);
else
{
if (_set.Max.Val.CompareTo(value.Val) == 1)
{
_set.Remove(_set.Max);
_set.Add(value);
}
}
}
public Node<K,V> ExtractMax()
{
var max = _set.Max;
_set.Remove(max);
return max;
}
public Node<K,V> ExtractMin()
{
var min = _set.Min;
_set.Remove(min);
return min;
}
public bool IsEmpty => _set.Count == 0;
}
public struct Node<K,V> where K : IComparable
where V : IComparable
{
public K Key;
public V Val;
public Node(K key, V val)
{
Val = val;
Key = key;
}
}
public class PriorityComparer<K,V> : IComparer<Node<K,V>> where K: IComparable
where V: IComparable
{
public int Compare(Node<K,V> i, Node<K,V> y)
{
var compareresult = i.Val.CompareTo(y.Val);
if (compareresult == 0)
return i.Key.CompareTo(y.Key);
return compareresult;
}
}
I'm trying to come up with the best way of doing some kind of switch style selection on a double to find out what range it is in. Something like this:
double a = 1.1;
switch(a)
{
case: (0.0, 1.6)
return 1;
case: (1.6, 2.337)
return 2;
case: (2.337, 3.2974)
return 3;
default:
return -1;
}
Obviously in this example, one value in the range would have to be non-inclusive, but you get my drift. Any Ideas?
Edit, the ranges are not necessarily integral.
EDIT 2:
I'm actually dealing with radians and finding out which of 12 ranges a point is in. I ended up doing this:
double pi = Math.PI;
double[] zones = new double[] {
0, pi/6, pi/3, pi/2,
2*pi/3, 5*pi/6, pi, 7*pi/6,
4*pi/3, 3*pi/2, 5*pi/3, 11*pi/6
};
for (int i = 0; i < 11; i++)
{
if (radians > zones[i] && radians <= zones[i + 1])
{
return i + 1;
}
}
I started to do an binary search type if-else, but it was going to get too messy.
The following is ideally suited to adjacent ranges, since you only need to write the range limits once:
double a = 1.1;
if (a < 0.0) {
// Too low
return -1;
} else if (a < 1.6) {
// Range [0.0, 1.6)
return 1;
} else if (a < 2.337) {
// Range [1.6, 2.337)
return 2;
} else if (a < 3.2974) {
// Range [2.337, 3.2974)
return 3;
} else {
// Too high
return -1;
}
This is probably over engineering but you could create a Range Class with Min and Max values and a Callback Function.
Then just create all the Ranges with respective min, and max values and callback and add them to an IEnumerable.
Use LINQ to find out the correct range:
range = Ranges.First(r => r.MinValue <= value and r.MaxValue > value);
Then just call the range callback.
Just round up
double a = 1.1;
if(d < 0.0)
return -1;
else
return (int)Math.Ceiling(a);
Perhaps this will do what you want to do with a nice syntactic structure. Please adjust visibilities and comparisons according to your purposes:
public static class Range
{
public interface ISwitchable
{
void SetDefault(Action defaultStatement);
void Execute();
}
public interface ISwitchable<T>: ISwitchable
where T: IComparable<T>
{
T Value { get; set; }
void AddCase(ICase<T> caseStatement);
}
public class Switchable<T> : ISwitchable<T>
where T: IComparable<T>
{
private readonly IList<ICase<T>> _caseStatements = new List<ICase<T>>();
private Action _defaultStatement;
#region ISwitchable<T> Members
public T Value { get; set; }
public void AddCase(ICase<T> caseStatement)
{
_caseStatements.Add(caseStatement);
}
public void SetDefault(Action defaultStatement)
{
_defaultStatement = defaultStatement;
}
public void Execute()
{
foreach (var caseStatement in _caseStatements)
if ((caseStatement.Min.CompareTo(Value) <= 0) && (caseStatement.Max.CompareTo(Value) > 0))
{
caseStatement.Action();
return;
}
_defaultStatement();
}
#endregion
}
public interface ICase<T>
where T: IComparable<T>
{
T Min { get; set; }
T Max { get; set; }
Action Action { get; set; }
}
public sealed class Case<T>: ICase<T>
where T: IComparable<T>
{
#region ICase<T> Members
public T Min { get; set; }
public T Max { get; set; }
public Action Action { get; set; }
#endregion
}
public static ISwitchable<T> Switch<T>(T value)
where T: IComparable<T>
{
return new Switchable<T>();
}
}
public static class SwitchableExtensions
{
public static Range.ISwitchable<T> Case<T>(this Range.ISwitchable<T> switchable, T min, T max, Action action)
where T: IComparable<T>
{
switchable.AddCase(new Range.Case<T>{ Min = min, Max = max, Action = action });
return switchable;
}
public static void Default(this Range.ISwitchable switchable, Action action)
{
switchable.SetDefault(action);
switchable.Execute();
}
}
Usage:
class Program
{
static void Main(string[] args)
{
Range.Switch(10)
.Case(0, 3, () => Console.WriteLine("Between 0 and 3"))
.Case(3, 7, () => Console.WriteLine("Between 3 and 7"))
.Default(() => Console.WriteLine("Something else"));
}
}
You can't do that with a switch.
if(a >= 0 && a < 1) return 1;
else if(a < 2) return 2;
etc.
Alternatively, you could write up a class to hold minval, maxval, and outputval, then just iterate over those possibilities and return the outputval that matches.
I have a generic class defined like this
class MyGenericClass<T> where T : ICompareable
{
T[] data;
public AddData(T[] values)
{
data = values;
}
}
In mainForm, I create 3 random numbers, and add them as values, lets say 1, 2 and 3. So my T[] data; will look like this: [0]1 [1]2 [2]3
What I want to do is to remove 1 of these values from the array, how do I do that when I'm using generics. Lets say I want to remove 3 from the array so it would look like this[0]1 [1]2
Why don't you use a generic List (List<T>) instead of the array as a private member of your class to hold the data ?
As it is a private member, the 'outside world' cannot access the list, and you will have a much easier life since a List allows you to Add and Remove items easily.
class MyGenericClass<T> where T : ICompareable
{
private List<T> data = new List<T>();
public AddData(params T[] values)
{
data.AddRange (values);
}
public RemoveData( T value )
{
data.Remove (value);
}
public RemoveData( params T[] values )
{
for( int i = 0; i < values.Length; i++ )
{
data.Remove (values[i]);
}
}
}
Once you've done this, you can use the Add member-method of the List to add items, and the Remove member method to remove items. Simple as that.
I've used the params keyword in the AddData method so that you can do this:
var x = new MyGenericClass<int>();
x.AddData(1);
x.AddData(2, 3, 4);
x.AddData(somIntegerList.ToArray());
Change your class to look like this (I also implemented Frederik's suggestion of using a List instead of a array.
class MyGenericClass<T> where T : ICompareable
{
List<T> data;
public AddData(T value)
{
data.Add(value);
}
public RemoveData(T value)
{
data.Remove(value);
}
}
If for some reasaon, you insist on using an array, the remove method may look something like this
public RemoveData(T value)
{
data = data.Where( e => e.CompareTo(value) != 0).ToArray();
}
I kind of had the same question, because I was writing a dynamically sized array to practice creating generic classes.
I found that you can either: move all of the elements down and then set the last element equal to default(T), or create a new array of size-1 to be filled with the remaining elements.
Ex:
public class Array<T>
{
private T[] _array { get; set; }
private int _max { get; set; }
private int _size { get; set; }
public Array()
{
_max = 10;
_array = new T[_max];
_size = 0;
}
public T Remove(int i)
{
if (i >= _size || i < 0) return default(T);
var tmp = _array[i];
for (var j = i; j < _size-1; ++j)
{
_array[j] = _array[j + 1];
}
_array[_size - 1] = default(T);
_size--;
return tmp;
}
}
Or...
public T Remove(int i) {
var tmp = new T[_size-1];
for(var j=0; j < i; ++j)
{
tmp[j] = _array[j];
}
var result = _array[i];
for(var j=i+1; j < _size-1; ++j)
{
tmp[j] = _array[j];
}
_array = null;
_array = tmp;
return result;
}