ソース
public class hash2d : IEquatable<hash2d> { public long[,] array2d; public hash2d(long[,] a) { array2d = new long[a.GetLength(0), a.GetLength(1)]; Array.Copy(a, array2d, a.Length); } public override bool Equals(object obj) => Equals(obj as hash2d); public bool Equals(hash2d other) { return other != null && this.array2d.Cast<long>().SequenceEqual(other.array2d.Cast<long>()); } public override int GetHashCode() { return (int)array2d.Cast<long>().Aggregate(0L ,(acc, i) => unchecked(acc * 457 + i * 389)); } }
使い方&結果
var h1 = new hash2d(new long[2, 2] { { 1, 2 }, { 3, 4 } }); var h2 = new hash2d(new long[2, 2] { { 1, 2 }, { 3, 4 } }); var h3 = new hash2d(new long[2, 2] { { 5, 6 }, { 7, 8 } }); var h4 = new hash2d(new long[2, 2] { { 2, 1 }, { 3, 4 } }); WriteLine("HashCode"); WriteLine("\th1:"+h1.GetHashCode()); WriteLine("\th2:"+h2.GetHashCode()); WriteLine("\th3:"+h3.GetHashCode()); WriteLine("\th4:"+h4.GetHashCode()); WriteLine("\nEquals"); WriteLine("\th1-h2:"+h1.Equals(h2)); WriteLine("\th1-h3:"+h3.Equals(h1)); WriteLine("\th1-h4:"+h4.Equals(h1)); var hs = new HashSet<hash2d>(); hs.Add(h1); WriteLine("\nHashSet"); WriteLine("\th1-h2:"+hs.Contains(h2)); WriteLine("\th1-h3:"+hs.Contains(h3)); WriteLine("\th1-h4:"+hs.Contains(h4)); //結果 HashCode h1:-1363972990 h2:-1363972990 h3:1443673746 h4:1322759658 Equals h1-h2:True h1-h3:False h1-h4:False HashSet h1-h2:True h1-h3:False h1-h4:False
参考
小ネタ
longの二次元配列をintの一次元配列にする
var a = new long[2, 2] { { 1, 2 }, { 3, 4 } }; . var b = a.Cast<long>().Select(i => (int)i).ToArray(); > b int[4] { 1, 2, 3, 4 }
参考
二次元配列をコピー
public long[,] array2d; public hash2d(long[,] a) { array2d = new long[a.GetLength(0), a.GetLength(1)]; Array.Copy(a, array2d, a.Length); }
参考
Dictionary
,HashSet
の仕組み
(1)まずGetHashCodeメソッドで、ハッシュ値が同じかを調べる
(2)ハッシュ値が同じときは、Equalsメソッドでオブジェクトの同値性を調べる
1と2が同じだったら、同じと判断する。
A hash code is a numeric value that is used to insert and identify an object in a hash-based collection such as the Dictionary<TKey,TValue> class, the Hashtable class, or a type derived from the DictionaryBase class.
Dictionary<TKey,TValue> requires an equality implementation to determine whether keys are equal. You can specify an implementation of the IEqualityComparer
generic interface by using a constructor that accepts a comparer parameter; if you do not specify an implementation, the default generic equality comparer EqualityComparer .Default is used.
適当に確認
Equals
はTrue
を返すようにする
public bool Equals(hash2d other) { return true; } HashCode h1:-1363972990 h2:-1363972990 h3:1443673746 h4:1322759658 Equals h1-h2:True h1-h3:True h1-h4:True HashSet h1-h2:True h1-h3:False h1-h4:False
GetHashCode
が同じ値を返すようにする
public override int GetHashCode() { return 0; } HashCode h1:0 h2:0 h3:0 h4:0 Equals h1-h2:True h1-h3:False h1-h4:False HashSet h1-h2:True h1-h3:False h1-h4:False
両方
public bool Equals(hash2d other) { return true; } public override int GetHashCode() { return 0; } HashCode h1:0 h2:0 h3:0 h4:0 Equals h1-h2:True h1-h3:True h1-h4:True HashSet h1-h2:True h1-h3:True h1-h4:True
背景
螺旋本の8パズルやってたら配列でHashSet
使いたくなった。螺旋本終わったらAtCoder再開する。
先日蟻本買ったのだけど。昨日今日あたりからセールしてるっぽい。ぽい・・・。