ローマ数字とアラビア数字間のLINQコンバーター

彼はLINQの学生と小学生を扱っていて、ローマ数字システムとアラビア数字システム間の変換を扱っていたことが判明しました。 その結果、考えが混乱し、興味深いコンバーターコードが判明しました。これは、ローカルアーカイブに埋めるのは残念です。 この例は、LINQを理解するための演習として機能します。



したがって、ローマ数字の要素をアラビア語と比較する辞書が必要です。



Dictionary<int, string> ra = new Dictionary<int, string> { { 1000, "M" }, { 900, "CM" }, { 500, "D" }, { 400, "CD" }, { 100, "C" }, { 90 , "XC" }, { 50 , "L" }, { 40 , "XL" }, { 10 , "X" }, { 9 , "IX" }, { 5 , "V" }, { 4 , "IV" }, { 1 , "I" } };
      
      





このディクショナリを使用すると、ローマ表記からアラビア表記へ、またはその逆のコンバータを作成できます。 簡潔さと美しさのために、前提条件を処理しません。 アラビア数字の場合、有効な範囲は[1.4000)として定義されています。 また、ローマ数字は正しく、大文字に変換する必要があります。



アラビア語からローマへのコンバーター



数値の分析は、大きな数値から始めます。 辞書のキーは降順で並べられます。 それらを指定された順序で見ると、最大で変換可能な数値(Where演算子)の値を持つ最初のキーが見つかります。 辞書では、この数字はローマ数字システムの文字通りの組み合わせに関連付けられています。 見つかった文字の組み合わせに、再帰的に変換された数値の残りの部分を貼り付けます(Select演算子)。 最初の結果は、ローマ字表記の数値の望ましい表現になります(演算子FirstOrDefault)。



 string ToRoman(int number) => ra .Where(d => number >= d.Key) .Select(d => d.Value + ToRoman(number - d.Key)) .FirstOrDefault();
      
      





ローマからアラビア語へのコンバーター



ローマ数字の解析は左から右へです。 変換された文字列number.StartsWith(d.Value)の先頭にある辞書のすべての文字の組み合わせを調べます。 一致する場合、キーフィールドには文字の組み合わせに対応する数値が含まれます。 結果の値は、再帰的に処理される残りの行に追加されます。



 int ToArabic(string number) => number.Length == 0 ? 0 : ra .Where(d => number.StartsWith(d.Value)) .Select(d => d.Key + ToArabic(number.Substring(d.Value.Length))) .FirstOrDefault();
      
      





コピーアンドペーストv1の準備ができたクラス
 static class RomanNum { // (c) 2015, Alexey Danov | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY ... static Dictionary<int, string> ra = new Dictionary<int, string> { { 1000, "M" }, { 900, "CM" }, { 500, "D" }, { 400, "CD" }, { 100, "C" }, { 90 , "XC" }, { 50 , "L" }, { 40 , "XL" }, { 10 , "X" }, { 9 , "IX" }, { 5 , "V" }, { 4 , "IV" }, { 1 , "I" } }; public static string ToRoman(int number) => ra .Where(d => number >= d.Key) .Select(d => d.Value + ToRoman(number - d.Key)) .FirstOrDefault(); public static int ToArabic(string number) => number.Length == 0 ? 0 : ra .Where(d => number.StartsWith(d.Value)) .Select(d => d.Key + ToArabic(number.Substring(d.Value.Length))) .First(); }
      
      





これは停止する可能性があります。 しかし、499という数字は、CDXCIX、LDVLIV、XDIX、VDIV、またはIDの5つの方法で記述できることがわかりました。 短いレコードの場合、辞書で指定されていない組み合わせを使用できます。 辞書を展開できますが、数字(1,5,10,50,100,500,1000)に対応する元の文字IVXLCDMからのみ開始できます。



VCレベル(VC == 95)の.Netマジシャンのスキルを引き出すために、辞書が自動的に生成されます。 そして、得られたコードを使用して、ICレベルの魔術師の.Netスクールへの入学テストで、他の人のコードを読み取るスキルをテストできます。



バインディングを使用したローマからアラビア語へのコンバータ



辞書を生成するには、外部変数を使用する必要がありました。 コメントなしのコード。



 int o = 1; string w = "IVXLCDM"; Dictionary<char, int> ra = w.ToDictionary(ch => ch, ch => (o = ("" + o)[0] == '1' ? o * 2 : o * 5) / 2); int ToArabic(string num) => num.Select((c, i) => ++i < num.Length && ra[c] < ra[num[i]] ? -ra[c] : ra[c]).Sum();
      
      





アラブからローマへのコンバーター



しかし、簡潔にするために、ローマのシステムへの翻訳には、いくつかの補助機能が必要でした。 関数自体にそれらを含めることができますが、ヒープを取得します。



 string W(int k, int l = 1) => w.Substring(k, l); string R(char m, int k) => m == '9' ? W(k-2)+W(k) : m == '5' ? W(k-1) : m == '4' ? W(k-2, 2) : W(k-2); string ToRoman(int num) => num < 1 ? "" : (from z in "000100101".Split('1') from m in "9541" select m + z) .Where(z => num >= (o = int.Parse(z))) .Select(z => R(z[0], z.Length * 2)).First() + ToRoman(num - o);
      
      







コピー&ペーストv2の準備ができたクラス
 static class RomanNumEx { // (c) 2015, Alexey Danov | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY ... static int o = 1; static string w = "IVXLCDM"; static Dictionary<char, int> ra = w.ToDictionary(ch => ch, ch => (o = ("" + o)[0] == '1' ? o * 2 : o * 5) / 2); public static int ToArabic(string num) => num .Select((c, i) => ++i < num.Length && ra[c] < ra[num[i]] ? -ra[c] : ra[c]).Sum(); static string W(int k, int l = 1) => w.Substring(k, l); static string R(char m, int k) => m == '9' ? W(k-2)+W(k) : m == '5' ? W(k-1) : m == '4' ? W(k-2, 2) : W(k-2); public static string ToRoman(int num) => num < 1 ? "" : (from z in "000100101".Split('1') from m in "9541" select m + z) .Where(z => num >= (o = int.Parse(z))) .Select(z => R(z[0], z.Length * 2)).First() + ToRoman(num - o); }
      
      





これらの例は速度が最適とはほど遠いですが、使用できます。 そして何よりも、LINQの基本を学習する際に。



All Articles