2 つの Dictionary をひとつにまとめる
両方の Dictionary に同じキーが含まれる場合は、Sum()
で足し合わせます。
using System; using System.Collections.Generic; using System.Linq; class Program { static Dictionary<int, int> Add(Dictionary<int, int> a, Dictionary<int, int> b) { return a.Concat(b).GroupBy(e => e.Key, e => e.Value).ToDictionary(e => e.Key, e => e.Sum()); } static void Main() { var a = new Dictionary<int, int> { { 1, 2 }, { 2, 3 }, }; var b = new Dictionary<int, int> { { 0, 1 }, { 1, 1 }, { 2, 2 }, { 5, 0 }, }; var c = Add(a, b); foreach (var k in c.Keys.OrderBy(e => e)) { Console.WriteLine("key:{0} val:{1}", k, c[k]); } } }
実行結果です。
key:0 val:1 key:1 val:3 key:2 val:5 key:5 val:0
0,1,0,1,0,1... を繰り返すシーケンス
using System; using System.Collections.Generic; using System.Linq; class Program { static IEnumerable<int> ZeroOne() { int n = 0; while (true) { yield return n; n ^= 1; } } static void Main() { Console.WriteLine(string.Join(",", ZeroOne().Take(10))); // => 0,1,0,1,0,1,0,1,0,1 } }
実行結果です。
0,1,0,1,0,1,0,1,0,1
Pairs 関数
Python の
>>> [(i, j) for i in range(3) for j in range(3)] [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
のような各ペアを求める Pairs 関数を作成してみました。
using System; using System.Collections.Generic; using System.Linq; public static class Iter { static IEnumerable<T[]> Product_1<T>(int p, T[] buf, List<List<T>> pools) { if (p == buf.Length) { yield return buf; } else { foreach (var e in pools[p]) { buf[p] = e; foreach (var ret in Product_1(p+1, buf, pools)) { yield return ret; } } } } public static IEnumerable<T[]> Product<T>(IEnumerable<T> xs, int repeat = 1) { var pools = new List<List<T>>(Enumerable.Repeat(xs.ToList(), repeat)); return Product_1(0, new T[pools.Count], pools); } public static IEnumerable<T[]> Product<T>(IEnumerable<T> xs, IEnumerable<T> ys, int repeat = 1) { var ls = new List<List<T>> { xs.ToList(), ys.ToList() }; var pools = new List<List<T>>(Enumerable.Repeat(ls, repeat).SelectMany(e => e)); return Product_1(0, new T[pools.Count], pools); } public static IEnumerable<U> Pairs<T, U>(IEnumerable<T> xs, IEnumerable<T> ys, Func<T, T, U> fn) { foreach (var e in Product(xs, ys)) { var cs = e.ToArray(); yield return fn(cs[0], cs[1]); } } } class Program { static void Main() { var xs = new[] { 0, 1, 2 }; var ys = Iter.Pairs(xs, xs, (a, b) => Tuple.Create(a, b)); Console.WriteLine(string.Join(" ", ys)); // => (0, 0) (0, 1) (0, 2) (1, 0) (1, 1) (1, 2) (2, 0) (2, 1) (2, 2) } }
Product
を経由せずに、foreach で 2 重ループを回すほうが簡単ですが、Product
の応用を考えていて Pairs
を作れることが分かったので作ってみました。
リンク
Array.Clear() で 2 次元配列をクリアする
Array.Clear メソッドは、1 次元配列だけでなく、2 次元配列もクリアすることが出来ます。
using System; using System.Collections.Generic; using System.Linq; class Program { static void Display(int[,] ary) { for (int i = 0; i < ary.GetLength(0); i++) { for (int j = 0; j < ary.GetLength(1); j++) { Console.Write("{0} ", ary[i, j]); } Console.WriteLine(); } Console.WriteLine(); } static void Main() { var ary = new int[,] { { 1, 2, 3 }, { 4, 5, 6 }, }; Display(ary); // 1 2 3 // 4 5 6 Array.Clear(ary, 1, ary.Length - 1); // ary[0, 0] 以外をクリア Display(ary); // 1 0 0 // 0 0 0 Array.Clear(ary, 0, ary.Length); // 全ての要素をクリア Display(ary); // 0 0 0 // 0 0 0 } }
実行結果です。
1 2 3 4 5 6 1 0 0 0 0 0 0 0 0 0 0 0
リンク
Conditional 属性の練習
using System; using System.Diagnostics; class Program { [Conditional("TEST")] static void Foo() { Console.WriteLine("FOO!"); } static void Main() { Console.WriteLine("BEGIN"); Foo(); Console.WriteLine("END"); } }
実行結果です。
$ mcs -define:TEST a.cs && mono a.exe BEGIN FOO! END $ mcs a.cs && mono a.exe BEGIN END
リンク
Type からインスタンスを生成する
using System; class Foo { public void Say() { Console.WriteLine("Foo!"); } } class Bar { public Bar(int n, string s) { Console.WriteLine("n:{0} s:{1}", n, s); } public void Say() { Console.WriteLine("Bar!"); } } class Program { static void Main() { var foo = (Foo)Activator.CreateInstance(typeof(Foo)); foo.Say(); // Foo! Type barType = typeof(Bar); // typeof() は Type 型を返す var args = new object[] { 123, "bar" }; // Bar のコンストラクタ引数に渡す値 var bar = (Bar)Activator.CreateInstance(barType, args); bar.Say(); // Bar! } }
実行結果です。
Foo! n:123 s:bar Bar!
参考
SEND + MORE = MONEY
using System; using System.Collections.Generic; using System.Linq; class Program { static int ToInt(string s, int[] map) { int x = 0; foreach (var c in s) { x = 10 * x + map[c]; if (x == 0 && s.Length > 1) return -1; // leading zero } return x; } static void Solve_1(int p, char[] cs, int used, int[] map, string[] ss) { if (p == cs.Length) { var a = ss.Take(ss.Length - 1).Select(e => ToInt(e, map)); if (a.Contains(-1)) return; // 不正な変換結果 int b = ToInt(ss.Last(), map); if (a.Sum() == b) { Console.WriteLine("{0} = {1}", string.Join(" + ", ss.Take(ss.Length - 1)), ss.Last()); Console.WriteLine("{0} = {1}", string.Join(" + ", a), b); } return; } for (int i = 0; i < 10; i++) { if ((used & (1 << i)) != 0) continue; map[cs[p]] = i; // cs[p] に i を割り当てる Solve_1(p + 1, cs, used | (1 << i), map, ss); } } static void Solve(params string[] ss) { var cs = new HashSet<char>(ss.SelectMany(e => e)).ToArray(); if (cs.Length > 10) throw new Exception(); // 10 種類より多いと数字を割り当てられない var map = new int[128]; // どの文字にどの数字を割り当てたか Solve_1(0, cs, 0, map, ss); Console.WriteLine(); } static void Main() { Solve("SEND", "MORE", "MONEY"); Solve("CROSS", "ROADS", "DANGER"); Solve("SIX", "SEVEN", "SEVEN", "TWENTY"); } }
実行結果です。
$ time mono a.exe SEND + MORE = MONEY 9567 + 1085 = 10652 CROSS + ROADS = DANGER 96233 + 62513 = 158746 SIX + SEVEN + SEVEN = TWENTY 650 + 68782 + 68782 = 138214 mono a.exe 5.38s user 0.03s system 99% cpu 5.419 total