I am trying to make a dictionary key from 2 ints, I am thinking to combine them as follows
2 and 3 ---> 23
21 and 34 ---> 2134
etc etc
How would one acheive this, and if this is a bad approach, what would be better?
Thanks in advance
The following struct combines two integers and overrides equality members to make it usable as key in a dictionary. This solution is faster than my previous proposal using a Tuple<T1,T2> and less error prone than using a long.
public struct IntKey
{
private readonly int first;
private readonly int second;
public int First { get { return first; } }
public int Second { get { return second; } }
public IntKey(int first, int second)
{
this.first = first;
this.second = second;
}
public bool Equals(IntKey other)
{
return this.first == other.first && this.second == other.second;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
return obj is IntKey && Equals((IntKey) obj);
}
public override int GetHashCode()
{
unchecked
{
return (this.first*397) ^ this.second;
}
}
}
[TestClass]
public class DictionaryTests
{
[TestMethod]
public void Test()
{
var dictionary = new Dictionary<IntKey, string>();
for (int j = 0; j < 3; j++)
{
dictionary.Clear();
var watch = Stopwatch.StartNew();
for (int i = 0; i < 1000000; i++)
{
dictionary.Add(new IntKey(i, i), "asdf");
}
Console.WriteLine(watch.ElapsedMilliseconds);
watch.Restart();
for (int i = 0; i < 1000000; i++)
{
var value = dictionary[new IntKey(i, i)];
}
Console.WriteLine(watch.ElapsedMilliseconds);
}
}
}
Try it. 1,000,000 writes or reads take about 250ms on my Azure VM.
If you know the max value for your int number, say 256 then you can do
firstInt * 256 + secondInt
the above will give you unique number with the performance benefit of the int.
Just reverse the calculation to get back the two numbers
Related
I am trying to implement the class Vector as an abstract one and have stuff like Vector2D and vector3D inherit from it. However, I ran into a problem with the overriding of operators, because they demand a static object reference be returned and I can't create one since I'm not allowed to call the abstract class' constructor there.
Here's the override I came up with:
public static Vector operator +(Vector v1, Vector v2)
{
if (v1.Dimension != v2.Dimension)
{
throw new Exception("Vector Dimensions Must Be Equal");
}
else
{
double[] newMatrix = new double[v1.Dimension]; //the matrix for the new (resulting) vector
for (int i = 0; i < v1.Dimension; i++)
{
newMatrix[i] = v1.Matrix[i] + v2.Matrix[i];
}
return new Vector(newMatrix);
//the abstract class has a constructor that takes a matrix
//and constructs a vector based on it, but it can't be called here
}
}
I tried both using the matrix constructor and generating a new empty instance (I have either of those constructors). Both boil down to the "can't instantiate abstract class" error.
I am aware that I could implement the operations in each of the classes that will derive from Vector, but I hoped there is some workaround/technique/design pattern which solves the problem in a more elegant way, but I don't seem to find any article out there talking about overriding operators in abstract classes (maybe that approach makes no sense..?). Anyway, any help is highly appreciated. Here is the whole class, if needed:
using System;
using System.Text;
namespace PhysicsProblems
{
public abstract class Vector
{
private static int IdCounter;
protected readonly int ID;
protected double[] Matrix;
protected int Dimension
{
get
{
return Matrix.Length;
}
}
public double Magnitude
{
get
{
double sum = 0;
foreach (var value in Matrix)
{
sum += value * value;
}
return Math.Sqrt(sum);
}
}
public Vector(int dimension)
{
ID = IdCounter++;
for (int i = 0; i < dimesion; i++)
{
Matrix[i] = 0;
}
}
public Vector(double[] matrix)
{
ID = IdCounter++;
matrix.CopyTo(Matrix, 0);
}
public static Vector operator +(Vector v1)
{
return v1;//to fix
}
public static Vector operator -(Vector v1)
{
for (int i = 0; i < v1.Matrix.Length; i++)
{
v1.Matrix[i] = -v1.Matrix[i];
}
return v1;//to fix
}
public static Vector operator +(Vector v1, Vector v2)
{
if (v1.Dimension != v2.Dimension)
{
throw new Exception("Vector Dimensions Must Be Equal");
}
else
{
double[] newMatrix = new double[v1.Dimension]; //the matrix for the new (resulting) vector
for (int i = 0; i < v1.Dimension; i++)
{
newMatrix[i] = v1.Matrix[i] + v2.Matrix[i];
}
return new Vector(newMatrix);
//the abstract class has a constructor that takes a matrix
//and constructs a vector based on it, but it can't be called here
}
}
public bool Equals(Vector vector)
{
if (vector.Dimension != Dimension) return false;
bool check = true;
for (int i = 0; i < Matrix.Length; i++)
{
if (vector.Matrix[i] != Matrix[i]) check = false;
}
return check;
}
public override bool Equals(object obj)
{
return Equals(obj as Vector);
}
public override int GetHashCode()
{
unchecked
{
int hash = 19;
hash = (hash * 486187739) + ID.GetHashCode();
hash = (hash * 486187739) + Dimension.GetHashCode();
return hash;
}
}
public override string ToString()
{
if (Dimension < 4)
{
var stringBuilder = new StringBuilder();
for (int i = 0; i < Dimension; i++)
{
stringBuilder
.Append(Constants.AxisLetters[i])
.Append(": ")
.Append(Matrix[i]);
if (i != Dimension - 1) stringBuilder.Append(", ");
}
return stringBuilder.ToString();
}
else
{
throw new NotImplementedException();
}
}
}
}
And the inheriting class Vector2D:
using System;
using System.Text;
namespace PhysicsProblems
{
public class Vector2D : Vector
{
public double X
{
get { return Matrix[0]; }
set { Matrix[0] = value; }
}
public double Y
{
get { return Matrix[1]; }
set { Matrix[1] = value; }
}
public Vector2D(int dimension) : base(dimension)
{ }
public Vector2D(double[] matrix) : base(matrix)
{ }
}
}
A little disclaimer I consider important: I'm fairly OK with OOP and have some experience, however, I took up C# a week or two ago. Therefore, rookie mistakes are to be expected
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();
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 solve questions of C# programming in testdome.com, but I found problem about performance. How to solve it?
BinarySearchTree
using System;
public class Node
{
public int Value { get; set; }
public Node Left { get; set; }
public Node Right { get; set; }
public Node(int value, Node left, Node right)
{
Value = value;
Left = left;
Right = right;
}
}
public class BinarySearchTree
{
public static bool Contains(Node root, int value)
{
Console.WriteLine("value=" + value);
if(root == null)
return false;
else if(root.Value == value)
return true;
else if(root.Value != value)
{
return Contains(root.Left, value) | Contains(root.Right, value);
}
return false;
}
public static void Main(string[] args)
{
Node n1 = new Node(1, null, null);
Node n3 = new Node(3, null, null);
Node n2 = new Node(2, n1, n3);
Console.WriteLine(Contains(n2, 3));
}
}
Performance test on a large tree: Memory limit exceeded
https://www.testdome.com/for-developers/solve-question/7482
TwoSum
using System;
using System.Collections.Generic;
class TwoSum
{
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
for(int ctr1=0; ctr1<list.Count; ctr1++)
{
for(int ctr2=0; ctr2<list.Count; ctr2++)
{
if ((ctr1 != ctr2) && (list[ctr1]+list[ctr2] == sum))
return new Tuple<int, int>(ctr1, ctr2);
}
}
return null;
}
public static void Main(string[] args)
{
Tuple<int, int> indices = FindTwoSum(new List<int>() { 1, 3, 5, 7, 9 }, 12);
Console.WriteLine(indices.Item1 + " " + indices.Item2);
}
}
Performance test with a large number of elements: Time limit exceeded
https://www.testdome.com/for-developers/solve-question/8125
For the Binary search tree, testdome.com provides a hint "If a value being searched for is smaller than the value of the node, then the right subtree can be ignored." This cuts memory consumption by half.
public static bool Contains(Node root, int value) {
Console.WriteLine("value=" + value);
if (root == null) {
return false;
}
else if (value == root.Value) {
return true;
}
else if (value < root.Value) {
// Hint 2: If a value being searched for is smaller than the value of the node,
// then the right subtree can be ignored.
return Contains(root.Left, value);
}
else {
return Contains(root.Right, value);
}
return false;
}
For the TwoSum, if we assume that the values in the input array are unique, we can use a dictionary to look up an index by its value (in O(1) time). This relates to the hint "A dictionary can be used to store pre-calculated values, this may allow a solution with O(N) complexity."
// Write a function that, when passed a list and a target sum,
// returns, efficiently with respect to time used,
// two distinct zero-based indices of any two of the numbers,
// whose sum is equal to the target sum.
// If there are no two numbers, the function should return null.
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum) {
if (list.Count < 2) {
return null;
}
// Hint 2: A dictionary can be used to store pre-calculated values,
// this may allow a solution with O(N) complexity.
var indexByValue = new Dictionary<int, int>();
for (var i = 0; i < list.Count; i++) {
var value = list[i];
// ensure that the values used as keys are unique
// this is OK because we only have to return any tuple matching the sum,
// therefore we can ignore any duplicate values
if (!indexByValue.ContainsKey(value)) {
indexByValue.Add(value, i);
}
}
for (var j = 0; j < list.Count; j++) {
var remainder = sum - list[j];
if (indexByValue.ContainsKey(remainder)) {
return new Tuple<int, int> (j, indexByValue[remainder]);
}
}
return null;
}
Simpler way to attack the problem. The above answers are good, but think the desired result can be found quicker.
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
if (list.Count < 2) { return null; }
foreach (int i in list)
{
int result = sum - i;
if(list.Contains(result))
{
return new Tuple<int, int>(i, result);
}
}
return null;
}
For TwoSum, I found the below link that gives 100% pass on TestDome: Look for JonnyT's answer:
TwoSum 100% Pass
Below is the code as well:
PS: I am only providing this to help others, so please upvote JonnyT's answer instead of mine :)
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
HashSet<int> hs = new HashSet<int>();
for (int i = 0; i < list.Count; i++)
{
var needed = sum - list[i];
if (hs.Contains(needed))
{
return Tuple.Create(list.IndexOf(needed), i);
}
hs.Add(list[i]);
}
return null;
}
public static void Main(string[] args)
{
Tuple<int, int> indices = FindTwoSum(new List<int>() { 3, 1, 5, 7, 5, 9 }, 10);
if (indices != null)
{
Console.WriteLine(indices.Item1 + " " + indices.Item2);
}
}
// This passes all tests
public static bool Contains(Node root, int value)
{
var result = false;
if (root == null) return result;
if (value == root.Value)
{
result = true;
}
else
{
if(value <= root.Value)
{
if(Contains(root.Left, value))
{
result = true;
}
}
else
{
return Contains(root.Right, value);
}
}
return result;
}
For Twosum:
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
if (list.Count < 2)
{
return Tuple<int, int>(0,0);
}
for (var j = 0; j < list.Count; j++)
{
var remainder = sum - list[j];
if (list.Contains(remainder))
{
return new Tuple<int, int>(list[j], remainder);
}
}
return new Tuple<int, int>(0,0);
}
I recently designed a data structure similar to 'Queue' and 'Stack' for a special purpose, with a fixed maximum number of objects in it and when it is full and inserted, the first inserted object drops out.
The Code:
public class AssemblyLine<T>
{
private long length;
public long Length { get { return this.length; } }
private T[] data;
private long Pointer = 0;
private long count = 0;
public long Count { get { return this.count; } }
public void Insert(T obj)
{
this.Data[Pointer] = obj;
this.Next();
if (this.count < this.length)
this.count++;
}
public T[] GetLastX(long x)
{
long p = this.Pointer;
if (x > this.count)
x = this.count;
T[] result = new T[x];
for (int i = 0; i < x; i++)
{
Previous();
result[i] = Grab();
}
this.Pointer = p;
return result;
}
public T[] GetFirstX(long x)
{
long p = this.Pointer;
if (x > this.count)
x = this.count;
long gap = this.length - this.count;
this.Pointer = (this.Pointer + gap) % this.length;
T[] result = new T[x];
for (int i = 0; i < x; i++)
{
result[i] = Grab();
Next();
}
this.Pointer = p;
return result;
}
public void Clear()
{
this.data = new T[this.length];
this.count = 0;
}
private void Next()
{
this.Pointer++;
if (this.Pointer > this.length - 1)
this.Pointer = 0;
}
private void Previous()
{
this.Pointer--;
if (this.Pointer < 0)
this.Pointer = this.length - 1;
}
private T Grab()
{
return this.data[this.Pointer];
}
public AssemblyLine(long Length)
{
this.length = Length;
this.data = new T[Length];
}
}
Now I am curious if its possible to get that connected to Linq, providing something like this:
AssemblyLine<int> myAssemblyLine = new AssemblyLine(100);
// Insert some Stuff
List<int> myList = myAssemblyLine.Where(i => i > 5).ToList();
Any idea someone?
Almost all LINQ extension methods are declared on IEnumerable<T>, so as soon as your class implements that interface, you'll get it for free.
There are just couple methods that use non-generic IEnumerable, like Cast or OfType, but if you can get your class implement generic IEnumerable<T> it will be much better, because users won't have to call Cast<T> first, to get IEnumerable<T> and access all the other methods (as is right now the case for some legacy collections).
You have to implement IEnumerable<T> for .Where(). See Adding LINQ to my classes.
Once you implement IEnumerable<T> and all required methods, you will have access to these methods: http://msdn.microsoft.com/en-us/library/vstudio/system.linq.enumerable_methods(v=vs.100).aspx