2016년 8월 31일 수요일

C# User defined Enumerable

1, 2, 3, 4, 5....의 순으로 인수를 얻어오기 위한 방식은 간단합니다.

for (int k = 1; k <= 5; ++k)
{
    Console.WriteLine(p);
};


그런데 이를테면 2, 3, 5, 7, 11, ... 순으로 소수를 얻어오려면 IEnumerable을 사용하면 좀 더 간단히 할 수 있습니다. Iterator를 사용해서 말입니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PrimeNumber
{
    internal class PrimeNumber
    {
        List<int> m_Prime = new List<int>();

        internal IEnumerable<int> Prime()
        {
            m_Prime.Add(2);
            yield return 2; // 최초에 2 리턴

            for (int num = 3; ; num += 2)
            {
                // 소수 갯수가 100개 넘었다면 끝
                if (m_Prime.Count >= 100)
                    yield break;

                // 소수계산 공식
                bool isPrime = true;
                foreach (int p in m_Prime)
                {
                    if (num % p == 0)
                    {
                        isPrime = false;
                        break;
                    }
                    if (p * p > num)
                        break;
                }

                if (isPrime)
                {
                    m_Prime.Add(num);
                    yield return num; // 소수를 찾았으면 소수 리턴
                }
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            PrimeNumber prime = new PrimeNumber();
            foreach (var p in prime.Prime())
                Console.WriteLine(p);
        }
    }
}

어디서든지 yield return을 만나면 일단 리턴을 한 후, 다음 함수가 불리면 yield문 이후부터 다시 실행 시작합니다. 반면 yield break는 완전한 중지로 Main()의 foreach구문을 빠져나오게 됩니다.

소수찾기 루틴을 코딩하기가 복잡하다면? 다음과 같이 하면 됩니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PrimeNumber
{
    internal class PrimeNumber
    {
        List m_Prime = new List();

        internal IEnumerable<int> Prime()
        {
            yield return 2;
            yield return 3;
            yield return 5;
            yield return 7;
            yield return 11;
            yield return 13;
            yield return 17;
            yield return 19;
            yield return 23;
            yield return 29;
            yield return 31;
            yield return 37;
            yield return 41;
            yield return 43;
            yield return 47;
            yield return 53;
            yield return 59;
            yield return 61;
            yield return 67;
            yield return 71;
            yield return 73;
            yield return 79;
            yield return 83;
            yield return 89;
            yield return 97;
            yield return 101;
            yield return 103;
            yield return 107;
            yield return 109;
            yield return 113;
            yield return 127;
            yield return 131;
            yield return 137;
            yield return 139;
            yield return 149;
            yield return 151;
            yield return 157;
            yield return 163;
            yield return 167;
            yield return 173;
            yield return 179;
            yield return 181;
            yield return 191;
            yield return 193;
            yield return 197;
            yield return 199;
            yield return 211;
            yield return 223;
            yield return 227;
            yield return 229;
            yield return 233;
            yield return 239;
            yield return 241;
            yield return 251;
            yield return 257;
            yield return 263;
            yield return 269;
            yield return 271;
            yield return 277;
            yield return 281;
            yield return 283;
            yield return 293;
            yield return 307;
            yield return 311;
            yield return 313;
            yield return 317;
            yield return 331;
            yield return 337;
            yield return 347;
            yield return 349;
            yield return 353;
            yield return 359;
            yield return 367;
            yield return 373;
            yield return 379;
            yield return 383;
            yield return 389;
            yield return 397;
            yield return 401;
            yield return 409;
            yield return 419;
            yield return 421;
            yield return 431;
            yield return 433;
            yield return 439;
            yield return 443;
            yield return 449;
            yield return 457;
            yield return 461;
            yield return 463;
            yield return 467;
            yield return 479;
            yield return 487;
            yield return 491;
            yield return 499;
            yield return 503;
            yield return 509;
            yield return 521;
            yield return 523;
            yield return 541;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            PrimeNumber prime = new PrimeNumber();
            foreach (var p in prime.Prime())
                Console.WriteLine(p);
        }
    }
}

댓글 없음:

댓글 쓰기