クイズ
Brad Abrams氏のところから。
・http://blogs.msdn.com/brada/archive/2004/10/29/249607.aspx
複数の配列の任意部分の合計を求める。
using System; using System.Collections.Generic; struct MyArraySegment<T> { readonly T arr; readonly int offset; readonly int count; public MyArraySegment(T arr, int offset, int count) { this.arr = arr; this.offset = offset; this.count = count; } public T this[int index] { get { return arr[offset + index]; } } public int Count { get { return count; } } // 型変換 ArraySegment -> MyArraySegment public static implicit operator MyArraySegment<T>(ArraySegment<T> arr) { return new MyArraySegment<T>(arr.Array, arr.Offset, arr.Count); } } class Program { static IEnumerable<T> Range<T>(T arr, int start, int count) { for (int i = start; i < start + count; ++i) yield return arr[i]; } static IEnumerable<T> Concat<T>(params IEnumerable<T> args) { foreach (IEnumerable<T> e in args) foreach (T t in e) yield return t; } static int Sum(IEnumerable<int> e) { int ret = 0; foreach (int n in e) ret += n; return ret; } static int Sum(params ArraySegment<int> args) { int ret = 0; foreach (ArraySegment<int> arr in args) for (int i = arr.Offset; i < arr.Offset + arr.Count; ++i) ret += arr.Array[i]; // ※ MyArraySegmentへ型変換しています // ↓これが出来たほうが便利なのに・・・ ret = 0; foreach (MyArraySegment<int> arr in args) for (int i = 0; i < arr.Count; ++i) ret += arr[i]; return ret; } static void Main(string args) { int set1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int set2 = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 }; int set3 = { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 }; int set4 = { 1, 1, 2, 3, 5, 8, 13, 21 }; int set5 = { 2, 3, 5, 7, 11, 13, 17, 19 }; int set6 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // 回答 Console.WriteLine(Sum( new ArraySegment<int>(set1, 0, 1), new ArraySegment<int>(set2, 0, 1), new ArraySegment<int>(set3, 0, 1), new ArraySegment<int>(set4, 0, 1), new ArraySegment<int>(set5, 0, 1), new ArraySegment<int>(set6, 0, 1))); // こっちの方が好み(パフォーマンス悪いけど) Console.WriteLine(Sum(Concat( Range(set1, 0, 1), Range(set2, 0, 1), Range(set3, 0, 1), Range(set4, 0, 1), Range(set5, 0, 1), Range(set6, 0, 1)))); Console.Read(); } }
ArraySegmentの使い方が趣旨ですが、微妙に使いにくい気も。IEnumeratableなどをサポートしていないのは構わないのですが、インデクサくらいは欲しかったかも。あと、本題とは関係ありませんが、explicit/implicitって初めて使いました。というか、存在を知りませんでした。(^^;