100までの素数を求めるプログラム(2)
akirameiさんに反応いただき,LINQを用いた解き方をご自身の日記にされてました.
http://d.hatena.ne.jp/akiramei/20060217
天才ですねー.これの後に自分のプログラムを見せるのは非常に気まずいのですが,まぁ書きっぱなしというのもアレなので,とりあえず笑ってくださいな.
ただその前に……
エレガントってなに?
ふたたびakirameiさんの日記より,
ちなみにネタ優先なのでアルゴリズム的には無駄があります。(^^;
素数の作成といえばエラトステネスの篩いなんかが有名ですが,自分が今回"エレガント"という言葉を使った意図としては,そのような
アルゴリズム・効率性としての美しさ ではなく,
むしろ
いかに簡単な記法・記述で目的が達成できるか
を考えたいというところにありました.
akirameiさんの解法はGetPrimesメソッドが2行(実質1行)という点で,まさに理想的です(まさかLINQとは思いませんでしたが(^^;).
リファクタリング Start
まずは,
static bool IsPrime(int target, List<int> primeList) { foreach (int prime in primeList) { if (target % prime == 0) return false; } return true; }
について考えます.このメソッドはある数(:target)が素数リスト(:primeList)で割り切れるかを調べるものですが,一般化して考えると,
あるリストの中に,ある条件に含まれる要素が存在するかを調べるもの(=メソッド)
ということになります.そのような目的のために,List
static bool IsPrime(int target, List<int> primeList) { return !primeList.Exists(delegate(int j) { return target % j == 0; } ); }
引数にはAnonymous Methodを使いました.このExistsメソッドの使い方だと素数でないときにtrueが返るので,真偽値を反転したものをIsPrimeの戻り値としています.
ここまでくれば,GetPrimesメソッドでIsPrimeメソッドを使用している箇所をインライン展開できます.最終的には以下のようになりました.(Mainメソッドは修正不要なのですが,akirameiさんにインスパイアされ,ついでに変更してみました)
class Program { static List<int> GetPrimes(int maxNum) { List<int> primeList = new List<int>(); primeList.Add(2); for (int i = 3; i <= maxNum; i++) { if (!primeList.Exists(delegate(int j) { return i % j == 0; } )) { primeList.Add(i); } } return primeList; } static void Main(string[] args) { foreach (int prime in GetPrimes(100)) { Console.Write("{0},", prime); } Console.WriteLine(@" 「素数」は1と自分の数でしか割ることのできない孤独な数字…… わたしに勇気を与えてくれる"); } }
いまの自分にはこれが精いっぱいかな.もっとうまいやり方となると……LINQ??
[2/19 追記]
さらにakirameiさんより,拡張メソッド(Extention Method : C# 3.0の新機能)を使った改良版がアップされました.
http://d.hatena.ne.jp/akiramei/20060219
勉強になりますねー.多謝.
最後のConsole.WriteLine
これって,
- 作者: 小川洋子
- 出版社/メーカー: 新潮社
- 発売日: 2003/08/28
- メディア: 単行本
- 購入: 20人 クリック: 1,593回
- この商品を含むブログ (723件) を見る
akirameiさんはサンプルにさりげなくネタ(例えば,http://d.hatena.ne.jp/akiramei/20060123/p1)を仕込んでくるので要注意(?)です.