<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>ohyecloudy's training notes</title>
	
	<link>http://ohyecloudy.com/algo</link>
	<description>알고리즘 수련을 위한 블로그</description>
	<lastBuildDate>Sun, 08 Jan 2012 13:48:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/algo" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="algo" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>ACM 10196 (Uva ID) : Check The Check</title>
		<link>http://ohyecloudy.com/algo/archives/39?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=acm-10196-uva-id-check-the-check</link>
		<comments>http://ohyecloudy.com/algo/archives/39#comments</comments>
		<pubDate>Wed, 07 Apr 2010 22:00:49 +0000</pubDate>
		<dc:creator>ohyecloudy</dc:creator>
				<category><![CDATA[Volume CI]]></category>
		<category><![CDATA[ad hoc]]></category>
		<category><![CDATA[simulation]]></category>

		<guid isPermaLink="false">http://ohyecloudy.com/algo/?p=39</guid>
		<description><![CDATA[문제 링크 : http://uva.onlinejudge.org/external/101/10196.html 응시 유저 수 : 2805 해결한 유저 비율 :76.11% &#160; 모든 체스 말을 기준으로 계산해도 되고 검정, 흰 King을 중심으로 이 녀석이 공격을 받는지 검사해도 된다. 난 King을 중심으로 공격을 받는지를 검사했다. 좀 더 다듬으면 Queen, Rook, Bishop을 검사할 때 중복되는 부분을 제거할 수 있다. 더 다듬고 줄이니 코드가 더 읽기 [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li>문제 링크 : <a href="http://uva.onlinejudge.org/external/101/10196.html" target="_blank">http://uva.onlinejudge.org/external/101/10196.html</a></li>
<li>응시 유저 수 : 2805</li>
<li>해결한 유저 비율 :76.11%</li>
</ul>
<p><a href="https://picasaweb.google.com/lh/photo/3LfRCQLYx109635uGpmcshjKjL_S5HiV0-13YIuHFbQ?feat=embedwebsite"><img src="https://lh5.googleusercontent.com/-ZHEKU6-hc-8/TwmXInzNs7I/AAAAAAAAJxY/oveIBUab1-o/s640/temp_3.png" alt="" width="640" height="43" /></a></p>
<p><span id="more-39"></span></p>
<p>&nbsp;</p>
<p>모든 체스 말을 기준으로 계산해도 되고 검정, 흰 King을 중심으로 이 녀석이 공격을 받는지 검사해도 된다. 난 King을 중심으로 공격을 받는지를 검사했다.</p>
<p>좀 더 다듬으면 Queen, Rook, Bishop을 검사할 때 중복되는 부분을 제거할 수 있다. 더 다듬고 줄이니 코드가 더 읽기 힘들어져서 이 정도로 마무리.</p>
<p>유닛 테스트하다가 올릴 뻔했다. 조낸 귀찮음. 저렇게까지 테스트할 필요가 있을까? 아니다. 크롬 소스를 보니 저거보다 더 심하더라. 이건 아직 계속 경험해보는 게 좋은 단계라서 뭐라 하기 힘들다.</p>
<p>&nbsp;</p>
<p>소스 코드</p>
<pre class="brush:cpp">////////////////////////////////////////////////////////////////////////////////
// UVa Online Judge(http://uva.onlinejudge.org/)
//
// problem : 10196 Check The Check
//           (http://uva.onlinejudge.org/external/101/10196.html)
//
// - OOP, Unit test, STL을 남발한다.
// - 속도보다는 읽기 좋게 작성한다.
//
// This file is licenced under a Creative Commons license:
// http://creativecommons.org/licenses/by-nc-sa/2.0/kr/
////////////////////////////////////////////2010. 04. 07 ohyecloudy at gmail.com
//////////////////////////////////////////////////////http://ohyecloudy.com/algo

#ifdef ONLINE_JUDGE
#   define UNIT_TEST 0
#else
#   define UNIT_TEST 1
#endif 

#if UNIT_TEST
#    include &lt;gtest/gtest.h&gt;
#    include &lt;sstream&gt;
#endif

#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;string&gt;
#include &lt;algorithm&gt;

//#############################################################################V
// submit code

////////////////////////////////////////////////////////////////////////////////
struct PieceColor
{
	enum Type
	{
		BLACK,
		WHITE,
	};
};

struct Piece
{
	enum Type
	{
	    EMPTY			= '.',
		INVALID			= '#',

		BLACK_PAWN		= 'p',
		BLACK_ROOK		= 'r',
		BLACK_BISHOP	= 'b',
		BLACK_QUEEN		= 'q',
		BLACK_KING		= 'k',
		BLACK_KNIGHT	= 'n',

		WHITE_PAWN		= 'P',
		WHITE_ROOK		= 'R',
		WHITE_BISHOP	= 'B',
		WHITE_QUEEN		= 'Q',
		WHITE_KING		= 'K',
		WHITE_KNIGHT	= 'N',
	};
};

////////////////////////////////////////////////////////////////////////////////
class ChessBoard
{
public:
    //--------------------------------------------------------------------------
    ChessBoard()
    {
        m_configuration.resize(BOARD_EXTENT);
        for (Configuration::iterator iter = m_configuration.begin();
            iter != m_configuration.end(); ++iter)
        {
            iter-&gt;resize(BOARD_EXTENT);
        }

        ClearBoard();
    }

    //--------------------------------------------------------------------------
    void        Load(std::istream&amp; ist)
    {
        ClearBoard();

        char input;
        for (int i = 0; i &lt; BOARD_EXTENT; ++i)
        {
            for (int j = 0; j &lt; BOARD_EXTENT; ++j)
            {
                ist &gt;&gt; input;
				m_configuration[j][i] = static_cast&lt;Piece::Type&gt;(input);
                TestAndUpdateKing(j, i);
            }
        }
    }

    //--------------------------------------------------------------------------
    std::string    CheckTheCheck()
    {
        std::string colorInCheck = "no";

        // there won't be a configuration where both kings are in check.
        if (IsInCheck(m_whiteKing.first, m_whiteKing.second, PieceColor::BLACK))
        {
            colorInCheck = "white";
        }
        else if (
			IsInCheck(m_blackKing.first, m_blackKing.second, PieceColor::WHITE))
        {
            colorInCheck = "black";
        }

        return colorInCheck + " king is in check.";
    }

    //--------------------------------------------------------------------------
    bool        IsInCheck(int x, int y, PieceColor::Type attack) const
    {
        return
            IsPawnAttack(x, y, attack) ||
            IsRookAttack(x, y, attack) ||
            IsBishopAttack(x, y, attack) ||
            IsQueenAttack(x, y, attack) ||
            IsKnightAttack(x, y, attack);
    }

    //--------------------------------------------------------------------------
    bool        ExistBothKings() const
    {
        return
            m_blackKing.first != INVALID_COORD &amp;&amp;
			m_blackKing.second != INVALID_COORD &amp;&amp;
            m_whiteKing.first != INVALID_COORD &amp;&amp;
			m_whiteKing.second != INVALID_COORD;
    }

    //--------------------------------------------------------------------------
	void        PlacePiece(int x, int y, Piece::Type piece)
    {
        m_configuration[x][y] = piece;
        TestAndUpdateKing(x, y);
    }

    //--------------------------------------------------------------------------
    void        ClearBoard()
    {
        m_blackKing = Coord(INVALID_COORD, INVALID_COORD);
        m_whiteKing = Coord(INVALID_COORD, INVALID_COORD);

        for( Configuration::iterator iter = m_configuration.begin();
            iter != m_configuration.end(); ++iter )
        {
            ConfigurationCol&amp; col = *iter;
            std::fill(col.begin(), col.end(), Piece::EMPTY);
        }
    }

    //--------------------------------------------------------------------------
    bool        IsPawnAttack(int x, int y, PieceColor::Type attack) const
    {
        if (attack == PieceColor::BLACK)
        {
            if (Piece::BLACK_PAWN == GetPiece( x+1, y-1 ) ||
                Piece::BLACK_PAWN == GetPiece( x-1, y-1 ))
            {
                return true;
            }
        }
        else
        {
            if (Piece::WHITE_PAWN == GetPiece( x+1, y+1 ) ||
                Piece::WHITE_PAWN == GetPiece( x-1, y+1 ))
            {
                return true;
            }
        }

        return false;
    }

    //--------------------------------------------------------------------------
    bool        IsRookAttack(int x, int y, PieceColor::Type attack) const
    {
        char piece = Piece::BLACK_ROOK;
        if (attack == PieceColor::WHITE)
        {
            piece = Piece::WHITE_ROOK;
        }

        if (piece == GetFirstPiece( x, y,  0, -1 ))        return true;
        if (piece == GetFirstPiece( x, y,  0,  1 ))        return true;
        if (piece == GetFirstPiece( x, y, -1,  0 ))        return true;
        if (piece == GetFirstPiece( x, y,  1,  0 ))        return true;

        return false;
    }

    //--------------------------------------------------------------------------
    bool        IsBishopAttack(int x, int y, PieceColor::Type attack) const
    {
        char piece = Piece::BLACK_BISHOP;
        if (attack == PieceColor::WHITE)
        {
            piece = Piece::WHITE_BISHOP;
        }

        if (piece == GetFirstPiece( x, y, -1, -1 ))        return true;
        if (piece == GetFirstPiece( x, y,  1, -1 ))        return true;
        if (piece == GetFirstPiece( x, y, -1,  1 ))        return true;
        if (piece == GetFirstPiece( x, y,  1,  1 ))        return true;

        return false;
    }

    //--------------------------------------------------------------------------
    bool        IsQueenAttack(int x, int y, PieceColor::Type attack) const
    {
        char piece = Piece::BLACK_QUEEN;
        if (attack == PieceColor::WHITE)
        {
            piece = Piece::WHITE_QUEEN;
        }

        if (piece == GetFirstPiece( x, y,  0, -1 ))        return true;
        if (piece == GetFirstPiece( x, y,  0,  1 ))        return true;
        if (piece == GetFirstPiece( x, y, -1,  0 ))        return true;
        if (piece == GetFirstPiece( x, y,  1,  0 ))        return true;
        if (piece == GetFirstPiece( x, y, -1, -1 ))        return true;
        if (piece == GetFirstPiece( x, y,  1, -1 ))        return true;
        if (piece == GetFirstPiece( x, y, -1,  1 ))        return true;
        if (piece == GetFirstPiece( x, y,  1,  1 ))        return true;

        return false;
    }

    //--------------------------------------------------------------------------
    bool        IsKnightAttack(int x, int y, PieceColor::Type attack) const
    {
        char piece = Piece::BLACK_KNIGHT;
        if (attack == PieceColor::WHITE)
        {
            piece = Piece::WHITE_KNIGHT;
        }

        if (piece == GetPiece( x-1,    y-2 ))            return true;
        if (piece == GetPiece( x+1,    y-2 ))            return true;
        if (piece == GetPiece( x-2,    y-1 ))            return true;
        if (piece == GetPiece( x+2,    y-1 ))            return true;
        if (piece == GetPiece( x-2,    y+1 ))            return true;
        if (piece == GetPiece( x+2,    y+1 ))            return true;
        if (piece == GetPiece( x-1,    y+2 ))            return true;
        if (piece == GetPiece( x+1,    y+2 ))            return true;

        return false;
    }

private:
    //--------------------------------------------------------------------------
	Piece::Type		GetPiece(int x, int y) const
    {
        if (x &lt; 0 || x &gt;= BOARD_EXTENT)    return Piece::INVALID;
        if (y &lt; 0 || y &gt;= BOARD_EXTENT)    return Piece::INVALID;

        return m_configuration[x][y];
    }

    //--------------------------------------------------------------------------
    const Piece::Type	GetFirstPiece(int startX, int startY, int dx, int dy) const
    {
        if (dx == 0 &amp;&amp; dy == 0)            return GetPiece(startX, startY);

        int curX = startX + dx;
        int curY = startY + dy;

        Piece::Type current = Piece::INVALID;
        while ((current = GetPiece(curX, curY)) != Piece::INVALID)
        {
            if (current != Piece::EMPTY)
            {
                return current;
            }

            curX += dx;
            curY += dy;
        }

        return current;
    }

    //--------------------------------------------------------------------------
    void        TestAndUpdateKing(int x, int y)
    {
		if (Piece::WHITE_KING == m_configuration[x][y])
        {
            m_whiteKing.first = x;
            m_whiteKing.second = y;
        }
		else if (Piece::BLACK_KING == m_configuration[x][y])
        {
            m_blackKing.first = x;
            m_blackKing.second = y;
        }
    }

private:
	typedef std::vector&lt;Piece::Type&gt;         ConfigurationCol;
    typedef std::vector&lt;ConfigurationCol&gt;    Configuration;
    Configuration                            m_configuration;

    typedef std::pair&lt;int, int&gt;              Coord;
    Coord                                    m_blackKing;
    Coord                                    m_whiteKing;

	static const int INVALID_COORD;
    static const int BOARD_EXTENT;
};

const int ChessBoard::INVALID_COORD		= -1;
const int ChessBoard::BOARD_EXTENT		= 8;

//#############################################################################A

#if UNIT_TEST
//#############################################################################V
// test code
TEST( piece_attack, pawn )
{
    ChessBoard board;

    {
        //........
        //p.......
        //.*......
        board.ClearBoard();
        board.PlacePiece( 0, 1, Piece::BLACK_PAWN );
        ASSERT_TRUE( board.IsPawnAttack( 1, 2, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsPawnAttack( 2, 2, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsPawnAttack( 0, 1, PieceColor::BLACK ) );
    }

    {
        //.p......
        //*.*.....
        board.ClearBoard();
        board.PlacePiece( 1, 0, Piece::BLACK_PAWN );
        ASSERT_TRUE( board.IsPawnAttack( 0, 1, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsPawnAttack( 2, 1, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsPawnAttack( 1, 1, PieceColor::BLACK ) );
    }

    {
        //.......p
        //......*.
        board.ClearBoard();
        board.PlacePiece( 7, 0, Piece::BLACK_PAWN );
        ASSERT_TRUE( board.IsPawnAttack( 6, 1, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsPawnAttack( 7, 1, PieceColor::BLACK ) );
    }

    {
        //.*......
        //P.......
        board.ClearBoard();
        board.PlacePiece( 0, 1, Piece::WHITE_PAWN );
        ASSERT_TRUE( board.IsPawnAttack( 1, 0, PieceColor::WHITE ) );
        ASSERT_FALSE( board.IsPawnAttack( 0, 1, PieceColor::WHITE ) );
    }
}

TEST( piece_attack, rook )
{
    ChessBoard board;

    {
        //...*....
        //...*....
        //...*....
        //...*....
        //***r****
        //...*....
        //...*....
        //...*....

        board.ClearBoard();
        board.PlacePiece( 3, 4, Piece::BLACK_ROOK );
        ASSERT_TRUE( board.IsRookAttack( 3, 0, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsRookAttack( 3, 1, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsRookAttack( 3, 2, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsRookAttack( 3, 3, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsRookAttack( 3, 5, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsRookAttack( 3, 6, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsRookAttack( 3, 7, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsRookAttack( 0, 4, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsRookAttack( 1, 4, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsRookAttack( 2, 4, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsRookAttack( 5, 4, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsRookAttack( 6, 4, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsRookAttack( 7, 4, PieceColor::BLACK ) );

        ASSERT_FALSE( board.IsRookAttack( 3, 4, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsRookAttack( 0, 0, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsRookAttack( 7, 7, PieceColor::BLACK ) );
    }

    {
        //...*....
        //...p....
        //........
        //........
        //*p.r..p*
        //........
        //...p....
        //...*....

        board.ClearBoard();
        board.PlacePiece( 3, 4, Piece::BLACK_ROOK );
        board.PlacePiece( 3, 1, Piece::BLACK_PAWN );
        board.PlacePiece( 3, 6, Piece::BLACK_PAWN );
        board.PlacePiece( 1, 4, Piece::BLACK_PAWN );
        board.PlacePiece( 6, 4, Piece::BLACK_PAWN );
        ASSERT_FALSE( board.IsRookAttack( 3, 0, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsRookAttack( 3, 7, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsRookAttack( 0, 4, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsRookAttack( 0, 7, PieceColor::BLACK ) );
    }
}

TEST( piece_attack, bishop )
{
    ChessBoard board;

    {
        //.......*
        //*.....*.
        //.*...*..
        //..*.*...
        //...b....
        //..*.*...
        //.*...*..
        //*.....*.

        board.ClearBoard();
        board.PlacePiece( 3, 4, Piece::BLACK_BISHOP );

        ASSERT_TRUE( board.IsBishopAttack( 0, 1, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsBishopAttack( 1, 2, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsBishopAttack( 2, 3, PieceColor::BLACK ) );

        ASSERT_TRUE( board.IsBishopAttack( 7, 0, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsBishopAttack( 6, 1, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsBishopAttack( 5, 2, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsBishopAttack( 4, 3, PieceColor::BLACK ) );

        ASSERT_TRUE( board.IsBishopAttack( 2, 5, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsBishopAttack( 1, 6, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsBishopAttack( 0, 7, PieceColor::BLACK ) );

        ASSERT_TRUE( board.IsBishopAttack( 4, 5, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsBishopAttack( 5, 6, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsBishopAttack( 6, 7, PieceColor::BLACK ) );

        ASSERT_FALSE( board.IsBishopAttack( 3, 3, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsBishopAttack( 0, 0, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsBishopAttack( 2, 1, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsBishopAttack( 7, 7, PieceColor::BLACK ) );
    }

    {
        //.......*
        //*.......
        //.p...p..
        //........
        //...b....
        //........
        //.r...r..
        //*.....*.

        board.ClearBoard();
        board.PlacePiece( 3, 4, Piece::BLACK_BISHOP );
        board.PlacePiece( 1, 2, Piece::BLACK_PAWN );
        board.PlacePiece( 5, 2, Piece::BLACK_PAWN );
        board.PlacePiece( 1, 6, Piece::BLACK_ROOK );
        board.PlacePiece( 5, 6, Piece::BLACK_ROOK );

        ASSERT_FALSE( board.IsBishopAttack( 0, 1, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsBishopAttack( 7, 0, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsBishopAttack( 0, 7, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsBishopAttack( 6, 7, PieceColor::BLACK ) );
    }
}

TEST( piece_attack, queen )
{
    ChessBoard board;

    {
        //...*...*
        //*..*..*.
        //.*.*.*..
        //..***...
        //***q****
        //..***...
        //.*.*.*..
        //*..*..*.

        board.ClearBoard();
        board.PlacePiece( 3, 4, Piece::BLACK_QUEEN );

        ASSERT_TRUE( board.IsQueenAttack( 0, 1, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 1, 2, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 2, 3, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 7, 0, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 6, 1, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 5, 2, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 4, 3, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 2, 5, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 1, 6, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 0, 7, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 4, 5, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 5, 6, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 6, 7, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 3, 0, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 3, 1, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 3, 2, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 3, 3, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 3, 5, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 3, 6, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 3, 7, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 0, 4, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 1, 4, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 2, 4, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 5, 4, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 6, 4, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsQueenAttack( 7, 4, PieceColor::BLACK ) );

        ASSERT_FALSE( board.IsQueenAttack( 0, 3, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsQueenAttack( 0, 0, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsQueenAttack( 2, 1, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsQueenAttack( 7, 7, PieceColor::BLACK ) );
    }

    {
        //...*...*
        //*.......
        //........
        //..ppp...
        //*p.q.p.*
        //........
        //.p.p.p..
        //*..*..*.

        board.ClearBoard();
        board.PlacePiece( 3, 4, Piece::BLACK_QUEEN );
        board.PlacePiece( 1, 4, Piece::BLACK_PAWN );
        board.PlacePiece( 5, 4, Piece::BLACK_PAWN );
        board.PlacePiece( 2, 3, Piece::BLACK_PAWN );
        board.PlacePiece( 3, 3, Piece::BLACK_PAWN );
        board.PlacePiece( 4, 3, Piece::BLACK_PAWN );
        board.PlacePiece( 1, 6, Piece::BLACK_PAWN );
        board.PlacePiece( 3, 6, Piece::BLACK_PAWN );
        board.PlacePiece( 5, 6, Piece::BLACK_PAWN );

        ASSERT_FALSE( board.IsQueenAttack( 0, 1, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsQueenAttack( 3, 0, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsQueenAttack( 7, 0, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsQueenAttack( 0, 3, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsQueenAttack( 7, 3, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsQueenAttack( 0, 7, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsQueenAttack( 3, 7, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsQueenAttack( 6, 7, PieceColor::BLACK ) );
    }
}

TEST( piece_attack, knight )
{
    ChessBoard board;

    {
        //........
        //........
        //..*p*...
        //.*ppp*..
        //..pnp...
        //.*ppp*..
        //..*p*...
        //........

        board.ClearBoard();
        board.PlacePiece( 3, 4, Piece::BLACK_KNIGHT );
        board.PlacePiece( 3, 2, Piece::BLACK_PAWN );
        board.PlacePiece( 2, 3, Piece::BLACK_PAWN );
        board.PlacePiece( 3, 3, Piece::BLACK_PAWN );
        board.PlacePiece( 4, 3, Piece::BLACK_PAWN );
        board.PlacePiece( 2, 4, Piece::BLACK_PAWN );
        board.PlacePiece( 4, 4, Piece::BLACK_PAWN );
        board.PlacePiece( 2, 5, Piece::BLACK_PAWN );
        board.PlacePiece( 3, 5, Piece::BLACK_PAWN );
        board.PlacePiece( 4, 5, Piece::BLACK_PAWN );
        board.PlacePiece( 3, 6, Piece::BLACK_PAWN );

        ASSERT_TRUE( board.IsKnightAttack( 2, 2, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsKnightAttack( 4, 2, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsKnightAttack( 1, 3, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsKnightAttack( 5, 3, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsKnightAttack( 1, 5, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsKnightAttack( 5, 5, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsKnightAttack( 2, 6, PieceColor::BLACK ) );
        ASSERT_TRUE( board.IsKnightAttack( 4, 6, PieceColor::BLACK ) );

        ASSERT_FALSE( board.IsKnightAttack( 1, 2, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsKnightAttack( 2, 1, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsKnightAttack( 5, 2, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsKnightAttack( 1, 6, PieceColor::BLACK ) );
        ASSERT_FALSE( board.IsKnightAttack( 5, 6, PieceColor::BLACK ) );
    }
}

TEST( check_the_check, sample )
{
    {
        //..k.....
        //ppp.pppp
        //........
        //.R...B..
        //........
        //........
        //PPPPPPPP
        //K.......

        std::stringstream ss;
        ss &lt;&lt; "..k....." &lt;&lt; std::endl;
        ss &lt;&lt; "ppp.pppp" &lt;&lt; std::endl;
        ss &lt;&lt; "........" &lt;&lt; std::endl;
        ss &lt;&lt; ".R...B.." &lt;&lt; std::endl;
        ss &lt;&lt; "........" &lt;&lt; std::endl;
        ss &lt;&lt; "........" &lt;&lt; std::endl;
        ss &lt;&lt; "PPPPPPPP" &lt;&lt; std::endl;
        ss &lt;&lt; "K......." &lt;&lt; std::endl;

        ChessBoard board;
        board.Load( ss );
        ASSERT_STREQ( "black king is in check.", board.CheckTheCheck().c_str() );
    }

    {
        //rnbqkbnr
        //pppppppp
        //........
        //........
        //........
        //........
        //PPPPPPPP
        //RNBQKBNR

        std::stringstream ss;
        ss &lt;&lt; "rnbqkbnr" &lt;&lt; std::endl;
        ss &lt;&lt; "pppppppp" &lt;&lt; std::endl;
        ss &lt;&lt; "........" &lt;&lt; std::endl;
        ss &lt;&lt; "........" &lt;&lt; std::endl;
        ss &lt;&lt; "........" &lt;&lt; std::endl;
        ss &lt;&lt; "........" &lt;&lt; std::endl;
        ss &lt;&lt; "PPPPPPPP" &lt;&lt; std::endl;
        ss &lt;&lt; "RNBQKBNR" &lt;&lt; std::endl;

        ChessBoard board;
        board.Load( ss );
        ASSERT_STREQ( "no king is in check.", board.CheckTheCheck().c_str() );
    }

    {
        //rnbqk.nr
        //ppp..ppp
        //....p...
        //...p....
        //.bPP....
        //.....N..
        //PP..PPPP
        //RNBQKB.R

        std::stringstream ss;
        ss &lt;&lt; "rnbqk.nr" &lt;&lt; std::endl;
        ss &lt;&lt; "ppp..ppp" &lt;&lt; std::endl;
        ss &lt;&lt; "....p..." &lt;&lt; std::endl;
        ss &lt;&lt; "...p...." &lt;&lt; std::endl;
        ss &lt;&lt; ".bPP...." &lt;&lt; std::endl;
        ss &lt;&lt; ".....N.." &lt;&lt; std::endl;
        ss &lt;&lt; "PP..PPPP" &lt;&lt; std::endl;
        ss &lt;&lt; "RNBQKB.R" &lt;&lt; std::endl;

        ChessBoard board;
        board.Load( ss );
        ASSERT_STREQ( "white king is in check.", board.CheckTheCheck().c_str() );
    }
}

//#############################################################################A
int main(int argc, char **argv)
{
    testing::InitGoogleTest(&amp;argc, argv);
    return RUN_ALL_TESTS();
}
#else
int main()
{
    //#########################################################################V
    // submit code

	int gameCount = 1;
	ChessBoard board;
	board.Load(std::cin);

	while (board.ExistBothKings())
	{
		std::cout &lt;&lt; "Game #" &lt;&lt; gameCount &lt;&lt; ": "
			&lt;&lt; board.CheckTheCheck() &lt;&lt; std::endl;

		// 한줄을 꿀꺽
		std::string dump;
		std::getline(std::cin, dump);

		board.Load(std::cin);
		++gameCount;
	}

    //#########################################################################A
    return 0;
}
#endif</pre>
<p>&nbsp;</p>
<p>아주 먼 옛날 짠 소스 코드</p>
<pre class="brush:cpp">//////////////////////////////////////////////////////////////////////////
// Check The Check (UVa ID : 10196)
//
// Ohyecloudy ( Ohyecloudy@gmail.com )
// Accepted.

#include &lt;iostream&gt;

using namespace std ;

enum { BLACK_KING = 0, WHITE_KING = 32} ;
const int CHESS_BOARD_SIZE = 8 ;

char chessBoard[8][8] ;

bool isValid(int x, int y)
{
	if ( x &lt; 0 || x &gt; CHESS_BOARD_SIZE-1 || y &lt; 0 || y &gt; CHESS_BOARD_SIZE-1 )
		return false ;

	return true ;
}

char getChessPin(int x, int y)
{
	if ( !isValid(x,y) )
		return NULL ;

	return chessBoard[y][x] ;
}

bool pieceDiagonal( int cking, char pin, int x, int y )
{
	int theta = 1 ;

	if ( cking == WHITE_KING )
		theta = -1 ;

	if ( getChessPin(x-1, y+theta) == pin + cking )
		return true ;
	if ( getChessPin(x+1, y+theta) == pin + cking )
		return true ;

	return false ;
}

bool lShape( int cking, int pin, int x, int y )
{
	for ( int i = -2 ; i &lt;= 2 ; i++ )
	{
		for ( int j = -2 ; j &lt;=2 ; j++ )
		{
			if ( (i == j) || i == 0 || j == 0 || ( i == -1 * j ) )
				continue ;

			if ( getChessPin( x+i, y+j ) == pin + cking )
				return true ;
		}
	}

	return false ;
}

bool diagonally( int cking, int pin, int x , int y )
{
	int fact = 1 ;

	for ( int i = 1 ; i &gt;= -1 ; i = i-2 )
	{
		for ( int j = 1 ; j &gt;= -1 ; j = j-2 )
		{
			while ( getChessPin( x + i*fact, y + j*fact ) == '.' )
				fact++ ;

			if ( getChessPin( x + i*fact, y + j*fact ) == pin + cking )
				return true ;

			fact = 1 ;
		}
	}

	return false ;
}

bool horNVer( int cking, int pin, int x, int y )
{
	int fact = 1 ;

	for ( int i = -1 ; i &lt;= 1 ; i++ )
	{
		for ( int j = -1 ; j &lt;= 1 ; j++ )
		{
			if ( i != 0 &amp;&amp; j != 0 || ( i == 0 &amp;&amp; j == 0 ) )
				continue ;

			while ( getChessPin( x + i*fact , y + j*fact ) == '.' )
				fact++ ;

			if ( getChessPin( x + i*fact , y + j*fact ) == pin + cking)
				return true ;

			fact = 1 ;
		}
	}

	return false ;
}

bool isCheck(int cking, int x, int y)
{
	// Pawn
	if (pieceDiagonal( cking, 'P' , x, y ))
		return true ;

	// Rook
	if (horNVer( cking, 'R', x, y ))
		return true ;

	// Bishop
	if (diagonally( cking, 'B', x , y ))
		return true ;

	// Queen
	if (diagonally( cking, 'Q', x , y ) || horNVer( cking, 'Q', x, y ) )
		return true ;

	// Knight
	if (lShape( cking, 'N', x, y ))
		return true ;

	return false ;
}

main()
{
	int wKing[2] ;
	int bKing[2] ;
	int ID = 1 ;

	bool isEnd = false ;

	while (!isEnd)
	{
		isEnd = true ;

		for ( int i = 0 ; i &lt; 8 ; ++i )
		{
			for ( int j = 0 ; j &lt; 8 ; ++j )
			{
				cin &gt;&gt; chessBoard[i][j] ;

				if ( chessBoard[i][j] == 'k' )
				{
					bKing[0] = j ;
					bKing[1] = i ;

					isEnd = false ;
				}
				else if ( chessBoard[i][j] == 'K' )
				{
					wKing[0] = j ;
					wKing[1] = i ;

					isEnd = false ;
				}
			}
		}

		if (!isEnd)
		{
			cin.ignore(100,'\n') ; // eat one line.

			if ( isCheck(WHITE_KING, wKing[0], wKing[1] ) )
				cout &lt;&lt; "Game #" &lt;&lt; ID &lt;&lt; ": white king is in check." &lt;&lt; endl ;
			else if ( isCheck(BLACK_KING, bKing[0], bKing[1] ) )
				cout &lt;&lt; "Game #" &lt;&lt; ID &lt;&lt; ": black king is in check." &lt;&lt; endl ;
			else
				cout &lt;&lt; "Game #" &lt;&lt; ID &lt;&lt; ": no king is in check." &lt;&lt; endl ;

			ID++ ;
		}
	}
}</pre>
<p>&nbsp;</p>
<div class="acc_license"><a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"><img src="http://i.creativecommons.org/l/by-nc-sa/3.0/88x31.png" alt="by-nc-sa" /></a></div><!--<rdf:RDF xmlns="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><Work rdf:about=""><license rdf:resource="http://creativecommons.org/licenses/by-nc-sa/3.0/" /></Work><License rdf:about="http://creativecommons.org/licenses/by-nc-sa/3.0/"><requires rdf:resource="http://creativecommons.org/ns#Attribution" /><permits rdf:resource="http://creativecommons.org/ns#Reproduction" /><permits rdf:resource="http://creativecommons.org/ns#Distribution" /><permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /><requires rdf:resource="http://creativecommons.org/ns#ShareAlike" /><prohibits rdf:resource="http://creativecommons.org/ns#CommercialUse" /><requires rdf:resource="http://creativecommons.org/ns#Notice" /></License></rdf:RDF>-->]]></content:encoded>
			<wfw:commentRss>http://ohyecloudy.com/algo/archives/39/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ACM 10033 (Uva ID) : Interpreter</title>
		<link>http://ohyecloudy.com/algo/archives/37?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=acm-10033-uva-id-interpreter</link>
		<comments>http://ohyecloudy.com/algo/archives/37#comments</comments>
		<pubDate>Tue, 06 Oct 2009 22:00:37 +0000</pubDate>
		<dc:creator>ohyecloudy</dc:creator>
				<category><![CDATA[Volume C]]></category>
		<category><![CDATA[ad hoc]]></category>
		<category><![CDATA[simulation]]></category>

		<guid isPermaLink="false">http://ohyecloudy.com/algo/?p=37</guid>
		<description><![CDATA[문제 링크 : http://uva.onlinejudge.org/external/100/10033.html 응시 유저 수 : 3002 해결한 유저 비율 :68.79% &#160; 예전에 배웠던 어셈블리 생각이 나는 문제다. 문제에 적힌 대로 instruction들을 차례대로 RAM에 적재하고 나서 program counter를 0에서부터 진행하면 된다. 점프할 때 점프하고. 빈 줄 처리를 위해 getline()을 사용했다. 이렇게 되면 instruction을 int로 선언했기 때문에 변환이 필요한데, stringstream을 사용해서 변환했다. PS : [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li>문제 링크 : <a href="http://uva.onlinejudge.org/external/100/10033.html" target="_blank">http://uva.onlinejudge.org/external/100/10033.html</a></li>
<li>응시 유저 수 : 3002</li>
<li>해결한 유저 비율 :68.79%</li>
</ul>
<p><img src="https://lh6.googleusercontent.com/-OKqB2Maletc/TwmU5mQiboI/AAAAAAAAJxQ/zoLRqbsXOE8/s640/2009-10-05_16_41_00.png" alt="" width="640" height="44" /></p>
<p><span id="more-37"></span></p>
<p>&nbsp;</p>
<p>예전에 배웠던 <strong>어셈블리 생각이 나는 문제</strong>다. 문제에 적힌 대로 instruction들을 차례대로 RAM에 적재하고 나서 program counter를 0에서부터 진행하면 된다. 점프할 때 점프하고.</p>
<p>빈 줄 처리를 위해 getline()을 사용했다. 이렇게 되면 instruction을 int로 선언했기 때문에 변환이 필요한데, stringstream을 사용해서 변환했다.</p>
<p>PS : 유닛 테스트 감을 익혀가고 있는데, 이 문제는 모든 instruction을 테스트하지 않았다. 레지스터와 램 값을 볼 수 있는 함수를 추가해서 instruction들을 테스트할까 말까 고민하다가 단위가 너무 작아서 넘어갔다.</p>
<p>&nbsp;</p>
<p>소스 코드</p>
<pre class="brush:cpp">////////////////////////////////////////////////////////////////////////////////
// UVa Online Judge(http://uva.onlinejudge.org/)
//
// problem : 10033 Interpreter (http://uva.onlinejudge.org/external/100/10033.html)
//
// - OOP, Unit test, STL을 남발한다.
// - 속도보다는 읽기 좋게 작성한다.
//
// This file is licenced under a Creative Commons license:
// http://creativecommons.org/licenses/by-nc-arg2/2.0/kr/
////////////////////////////////////////////2009. 10. 05 ohyecloudy at gmail.com
//////////////////////////////////////////////////////http://ohyecloudy.com/algo

#ifdef ONLINE_JUDGE
#   define UNIT_TEST 0
#else
#   define UNIT_TEST 1
#endif  

#if UNIT_TEST
#	include &lt;gtest/gtest.h&gt;
#endif

#include &lt;vector&gt;
#include &lt;sstream&gt;
#include &lt;iostream&gt;
#include &lt;string&gt;

//#############################################################################V
// submit code

////////////////////////////////////////////////////////////////////////////////
class Value
{
public:
	Value()	: m_value( 0 )			{}
	Value( int value )				{ Set( value ); }
	~Value()						{}

	// All results are reduced modulo 1000.
	void	Set( int value )		{ m_value = value % 1000; }
	int		Get() const				{ return m_value; }

private:
	int m_value;
};

////////////////////////////////////////////////////////////////////////////////
class Interpreter
{
public:
	//--------------------------------------------------------------------------
	Interpreter()			{}

	//--------------------------------------------------------------------------
	~Interpreter()			{}

	//--------------------------------------------------------------------------
	void	LoadInstruction( int instruction )
	{
		m_ram.push_back( Value(instruction) );
	}

	//--------------------------------------------------------------------------
	int		Execute()
	{
		// register와 ram 사이즈를 제한 사항에 맞춘다.
		m_register.resize( 10 );
		m_ram.resize( 1000 );

		int pc = 0;		// program counter
		int execCount = 0;

		for( ;; )
		{
			pc = ExecuteInstruction( m_ram[pc].Get(), pc );
			execCount++;
			if( pc == -1  )
			{
				break;
			}
		}

		return execCount;
	}

	//--------------------------------------------------------------------------
	int		ExecuteInstruction( int instruction, int currentPc )
	{
		int opCode = 1;
		int arg1 = 0;
		int arg2 = 0;
		ParseInstruction( instruction, opCode, arg1, arg2 );

		int nextPc = currentPc + 1;

		switch( opCode )
		{
		case 1:
			// 100 means halt
			nextPc = -1;
			break;

		case 2:
			// 2dn means set register d to n (between 0 and 9)
			m_register[arg1].Set( arg2 );
			break;

		case 3:
			// 3dn means add n to register d
			m_register[arg1].Set( m_register[arg1].Get() + arg2 );
			break;

		case 4:
			// 4dn means multiply register d by n
			m_register[arg1].Set( m_register[arg1].Get() * arg2 );
			break;

		case 5:
			// 5ds means set register d to the value of register s
			m_register[arg1].Set( m_register[arg2].Get() );
			break;

		case 6:
			// 6ds means add the value of register s to register d
			m_register[arg1].Set(
				m_register[arg1].Get() + m_register[arg2].Get() );
			break;

		case 7:
			// 7ds means multiply register d by the value of register s
			m_register[arg1].Set(
				m_register[arg1].Get() * m_register[arg2].Get() );
			break;

		case 8:
			{
				// 8da means set register d to the value in RAM
				// whose address is in register a
				int ramAddr = m_register[arg2].Get();
				m_register[arg1].Set( m_ram[ramAddr].Get() );
			}
			break;

		case 9:
			{
				// 9sa means set the value in RAM
				// whose address is in register a to the value of register s
				int ramAddr = m_register[arg2].Get();
				m_ram[ramAddr].Set( m_register[arg1].Get() );
			}
			break;

		case 0:
			{
				// 0ds means goto the location in register d
				// unless register s contains 0
				if( m_register[arg2].Get() != 0 )
				{
					nextPc = m_register[arg1].Get();
				}
			}
			break;
		}

		return nextPc;
	}

	static void	ParseInstruction( int inst, int&amp; opCode, int&amp; arg1, int&amp; arg2 )
	{
		opCode = inst / 100;
		arg1 = (inst - opCode * 100 ) / 10;		// first argument
		arg2 = inst - opCode * 100 - arg1 * 10;	// second argument
	}

private:
	std::vector&lt;Value&gt;				m_register;
	std::vector&lt;Value&gt;				m_ram;
};
//#############################################################################A

#if UNIT_TEST
//#############################################################################V
// test code
TEST( register, value_modulo_1000 )
{
	Value reg;
	reg.Set( 500 );
	ASSERT_EQ( reg.Get(), 500 );
	reg.Set( 1023 );
	ASSERT_EQ( reg.Get(), 23 );
}

TEST( interpreter, parse_instruction )
{
	int opCode, arg1, arg2;

	{
		Interpreter::ParseInstruction( 999, opCode, arg1, arg2 );
		ASSERT_EQ( opCode, 9 );
		ASSERT_EQ( arg1, 9 );
		ASSERT_EQ( arg2, 9 );
	}

	{
		Interpreter::ParseInstruction( 23, opCode, arg1, arg2 );
		ASSERT_EQ( opCode, 0 );
		ASSERT_EQ( arg1, 2 );
		ASSERT_EQ( arg2, 3 );
	}

	{
		Interpreter::ParseInstruction( 0, opCode, arg1, arg2 );
		ASSERT_EQ( opCode, 0 );
		ASSERT_EQ( arg1, 0 );
		ASSERT_EQ( arg2, 0 );
	}
}

TEST( interpreter, sample )
{
	Interpreter interpreter;
	interpreter.LoadInstruction(299);
	interpreter.LoadInstruction(492);
	interpreter.LoadInstruction(495);
	interpreter.LoadInstruction(399);
	interpreter.LoadInstruction(492);
	interpreter.LoadInstruction(495);
	interpreter.LoadInstruction(399);
	interpreter.LoadInstruction(283);
	interpreter.LoadInstruction(279);
	interpreter.LoadInstruction(689);
	interpreter.LoadInstruction(78);
	interpreter.LoadInstruction(100);
	interpreter.LoadInstruction(0);
	interpreter.LoadInstruction(0);
	interpreter.LoadInstruction(0);

	ASSERT_EQ( interpreter.Execute(), 16 );
}

//#############################################################################A
int main(int argc, char **argv)
{
	testing::InitGoogleTest(&amp;argc, argv);
	return RUN_ALL_TESTS();
}
#else
//#############################################################################V
// submit code

int ToInteger( const std::string&amp; str )
{
	int integer;

	std::stringstream ss;
	ss &lt;&lt; str;
	ss &gt;&gt; integer;

	return integer;
}

int main()
{
	std::string input;
	std::getline( std::cin, input );
	int caseCount = ToInteger( input );

	// case count와 첫번째 case 사이 빈줄을 꿀꺽.
	std::getline( std::cin, input );

	for( int i = 0; i &lt; caseCount; ++i )
	{
		Interpreter interpreter;
		int instruction = 0;

		// 빈 줄이 나올때까지 명령을 RAM에 적재한다.
		while( std::getline( std::cin, input ) &amp;&amp; !input.empty() )
		{
			instruction = ToInteger( input );
			interpreter.LoadInstruction( instruction );
		}

		std::cout &lt;&lt; interpreter.Execute() &lt;&lt; std::endl;

		// 답 사이에 공백이 있어야 한다.
		if( i + 1 &lt; caseCount )
		{
			std::cout &lt;&lt; std::endl;
		}
	}

	return 0;
}
//#############################################################################A
#endif</pre>
<p>&nbsp;</p>
<p>언젠지 기억도 안 나는 소스 코드</p>
<pre class="brush:cpp">//////////////////////////////////////////////////////////////////////////
// Interpreter (UVa ID : 10033)
//
// Ohyecloudy ( Ohyecloudy@gmail.com )
// Accepted.

#include &lt;iostream&gt;
#include &lt;cmath&gt;

using namespace std ;

int registers[10] ;
int RAM[1000] ;

void setRegisters(int address, int value)
{
	registers[address] = value % 1000 ;
}

int getRegisters(int address)
{
	return registers[address] ;
}

void setRAM(int address, int value)
{
	RAM[address] = value % 1000 ;
}

int getRAM(int address)
{
	return RAM[address] ;
}

void init()
{
	for ( int i = 0 ; i &lt; 10 ; ++i )
		registers[i] = 0 ;

	for ( int j = 0 ; j &lt; 1000 ; ++j )
		RAM[j] = 0 ;
}

int execute()
{
	int pc = 0 ;
	int nExe = 0 ;
	int ins ;
	int temp = 0 ;
	int temp2 = 0 ;

	while ( RAM[pc] != 100 )
	{
		ins = RAM[pc] ;
		int secPara = (ins % 100) / 10;
		int thiPara = (ins % 10) ;

		switch ( ins / 100 )
		{
		case 2:
			setRegisters( secPara, thiPara ) ;
			nExe++ ;
			pc++ ;
			break ;

		case 3:
			temp = getRegisters( secPara ) ;
			setRegisters( secPara, temp + thiPara ) ;
			nExe++ ;
			pc++ ;
			break ;

		case 4:
			temp = getRegisters( secPara ) ;
			setRegisters( secPara, temp * thiPara ) ;
			pc++ ;
			nExe++ ;
			break ;

		case 5:
			temp = getRegisters( thiPara ) ;
			setRegisters( secPara, temp ) ;
			pc++ ;
			nExe++ ;
			break ;

		case 6:
			temp = getRegisters( thiPara ) ;
			temp2 = getRegisters( secPara ) ;
			setRegisters( secPara, temp + temp2 ) ;
			pc++ ;
			nExe++ ;
			break ;

		case 7:
			temp = getRegisters( secPara ) ;
			temp2 = getRegisters( thiPara ) ;
			setRegisters( secPara, temp * temp2 ) ;
			pc++ ;
			nExe++ ;
			break ;

		case 8:
			temp = getRAM ( getRegisters( thiPara ) ) ;
			setRegisters( secPara, temp ) ;
			pc++ ;
			nExe++ ;
			break ;

		case 9:
			temp = getRegisters( thiPara ) ;
			temp2 = getRegisters( secPara ) ;
			setRAM( temp, temp2 ) ;
			pc++ ;
			nExe++ ;
			break ;

		case 0:
			temp = getRegisters( thiPara ) ;
			bool isContainZero = false ;

			if ( temp == 0 )
				isContainZero = true ;

			if ( !isContainZero )
				pc = getRegisters( secPara ) ;
			else
				pc++ ;

			nExe++ ;

			break ;
		} // end switch
	} // end while

	return nExe + 1 ; // 1 is halt instruction
}

main()
{
	int nCase ;
	char input[4] ;
	int inputLoc = 0 ;
	int toInt = 0 ;

	cin.getline(input,4) ;
	nCase = (int)(input[0]-'0') ;

	cin.ignore(100, '\n') ; // eat one line

	for ( int i = 0 ; i &lt; nCase ; ++i )
	{
		init() ;
		inputLoc = 0 ;

		while (1)
		{
			cin.getline(input, 4) ;

			if ( input[0] == NULL )
				break ;

			for ( int i = 0 ; i &lt; 3 ; ++i )
				toInt += (input[i]  - '0')*pow(10,2-i) ;

			RAM[inputLoc] = toInt ;
			toInt = 0 ;
			inputLoc++ ;
		}

		cout &lt;&lt; execute() &lt;&lt; endl ;

		if ( i != nCase-1 )
			cout &lt;&lt; endl ;
	}
}</pre>
<p>&nbsp;</p>
<div class="acc_license"><a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"><img src="http://i.creativecommons.org/l/by-nc-sa/3.0/88x31.png" alt="by-nc-sa" /></a></div><!--<rdf:RDF xmlns="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><Work rdf:about=""><license rdf:resource="http://creativecommons.org/licenses/by-nc-sa/3.0/" /></Work><License rdf:about="http://creativecommons.org/licenses/by-nc-sa/3.0/"><requires rdf:resource="http://creativecommons.org/ns#Attribution" /><permits rdf:resource="http://creativecommons.org/ns#Reproduction" /><permits rdf:resource="http://creativecommons.org/ns#Distribution" /><permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /><requires rdf:resource="http://creativecommons.org/ns#ShareAlike" /><prohibits rdf:resource="http://creativecommons.org/ns#CommercialUse" /><requires rdf:resource="http://creativecommons.org/ns#Notice" /></License></rdf:RDF>-->]]></content:encoded>
			<wfw:commentRss>http://ohyecloudy.com/algo/archives/37/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ACM 10267 (Uva ID) : Graphical Editor</title>
		<link>http://ohyecloudy.com/algo/archives/34?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=acm-10267-uva-id-graphical-editor</link>
		<comments>http://ohyecloudy.com/algo/archives/34#comments</comments>
		<pubDate>Mon, 05 Oct 2009 22:00:53 +0000</pubDate>
		<dc:creator>ohyecloudy</dc:creator>
				<category><![CDATA[Volume CII]]></category>
		<category><![CDATA[ad hoc]]></category>
		<category><![CDATA[simulation]]></category>

		<guid isPermaLink="false">http://ohyecloudy.com/algo/?p=34</guid>
		<description><![CDATA[문제 링크 : http://uva.onlinejudge.org/external/102/10267.html 응시 유저 수 : 2406 해결한 유저 비율 : 59.06% &#160; 리전을 채우는 명령어인 F는 그림판에 있는 색 채우기를 생각하면 된다. 간단하게 구현한다면 재귀 호출(recursive call)이나 큐(queue)를 사용하면 된다. 난 queue를 사용해서 해결. 딱딱 명령어가 나누어져 있어서 유닛 테스트를 연습하기에 딱 좋쿠나. PS : 이거 예제가 너무 마음에 안 든다. 사실 [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li>문제 링크 : <a href="http://uva.onlinejudge.org/external/102/10267.html" target="_blank">http://uva.onlinejudge.org/external/102/10267.html</a></li>
<li>응시 유저 수 : 2406</li>
<li>해결한 유저 비율 : 59.06%</li>
</ul>
<p><img src="https://lh6.googleusercontent.com/-0SP9dpySw14/TwmS9CgsvKI/AAAAAAAAJxI/39XYELZrRk0/s640/2009-10-05_11_23_12.png" alt="" width="640" height="46" /></p>
<p><span id="more-34"></span></p>
<p>&nbsp;</p>
<p>리전을 채우는 명령어인 <strong>F는 그림판에 있는 색 채우기</strong>를 생각하면 된다. 간단하게 구현한다면 재귀 호출(recursive call)이나 큐(queue)를 사용하면 된다. 난 queue를 사용해서 해결.</p>
<p>딱딱 명령어가 나누어져 있어서 유닛 테스트를 연습하기에 딱 좋쿠나.</p>
<p>PS : 이거 예제가 너무 마음에 안 든다. 사실 색 채우기 명령어가 이 문제에서 핵심인데, 예제에서 이 명령어가 어떻게 동작하는지 자세히 나오지 않는다. 한번 죽어보라는 거지.</p>
<p>&nbsp;</p>
<p>소스 코드</p>
<pre class="brush:cpp">////////////////////////////////////////////////////////////////////////////////
// UVa Online Judge(http://uva.onlinejudge.org/)
//
// problem : 10267 Graphical Editor (http://uva.onlinejudge.org/external/102/10267.html)
//
// - OOP, Unit test, STL을 남발한다.
// - 속도보다는 읽기 좋게 작성한다.
//
// This file is licenced under a Creative Commons license:
// http://creativecommons.org/licenses/by-nc-sa/2.0/kr/
////////////////////////////////////////////2009. 10. 05 ohyecloudy at gmail.com
//////////////////////////////////////////////////////http://ohyecloudy.com/algo
#ifdef ONLINE_JUDGE
#   define UNIT_TEST 0
#else
#   define UNIT_TEST 1
#endif  

#if UNIT_TEST
#	include &lt;gtest/gtest.h&gt;
#	include &lt;strstream&gt;
#endif

#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt;
#include &lt;string&gt;
#include &lt;limits&gt;
#include &lt;deque&gt;

//#############################################################################V
// submit code
////////////////////////////////////////////////////////////////////////////////
// 좌표는 외부에서 zero-based index로 건내줘야 한다.
class GraphicalEditor
{
public:
	//--------------------------------------------------------------------------
	explicit GraphicalEditor( int width = 0, int height = 0 )
	{
		CreateTable( width, height );
	}

	//--------------------------------------------------------------------------
	~GraphicalEditor()	{}

	//--------------------------------------------------------------------------
	void CreateTable( int width, int height )
	{
		m_bitmapWidth = width;
		m_bitmapHeight = height;

		ResizeTable();
		ClearTable();
	}

	//--------------------------------------------------------------------------
	void ClearTable()
	{
		for( Bitmap::iterator iter = m_bitmap.begin();
			iter != m_bitmap.end(); ++iter )
		{
			BitmapCol&amp; bitmapCol = *iter;
			std::fill( bitmapCol.begin(), bitmapCol.end(), 'O' );
		}
	}

	//--------------------------------------------------------------------------
	void DrawPixel( int x, int y, char color )
	{
		m_bitmap[x][y] = color;
	}

	//--------------------------------------------------------------------------
	void DrawVertical( int x, int y1, int y2, char color )
	{
		int lowerY = std::min( y1, y2 );
		int upperY = std::max( y1, y2 );

		for( int i = lowerY; i &lt;= upperY; ++i )
		{
			m_bitmap[x][i] = color;
		}
	}

	//--------------------------------------------------------------------------
	void DrawHorizontal( int x1, int x2, int y, char color )
	{
		int leftX = std::min( x1, x2 );
		int rightX = std::max( x1, x2 );

		for( int i = leftX; i &lt;= rightX; ++i )
		{
			m_bitmap[i][y] = color;
		}
	}

	//--------------------------------------------------------------------------
	void DrawRect( int x1, int y1, int x2, int y2, char color )
	{
		int leftX = std::min( x1, x2 );
		int rightX = std::max( x1, x2 );
		int lowerY = std::min( y1, y2 );
		int upperY = std::max( y1, y2 );

		for( int i = leftX; i &lt;= rightX; ++i )
		{
			for( int j = lowerY; j &lt;= upperY; ++j )
			{
				m_bitmap[i][j] = color;
			}
		}
	}

	//--------------------------------------------------------------------------
	void FillRegion( int x, int y, char targetColor )
	{
		char sourceColor = m_bitmap[x][y];
		m_bitmap[x][y] = targetColor;

		std::deque&lt;BitmapCoord&gt;		coordQueue;
		coordQueue.push_back( BitmapCoord(x, y) );

		while( !coordQueue.empty() )
		{
			BitmapCoord&amp; current = coordQueue.front();
			const int curX = current.first;
			const int curY = current.second;

			coordQueue.pop_front();

			if( sourceColor == m_bitmap[x][y] )		continue;

			TestAndPushBack( curX,		curY-1,	sourceColor, targetColor, coordQueue );
			TestAndPushBack( curX,		curY+1,	sourceColor, targetColor, coordQueue );
			TestAndPushBack( curX-1,	curY,	sourceColor, targetColor, coordQueue );
			TestAndPushBack( curX+1,	curY,	sourceColor, targetColor, coordQueue );
		}
	}

	//--------------------------------------------------------------------------
	void Display( const std::string&amp; filename, std::ostream&amp; ost ) const
	{
		ost &lt;&lt; filename &lt;&lt; std::endl;
		Display( ost );
	}		

	//--------------------------------------------------------------------------
	void Display( std::ostream&amp; ost ) const
	{
		for( int i = 0; i &lt; m_bitmapHeight; ++i )
		{
			for( int j = 0; j &lt; m_bitmapWidth; ++j )
			{
				ost &lt;&lt; m_bitmap[j][i];
			}
			ost &lt;&lt; std::endl;
		}
	}

private:
	typedef std::pair&lt;int, int&gt;			BitmapCoord;

private:
	//--------------------------------------------------------------------------
	void ResizeTable()
	{
		m_bitmap.resize( m_bitmapWidth );
		for( Bitmap::iterator iter = m_bitmap.begin();
			iter != m_bitmap.end(); ++iter )
		{
			iter-&gt;resize( m_bitmapHeight );
		}
	}

	//--------------------------------------------------------------------------
	void TestAndPushBack( int x, int y, char sourceColor, char targetColor,
		std::deque&lt;BitmapCoord&gt;&amp; coordQueue )
	{
		if( x &lt; 0 || x &gt;= m_bitmapWidth )		return;
		if( y &lt; 0 || y &gt;= m_bitmapHeight )		return;

		if( m_bitmap[x][y] == sourceColor )
		{
			m_bitmap[x][y] = targetColor;
			coordQueue.push_back( BitmapCoord(x, y) );
		}
	}

private:
	typedef std::vector&lt;char&gt;			BitmapCol;
	typedef std::vector&lt;BitmapCol&gt;		Bitmap;
	Bitmap								m_bitmap;

	int									m_bitmapWidth;
	int									m_bitmapHeight;
};
//#############################################################################A

#if UNIT_TEST

//#############################################################################V
// test code
TEST( graphical_editor, create_table )
{
	{
		GraphicalEditor editor(1, 1);
		std::stringstream ss;
		editor.Display( ss );
		ASSERT_STREQ( "O\n", ss.str().c_str() );
	}
	{
		GraphicalEditor editor(1, 2);
		std::stringstream ss;
		editor.Display( ss );
		ASSERT_STREQ( "O\nO\n", ss.str().c_str() );
	}
	{
		GraphicalEditor editor(2, 1);
		std::stringstream ss;
		editor.Display( ss );
		ASSERT_STREQ( "OO\n", ss.str().c_str() );
	}
}

TEST( graphical_editor, draw_pixel )
{
	GraphicalEditor editor(3, 3);
	std::stringstream ss;
	{
		editor.DrawPixel( 0, 0, 'C' );
		editor.Display( ss );
		ASSERT_STREQ( "COO\nOOO\nOOO\n", ss.str().c_str() );
	}
	{
		ss.str("");
		editor.DrawPixel( 1, 0, 'L' );
		editor.Display( ss );
		ASSERT_STREQ( "CLO\nOOO\nOOO\n", ss.str().c_str() );
	}
	{
		ss.str("");
		editor.DrawPixel( 2, 2, 'K' );
		editor.Display( ss );
		ASSERT_STREQ( "CLO\nOOO\nOOK\n", ss.str().c_str() );
	}
}

TEST( graphical_editor, clear_table )
{
	GraphicalEditor editor(3, 3);
	std::stringstream ss;
	{
		editor.DrawPixel( 0, 0, 'C' );
		editor.DrawPixel( 0, 1, 'C' );
		editor.DrawPixel( 0, 2, 'C' );
		editor.DrawPixel( 1, 0, 'C' );
		editor.DrawPixel( 1, 1, 'C' );
		editor.DrawPixel( 1, 2, 'C' );
		editor.DrawPixel( 2, 0, 'C' );
		editor.DrawPixel( 2, 1, 'C' );
		editor.DrawPixel( 2, 2, 'C' );

		editor.Display( ss );
		ASSERT_STREQ( "CCC\nCCC\nCCC\n", ss.str().c_str() );
	}
	{
		editor.ClearTable();
		ss.str("");
		editor.Display( ss );
		ASSERT_STREQ( "OOO\nOOO\nOOO\n", ss.str().c_str() );
	}
}

TEST( graphical_editor, draw_vertical )
{
	GraphicalEditor editor(3, 3);
	std::stringstream ss;
	{
		editor.DrawVertical(1, 0, 2, 'C');
		editor.Display( ss );

		ASSERT_STREQ( "OCO\nOCO\nOCO\n", ss.str().c_str() );
	}
	{
		editor.DrawVertical(2, 2, 1, 'L');
		ss.str("");
		editor.Display( ss );

		ASSERT_STREQ( "OCO\nOCL\nOCL\n", ss.str().c_str() );
	}
}

TEST( graphical_editor, draw_horizontal )
{
	GraphicalEditor editor(3, 3);
	std::stringstream ss;
	{
		editor.DrawHorizontal(0, 2, 2, 'C');
		editor.Display( ss );
		ASSERT_STREQ( "OOO\nOOO\nCCC\n", ss.str().c_str() );
	}
	{
		editor.DrawHorizontal(0, 1, 1, 'L');
		ss.str("");
		editor.Display( ss );
		ASSERT_STREQ( "OOO\nLLO\nCCC\n", ss.str().c_str() );
	}
}

TEST( graphical_editor, draw_rect )
{
	GraphicalEditor editor(3, 3);
	std::stringstream ss;
	{
		editor.DrawRect(0, 0, 2, 2, 'C');
		editor.Display( ss );

		ASSERT_STREQ( "CCC\nCCC\nCCC\n", ss.str().c_str() );
	}
	{
		editor.DrawRect(0, 0, 1, 0, 'L');
		ss.str("");
		editor.Display( ss );

		ASSERT_STREQ( "LLC\nCCC\nCCC\n", ss.str().c_str() );
	}
	{
		editor.DrawRect(1, 1, 1, 2, 'K');
		ss.str("");
		editor.Display( ss );

		ASSERT_STREQ( "LLC\nCKC\nCKC\n", ss.str().c_str() );
	}
}

TEST( graphical_editor, fill_region )
{
	GraphicalEditor editor(3, 3);
	std::stringstream ss;
	{
		editor.FillRegion( 1, 1, 'C' );
		editor.Display( ss );
		ASSERT_STREQ( "CCC\nCCC\nCCC\n", ss.str().c_str() );
	}
	{
		editor.DrawPixel( 2, 2, 'L' );
		editor.FillRegion( 0, 0, 'K' );
		ss.str("");
		editor.Display( ss );
		ASSERT_STREQ( "KKK\nKKK\nKKL\n", ss.str().c_str() );
	}
	{
		editor.DrawHorizontal( 0, 2, 1, 'C' );
		editor.FillRegion( 0, 0, 'L' );
		ss.str("");
		editor.Display( ss );
		ASSERT_STREQ( "LLL\nCCC\nKKL\n", ss.str().c_str() );
	}
	{
		editor.ClearTable();
		editor.DrawPixel( 1, 1, 'C' );
		editor.FillRegion( 1, 1, 'L' );
		ss.str("");
		editor.Display( ss );
		ASSERT_STREQ( "OOO\nOLO\nOOO\n", ss.str().c_str() );
	}
	{
		editor.ClearTable();
		editor.DrawVertical( 2, 0, 2, 'C' );
		editor.FillRegion( 2, 2, 'C' );
		ss.str("");
		editor.Display( ss );
		ASSERT_STREQ( "OOC\nOOC\nOOC\n", ss.str().c_str() );
	}
	{
		editor.ClearTable();
		editor.FillRegion( 1, 1, 'O' );
		ss.str("");
		editor.Display( ss );
		ASSERT_STREQ( "OOO\nOOO\nOOO\n", ss.str().c_str() );
	}
}

TEST( graphical_editor, display )
{
	GraphicalEditor editor(3, 3);
	std::stringstream ss;
	editor.Display( "sample.bmp", ss );
	ASSERT_STREQ( "sample.bmp\nOOO\nOOO\nOOO\n", ss.str().c_str() );
}

//#############################################################################A

int main(int argc, char **argv)
{
	testing::InitGoogleTest(&amp;argc, argv);
	return RUN_ALL_TESTS();
}

#else

int main()
{
	//#########################################################################V
	// submit code
	char command;
	GraphicalEditor editor;

	while( (std::cin &gt;&gt; command) &amp;&amp; command != 'X' )
	{
		switch( command )
		{
		case 'I':
			{
				int m, n;
				std::cin &gt;&gt; m &gt;&gt; n;
				editor.CreateTable( m, n );
			}
			break;

		case 'C':
			editor.ClearTable();
			break;

		case 'L':
			{
				int x, y;
				char c;
				std::cin &gt;&gt; x &gt;&gt; y &gt;&gt; c;
				editor.DrawPixel( x-1, y-1, c );
			}
			break;

		case 'V':
			{
				int x, y1, y2;
				char c;
				std::cin &gt;&gt; x &gt;&gt; y1 &gt;&gt; y2 &gt;&gt; c;
				editor.DrawVertical( x-1, y1-1, y2-1, c );
			}
			break;

		case 'H':
			{
				int x1, x2, y;
				char c;
				std::cin &gt;&gt; x1 &gt;&gt; x2 &gt;&gt; y &gt;&gt; c;
				editor.DrawHorizontal( x1-1, x2-1, y-1, c );
			}
			break;

		case 'K':
			{
				int x1, x2, y1, y2;
				char c;
				std::cin &gt;&gt; x1 &gt;&gt; y1 &gt;&gt; x2 &gt;&gt; y2 &gt;&gt; c;
				editor.DrawRect( x1-1, y1-1, x2-1, y2-1, c );
			}
			break;

		case 'F':
			{
				int x, y;
				char c;
				std::cin &gt;&gt; x &gt;&gt; y &gt;&gt; c;
				editor.FillRegion( x-1, y-1, c );
			}
			break;

		case 'S':
			{
				std::string fileName;
				std::cin &gt;&gt; fileName;
				editor.Display( fileName, std::cout );
			}
			break;

		default:
			// 라인 마지막까지 꿀꺽~
			std::cin.ignore( std::numeric_limits&lt;std::streamsize&gt;::max(), '\n' );
			break;
		}
	}
	//#########################################################################A
	return 0;
}
#endif</pre>
<p>&nbsp;</p>
<div class="acc_license"><a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"><img src="http://i.creativecommons.org/l/by-nc-sa/3.0/88x31.png" alt="by-nc-sa" /></a></div><!--<rdf:RDF xmlns="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><Work rdf:about=""><license rdf:resource="http://creativecommons.org/licenses/by-nc-sa/3.0/" /></Work><License rdf:about="http://creativecommons.org/licenses/by-nc-sa/3.0/"><requires rdf:resource="http://creativecommons.org/ns#Attribution" /><permits rdf:resource="http://creativecommons.org/ns#Reproduction" /><permits rdf:resource="http://creativecommons.org/ns#Distribution" /><permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /><requires rdf:resource="http://creativecommons.org/ns#ShareAlike" /><prohibits rdf:resource="http://creativecommons.org/ns#CommercialUse" /><requires rdf:resource="http://creativecommons.org/ns#Notice" /></License></rdf:RDF>-->]]></content:encoded>
			<wfw:commentRss>http://ohyecloudy.com/algo/archives/34/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ACM 706 (Uva ID) : LCD Display</title>
		<link>http://ohyecloudy.com/algo/archives/32?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=acm-706-uva-id-lcd-display</link>
		<comments>http://ohyecloudy.com/algo/archives/32#comments</comments>
		<pubDate>Sun, 12 Jul 2009 22:00:16 +0000</pubDate>
		<dc:creator>ohyecloudy</dc:creator>
				<category><![CDATA[Volume VII]]></category>
		<category><![CDATA[ad hoc]]></category>

		<guid isPermaLink="false">http://ohyecloudy.com/algo/?p=32</guid>
		<description><![CDATA[문제 링크 : http://uva.onlinejudge.org/external/7/706.html 응시 유저 수 : 5770 해결한 유저 비율 : 62.86% &#160; 문자와 문자 사이에 빈칸을 출력해야 하고 출력을 다 하고 빈 라인을 출력해야 한다. for_each로 문자의 row를 출력하려고 했는데, 마지막 문자 뒤에는 공백을 출력하면 안 돼서 그냥 반복자(iterator)를 사용해서 출력했다. 어렵기보단 귀찮은 문제.. 소스 코드 //////////////////////////////////////////////////////////////////////////////// // UVa Online Judge(http://uva.onlinejudge.org/) // [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li>문제 링크 : <a href="http://uva.onlinejudge.org/external/7/706.html" target="_blank">http://uva.onlinejudge.org/external/7/706.html</a></li>
<li>응시 유저 수 : 5770</li>
<li>해결한 유저 비율 : 62.86%</li>
</ul>
<p><img src="https://lh3.googleusercontent.com/-NvSZJCqDSq0/TwmQ8mhvKSI/AAAAAAAAJxA/DS3UrlswzsY/s640/aw.png" alt="" width="640" height="44" /></p>
<p><span id="more-32"></span></p>
<p>&nbsp;</p>
<p><strong>문자와 문자 사이에 빈칸을 출력</strong>해야 하고 <strong>출력을 다 하고 빈 라인을 출력</strong>해야 한다. for_each로 문자의 row를 출력하려고 했는데, 마지막 문자 뒤에는 공백을 출력하면 안 돼서 그냥 반복자(iterator)를 사용해서 출력했다. 어렵기보단 귀찮은 문제..</p>
<p>소스 코드</p>
<pre class="brush:cpp">////////////////////////////////////////////////////////////////////////////////
// UVa Online Judge(http://uva.onlinejudge.org/)
//
// problem : 706 LCD Display (http://uva.onlinejudge.org/external/7/706.html)
//
// - OOP, Unit test, STL을 남발한다.
// - 속도보다는 읽기 좋게 작성한다.
//
// This file is licenced under a Creative Commons license:
// http://creativecommons.org/licenses/by-nc-sa/2.0/kr/
////////////////////////////////////////////2009. 07. 12 ohyecloudy at gmail.com
#ifdef ONLINE_JUDGE
#   define UNIT_TEST 0
#else
#   define UNIT_TEST 1
#endif  

#if UNIT_TEST
#	include &lt;gtest/gtest.h&gt;
#	include &lt;strstream&gt;
#endif

#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;cassert&gt;
#include &lt;algorithm&gt;
#include &lt;string&gt;
//-----------------------------------------------------------------------------V
// submit code
class Lcd
{
public:
	typedef std::vector&lt;int&gt;	digit_vec;
public:
	explicit Lcd( int digit, int scale )
		: m_scale( scale )
	{
		m_digitList.push_back(digit);
	}
	explicit Lcd( const std::vector&lt;int&gt;&amp; digitList, int scale )
		: m_digitList( digitList )
		, m_scale( scale )
	{}

	void Display( std::ostream&amp; ost)
	{
		DisplayRow( ost, 0 );

		// 2번째 줄을 스케일만큼 출력.
		for( int i = 0; i &lt; m_scale; ++i )
		{
			DisplayRow( ost, 1 );
		}

		DisplayRow( ost, 2 );

		// 4번째 줄을 스케일만큼 출력.
		for( int i = 0; i &lt; m_scale; ++i )
		{
			DisplayRow( ost, 3 );
		}

		DisplayRow( ost, 4 );
		// Output a blank line after each number.
		ost &lt;&lt; std::endl;
	}
private:
	void DisplayRow( std::ostream&amp; ost, int row )
	{
		for( digit_vec::iterator iter = m_digitList.begin();
			iter != m_digitList.end(); ++iter )
		{
			DisplayDigitRow( ost, *iter, row );

			// 현재 이터레이션이 마지막일때를 제외하고 출력한 공백 출력.
			// 문자 사이에 공백이 하나 있어야하고
			// 마지막에는 공백이 없어야 하기 때문.
			if( std::distance( iter, m_digitList.end() ) &gt; 1 )
			{
				ost &lt;&lt; ' ';
			}
		}
		ost &lt;&lt; std::endl;
	}

	void DisplayDigitRow( std::ostream&amp; ost, int num, int row )
	{
		static char digit[10][15] =
		{
			{' ','-',' ', '|',' ','|', ' ',' ',' ', '|',' ','|', ' ','-',' ',}, // 0
			{' ',' ',' ', ' ',' ','|', ' ',' ',' ', ' ',' ','|', ' ',' ',' ',}, // 1
			{' ','-',' ', ' ',' ','|', ' ','-',' ', '|',' ',' ', ' ','-',' ',}, // 2
			{' ','-',' ', ' ',' ','|', ' ','-',' ', ' ',' ','|', ' ','-',' ',}, // 3
			{' ',' ',' ', '|',' ','|', ' ','-',' ', ' ',' ','|', ' ',' ',' ',}, // 4
			{' ','-',' ', '|',' ',' ', ' ','-',' ', ' ',' ','|', ' ','-',' ',}, // 5
			{' ','-',' ', '|',' ',' ', ' ','-',' ', '|',' ','|', ' ','-',' ',}, // 6
			{' ','-',' ', ' ',' ','|', ' ',' ',' ', ' ',' ','|', ' ',' ',' ',}, // 7
			{' ','-',' ', '|',' ','|', ' ','-',' ', '|',' ','|', ' ','-',' ',}, // 8
			{' ','-',' ', '|',' ','|', ' ','-',' ', ' ',' ','|', ' ','-',' ',}, // 9
		};

		ost &lt;&lt; digit[num][3 * row];

		// 2번째 열만 스케일만큼 출력한다.
		for( int i = 0; i &lt; m_scale; ++i )
		{
			ost &lt;&lt; digit[num][3 * row + 1];
		}

		ost &lt;&lt; digit[num][3 * row+2];
	}

private:
	digit_vec			m_digitList;
	int					m_scale;
};

//-----------------------------------------------------------------------------A

#if UNIT_TEST
//-----------------------------------------------------------------------------V
// test code
TEST( singleDisplay_all, scale1 )
{
	{
		// 0
		Lcd lcd( 0, 1 );

		std::stringstream ss;
		lcd.Display( ss );

		ASSERT_STREQ( " - \n| |\n   \n| |\n - \n\n", ss.str().c_str() );
	}
	{
		// 1
		Lcd lcd( 1, 1 );

		std::stringstream ss;
		lcd.Display( ss );

		ASSERT_STREQ( "   \n  |\n   \n  |\n   \n\n", ss.str().c_str() );
	}
	{
		// 2
		Lcd lcd( 2, 1 );

		std::stringstream ss;
		lcd.Display( ss );

		ASSERT_STREQ( " - \n  |\n - \n|  \n - \n\n", ss.str().c_str() );
	}
	{
		// 3
		Lcd lcd( 3, 1 );

		std::stringstream ss;
		lcd.Display( ss );

		ASSERT_STREQ( " - \n  |\n - \n  |\n - \n\n", ss.str().c_str() );
	}
	{
		// 4
		Lcd lcd( 4, 1 );

		std::stringstream ss;
		lcd.Display( ss );

		ASSERT_STREQ( "   \n| |\n - \n  |\n   \n\n", ss.str().c_str() );
	}
	{
		// 5
		Lcd lcd( 5, 1 );

		std::stringstream ss;
		lcd.Display( ss );

		ASSERT_STREQ( " - \n|  \n - \n  |\n - \n\n", ss.str().c_str() );
	}
	{
		// 6
		Lcd lcd( 6, 1 );

		std::stringstream ss;
		lcd.Display( ss );

		ASSERT_STREQ( " - \n|  \n - \n| |\n - \n\n", ss.str().c_str() );
	}
	{
		// 7
		Lcd lcd( 7, 1 );

		std::stringstream ss;
		lcd.Display( ss );

		ASSERT_STREQ( " - \n  |\n   \n  |\n   \n\n", ss.str().c_str() );
	}
	{
		// 8
		Lcd lcd( 8, 1 );

		std::stringstream ss;
		lcd.Display( ss );

		ASSERT_STREQ( " - \n| |\n - \n| |\n - \n\n", ss.str().c_str() );
	}
	{
		// 9
		Lcd lcd( 9, 1 );

		std::stringstream ss;
		lcd.Display( ss );

		ASSERT_STREQ( " - \n| |\n - \n  |\n - \n\n", ss.str().c_str() );
	}
}

TEST( singleDisplay_0, scale2 )
{
	Lcd lcd( 0, 2 );

	std::stringstream ss;
	lcd.Display( ss );

	ASSERT_STREQ( " -- \n|  |\n|  |\n    \n|  |\n|  |\n -- \n\n", ss.str().c_str() );
}

TEST( twoDisplay_01, scale1 )
{
	std::vector&lt;int&gt; digitList;
	digitList.push_back( 0 );
	digitList.push_back( 1 );
	Lcd lcd( digitList, 1 );

	std::stringstream ss;
	lcd.Display( ss );

	ASSERT_STREQ( " -     \n| |   |\n       \n| |   |\n -     \n\n", ss.str().c_str() );
}
//-----------------------------------------------------------------------------A
int main( int argc, char **argv )
{
	testing::InitGoogleTest( &amp;argc, argv );
	return RUN_ALL_TESTS();
}

#else

int main( int argc, char **argv )
{
	//-------------------------------------------------------------------------V
	// submit code
	int scale;
	std::string numberString;
	while( std::cin &gt;&gt; scale &gt;&gt; numberString )
	{
		if( scale == 0 )			break;

		Lcd::digit_vec numbers;
		for( std::string::iterator iter = numberString.begin();
			iter != numberString.end(); ++iter )
		{
			numbers.push_back( *iter - '0' );
		}

		Lcd lcd( numbers, scale );
		lcd.Display( std::cout );
	}

	//-------------------------------------------------------------------------A
	return 0;
}
#endif</pre>
<p>&nbsp;</p>
<p>찾아보니 예전에 풀었던 소스도 있었다. 코드 읽기가 너무 어려워&#8230; 게다가 무슨 깡으로 주석도 안 적었는지, 것 참.</p>
<p>예전 소스 코드</p>
<pre class="brush:cpp">//////////////////////////////////////////////////////////////////////////
// LC-Display (UVa ID : 706)
//
// Ohyecloudy ( Ohyecloudy@gmail.com )
// Accepted

#include &lt;iostream&gt;
#include &lt;string&gt;

using namespace std ;

int LC[10][7] = { { 1,1,1,0,1,1,1 },
{ 0,0,1,0,0,1,0},
{ 1,0,1,1,1,0,1},
{ 1,0,1,1,0,1,1},
{ 0,1,1,1,0,1,0},
{ 1,1,0,1,0,1,1},
{ 1,1,0,1,1,1,1},
{ 1,0,1,0,0,1,0},
{ 1,1,1,1,1,1,1},
{ 1,1,1,1,0,1,1} } ;

void print(int input,char ch)
{
    for ( int i = 0 ; i &lt; input ; ++i )
        cout &lt;&lt; ch ;
}

void drawNumber(string num, int scale )
{
    int i,j,idx ;

    for ( i = 0 ; i &lt; num.length() ; ++i )
    {
        idx = static_cast&lt;int&gt;(num.at(i) - '0') ;

        cout &lt;&lt; " " ;

        if ( LC[idx][0] == 1 )
            print(scale, '-') ;
        else
            print(scale, ' ') ;

        if ( i == num.length() - 1 )
            cout &lt;&lt;  " "  &lt;&lt; endl ;
        else
            cout &lt;&lt;  "  " ;
    }

    for ( i = 0 ; i &lt; scale ; ++i )
    {
        for ( j = 0 ; j &lt; num.length() ; ++j )
        {
            idx = static_cast&lt;int&gt;(num.at(j) - '0') ;

            if ( LC[idx][1] == 1 )
                cout &lt;&lt; '|' ;
            else
                cout &lt;&lt; ' ' ;

            print(scale, ' ') ;

            if ( LC[idx][2] == 1 )
                cout &lt;&lt; '|' ;
            else
                cout &lt;&lt; ' ' ;

            if ( j == num.length()-1 )
                cout &lt;&lt; endl ;
            else
                cout &lt;&lt; ' ' ;
        }
    }

    for ( i = 0 ; i &lt; num.length() ; ++i )
    {
        idx = static_cast&lt;int&gt;(num.at(i) - '0') ;

        cout &lt;&lt; " " ;

        if ( LC[idx][3] == 1 )
            print(scale, '-') ;
        else
            print(scale, ' ') ;

        if ( i == num.length() - 1 )
            cout &lt;&lt;  " "  &lt;&lt; endl ;
        else
            cout &lt;&lt;  "  " ;
    }

    for ( i = 0 ; i &lt; scale ; ++i )
    {
        for ( j = 0 ; j &lt; num.length() ; ++j )
        {
            idx = static_cast&lt;int&gt;(num.at(j) - '0') ;

            if ( LC[idx][4] == 1 )
                cout &lt;&lt; '|' ;
            else
                cout &lt;&lt; ' ' ;

            print(scale, ' ') ;

            if ( LC[idx][5] == 1 )
                cout &lt;&lt; '|' ;
            else
                cout &lt;&lt; ' ' ;

            if ( j == num.length()-1 )
                cout &lt;&lt; endl ;
            else
                cout &lt;&lt; ' ' ;
        }
    }

    for ( i = 0 ; i &lt; num.length() ; ++i )
    {
        idx = static_cast&lt;int&gt;(num.at(i) - '0') ;

        cout &lt;&lt; " " ;

        if ( LC[idx][6] == 1 )
            print(scale, '-') ;
        else
            print(scale, ' ') ;

        if ( i == num.length() - 1 )
            cout &lt;&lt;  " "  &lt;&lt; endl ;
        else
            cout &lt;&lt;  "  " ;
    }
}

main()
{
    string input ;
    int scale ;

    while ( cin &gt;&gt; scale &gt;&gt; input )
    {
        if ( scale == 0 )
        {
            if ( input.compare("0") == 0 )
                break ;
            else
                continue ;
        }

        drawNumber(input, scale ) ;
        cout &lt;&lt; endl ;
    }
}</pre>
<p>&nbsp;</p>
<div class="acc_license"><a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"><img src="http://i.creativecommons.org/l/by-nc-sa/3.0/88x31.png" alt="by-nc-sa" /></a></div><!--<rdf:RDF xmlns="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><Work rdf:about=""><license rdf:resource="http://creativecommons.org/licenses/by-nc-sa/3.0/" /></Work><License rdf:about="http://creativecommons.org/licenses/by-nc-sa/3.0/"><requires rdf:resource="http://creativecommons.org/ns#Attribution" /><permits rdf:resource="http://creativecommons.org/ns#Reproduction" /><permits rdf:resource="http://creativecommons.org/ns#Distribution" /><permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /><requires rdf:resource="http://creativecommons.org/ns#ShareAlike" /><prohibits rdf:resource="http://creativecommons.org/ns#CommercialUse" /><requires rdf:resource="http://creativecommons.org/ns#Notice" /></License></rdf:RDF>-->]]></content:encoded>
			<wfw:commentRss>http://ohyecloudy.com/algo/archives/32/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ACM 10137 (Uva ID) : The Trip</title>
		<link>http://ohyecloudy.com/algo/archives/29?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=acm-10137-uva-id-the-trip</link>
		<comments>http://ohyecloudy.com/algo/archives/29#comments</comments>
		<pubDate>Thu, 29 Jan 2009 22:00:24 +0000</pubDate>
		<dc:creator>ohyecloudy</dc:creator>
				<category><![CDATA[Volume CI]]></category>
		<category><![CDATA[ad hoc]]></category>

		<guid isPermaLink="false">http://ohyecloudy.com/algo/?p=29</guid>
		<description><![CDATA[문제 링크 : http://uva.onlinejudge.org/external/101/10137.html 응시 유저 수 : 3897 해결한 유저 비율 : 56.92% &#160; 소스코드 //////////////////////////////////////////////////////////////////////////////// // UVa Online Judge(http://icpcres.ecs.baylor.edu/onlinejudge/) // // problem : 10137 - The Trip // (http://uva.onlinejudge.org/external/101/10137.html) // // OOP, Unit test, STL을 연습하기 위함 // // This file is licenced under a Creative Commons license: // http://creativecommons.org/licenses/by-nc-sa/2.0/kr/ ///////////////////////////////////////////////2009. 01. 28 ohyecloudy@gmail.com [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li>문제 링크 : <a href="http://uva.onlinejudge.org/external/101/10137.html" target="_blank">http://uva.onlinejudge.org/external/101/10137.html</a></li>
<li>응시 유저 수 : 3897</li>
<li>해결한 유저 비율 : 56.92%</li>
</ul>
<p><img src="https://lh4.googleusercontent.com/--_wwY-KRIpc/TwmOaydL28I/AAAAAAAAJw4/l36kIceFQVc/s640/image_thumb_1.png" alt="" width="640" height="48" /></p>
<p><span id="more-29"></span></p>
<p>&nbsp;</p>
<p>소스코드</p>
<pre class="brush:cpp">////////////////////////////////////////////////////////////////////////////////
// UVa Online Judge(http://icpcres.ecs.baylor.edu/onlinejudge/)
//
// problem : 10137 - The Trip
// (http://uva.onlinejudge.org/external/101/10137.html)
//
// OOP, Unit test, STL을 연습하기 위함
//
// This file is licenced under a Creative Commons license:
// http://creativecommons.org/licenses/by-nc-sa/2.0/kr/
///////////////////////////////////////////////2009. 01. 28 ohyecloudy@gmail.com

#if ONLINE_JUDGE
#	define UNIT_TEST 0
#else
#	define UNIT_TEST 1
#endif

#if UNIT_TEST
#	include &lt;gtest/gtest.h&gt;
#endif

#include &lt;iostream&gt;
#include &lt;iomanip&gt;
#include &lt;algorithm&gt;
#include &lt;limits&gt;
#include &lt;vector&gt;
#include &lt;cmath&gt;
//-----------------------------------------------------------------------------V
// submit code
namespace
{
	// 평균값을 구하는 functor
	class MeanValue
	{
	public:
		MeanValue() : m_sum(0.0f), m_count(0)		{}

		void operator() (double elem)
		{
			m_sum += elem;
			++m_count;
		}

		operator double()							{ return m_sum / m_count; }

	private:
		double	m_sum;
		int		m_count;
	};
}

////////////////////////////////////////////////////////////////////////////////
// TravelExpense
class TravelExpense
{
public:
	explicit TravelExpense(int expenseCount) : m_expenseCount(expenseCount)
	{
		m_expenseList.reserve(expenseCount);
	}

	std::ostream&amp; operator&gt;&gt; (std::ostream&amp; ost)
	{
		ost &lt;&lt; "$" &lt;&lt; std::fixed &lt;&lt; std::showpoint &lt;&lt; std::setprecision(2) &lt;&lt;
			GetMinExchange() &lt;&lt; std::endl;
		return ost;
	}

	std::istream&amp; operator&lt;&lt; (std::istream&amp; ist)
	{
		for (int i = 0; i &lt; m_expenseCount; ++i)
		{
			double expense;
			ist &gt;&gt; expense;
			AddExpense(expense);
		}
		return ist;
	}

protected:
	void	AddExpense(double expense)	{ m_expenseList.push_back(expense); }

	double	GetMinExchange() const
	{
		// 소수점 셋째 자리에서 반올림한 평균값
		double meanValue = for_each(m_expenseList.begin(), m_expenseList.end(), MeanValue());
		meanValue = floor((meanValue + 0.005) * 100.0) * 0.01;

		double meanValueOver = 0.0;
		double meanValueUnder = 0.0;
		for (std::vector&lt;double&gt;::const_iterator iter = m_expenseList.begin();
			iter != m_expenseList.end(); ++iter)
		{
			const double expense = *iter;
			if (expense &gt; meanValue)	meanValueOver	+= expense - meanValue;
			else						meanValueUnder	+= meanValue - expense;
		}

		// 평균 이상에서 평균을 뺀 값을 더한 총합이 단 하나의 경우를 제외하고는 항상 작다.
		// 단 하나의 경우는 1 센트 오차를 인정해서 평균에서 평균 이하 값을 뺀 총합이 0이
		// 되는 경우. 예) 12.00, 12.00, 12.00, 12.01
		return std::min&lt;double&gt;(meanValueOver, meanValueUnder);
	}

private:
	std::vector&lt;double&gt;		m_expenseList;
	int						m_expenseCount;
};

std::ostream&amp; operator&lt;&lt; (std::ostream&amp; ost, TravelExpense&amp; travelExpense)
{
	travelExpense &gt;&gt; ost;
	return ost;
}

std::istream&amp; operator&gt;&gt; (std::istream&amp; ist, TravelExpense&amp; travelExpense)
{
	travelExpense &lt;&lt; ist;
	return ist;
}

//-----------------------------------------------------------------------------A

#if UNIT_TEST
//-----------------------------------------------------------------------------V
// test code
class TestTravelExpense : public TravelExpense
{
public:
	explicit TestTravelExpense(int expenseCount) : TravelExpense(expenseCount)	{}

	using TravelExpense::AddExpense;
	using TravelExpense::GetMinExchange;
};

TEST(GetMinExchange, ExchangeZero_1)
{
	TestTravelExpense travelExpense(0);

	for (int i=0; i &lt; 999; ++i)
	{
		travelExpense.AddExpense(10000.00);
	}

	travelExpense.AddExpense(9999.99);

	ASSERT_DOUBLE_EQ(0.00, travelExpense.GetMinExchange());
}

TEST(GetMinExchange, ExchangeZero_2)
{
	TestTravelExpense travelExpense(0);

	travelExpense.AddExpense(12.01);
	travelExpense.AddExpense(12.00);
	travelExpense.AddExpense(12.00);
	travelExpense.AddExpense(12.00);

	ASSERT_DOUBLE_EQ(0.00, travelExpense.GetMinExchange());
}

TEST(GetMinExchange, ProblemSample_1)
{
	TestTravelExpense travelExpense(0);

	travelExpense.AddExpense(10.00);
	travelExpense.AddExpense(20.00);
	travelExpense.AddExpense(30.00);
	ASSERT_DOUBLE_EQ(10.0, travelExpense.GetMinExchange());
}

TEST(GetMinExchange, ProblemSample_2)
{
	TestTravelExpense travelExpense(0);

	travelExpense.AddExpense(15.00);
	travelExpense.AddExpense(15.01);
	travelExpense.AddExpense(3.00);
	travelExpense.AddExpense(3.01);
	ASSERT_DOUBLE_EQ(11.99, travelExpense.GetMinExchange());
}

//-----------------------------------------------------------------------------A
int main(int argc, char **argv)
{
	testing::InitGoogleTest(&amp;argc, argv);
	return RUN_ALL_TESTS();
}

#else
int main(int argc, char **argv)
{
	//-------------------------------------------------------------------------V
	// submit code
	int expenseCount;
	std::cin &gt;&gt; expenseCount;

	while ( expenseCount &gt; 0)
	{
		TravelExpense travelExpense(expenseCount);
		std::cin &gt;&gt; travelExpense;
		std::cout &lt;&lt; travelExpense;

		std::cin &gt;&gt; expenseCount;
	}

	//-------------------------------------------------------------------------A
	return 0;
}
#endif</pre>
<p><strong>오차 범위를 확인 안 하고 막 float 자료형을 써서 WA를 계속 받았던 문제</strong>였다. double 자료형을 사용해야지 Round-off 에러를 피할 수 있다. 평균값을 반올림해서 구하고 평균 이상 값과 평균 이하 값에서 평균값을 뺀 총합을 구하고 그 중 최솟값을 구하면 된다. <strong>간단한 문제인데, 자료형 선택에서 실수를 많이 하는 문제</strong>이다.</p>
<p>&nbsp;</p>
<p>예전 소스 코드</p>
<pre class="brush:cpp">//////////////////////////////////////////////////////////////////////////
// The Trip (UVa ID : 10137)
//
// Ohyecloudy ( Ohyecloudy@gmail.com )
// Accepted

#include &lt;iostream&gt;
#include &lt;cmath&gt;
#include &lt;iomanip&gt;

using namespace std ;

long double money[1000] ;
int nStudent ;

long double round( int n, long double input )
{
	return floor( input * pow ( 10.0, n ) + 0.5 ) / pow ( 10.0, n ) ;
}

long double getExchange()
{
	long double tot = 0 ;

	for ( int i = 0 ; i &lt; nStudent ; ++i )
		tot += money[i] ;

	long double avg = round( 2, tot / nStudent ) ;

	long double incomeToAvg = 0 ;
	long double outcomeToAvg = 0 ;

	for ( int j = 0 ; j &lt; nStudent ; ++j )
	{
		if ( money[j] &gt; avg )
			outcomeToAvg += money[j] - avg ;
		else
			incomeToAvg += avg - money[j] ;
	}

	if ( outcomeToAvg == 0 )
		outcomeToAvg = incomeToAvg ;
	if ( incomeToAvg == 0 )
		incomeToAvg = outcomeToAvg ;

	if ( incomeToAvg &gt; outcomeToAvg )
		return outcomeToAvg ;
	else
		return incomeToAvg ;
}

main()
{
	while ( cin &gt;&gt; nStudent )
	{
		if ( nStudent == 0 )
			break ;

		for ( int i = 0 ; i &lt; nStudent ; ++i )
			cin &gt;&gt; money[i] ;

		cout.setf( ios::showpoint | ios::fixed ) ;

		cout &lt;&lt; "$" &lt;&lt; setprecision(2) &lt;&lt; getExchange() &lt;&lt; endl ;
	}
}</pre>
<p>왜 0일때 특별 처리를 해주는지 모르겠다. -_-; 저렇게 해도 AC가 뜬다. 미래의 나를 위해 주석을 달았어야 하는데 말이지&#8230;</p>
<p>&nbsp;</p>
<div class="acc_license"><a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"><img src="http://i.creativecommons.org/l/by-nc-sa/3.0/88x31.png" alt="by-nc-sa" /></a></div><!--<rdf:RDF xmlns="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><Work rdf:about=""><license rdf:resource="http://creativecommons.org/licenses/by-nc-sa/3.0/" /></Work><License rdf:about="http://creativecommons.org/licenses/by-nc-sa/3.0/"><requires rdf:resource="http://creativecommons.org/ns#Attribution" /><permits rdf:resource="http://creativecommons.org/ns#Reproduction" /><permits rdf:resource="http://creativecommons.org/ns#Distribution" /><permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /><requires rdf:resource="http://creativecommons.org/ns#ShareAlike" /><prohibits rdf:resource="http://creativecommons.org/ns#CommercialUse" /><requires rdf:resource="http://creativecommons.org/ns#Notice" /></License></rdf:RDF>-->]]></content:encoded>
			<wfw:commentRss>http://ohyecloudy.com/algo/archives/29/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ACM 10189 (UVa ID) : Minesweeper</title>
		<link>http://ohyecloudy.com/algo/archives/23?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=acm-10189-uva-id-minesweeper</link>
		<comments>http://ohyecloudy.com/algo/archives/23#comments</comments>
		<pubDate>Tue, 13 Jan 2009 22:00:53 +0000</pubDate>
		<dc:creator>ohyecloudy</dc:creator>
				<category><![CDATA[Volume CI]]></category>
		<category><![CDATA[ad hoc]]></category>

		<guid isPermaLink="false">http://ohyecloudy.com/algo/?p=23</guid>
		<description><![CDATA[문제 링크 : http://uva.onlinejudge.org/external/101/10189.html 응시 유저 수 : 8828 해결한 유저 비율 : 64.23% &#160; 소스코드 //////////////////////////////////////////////////////////////////////////////// // UVa Online Judge(http://icpcres.ecs.baylor.edu/onlinejudge/) // // problem : 10189 - Minesweeper // (http://uva.onlinejudge.org/external/101/10189.html) // // OOP, Unit test, STL을 연습하기 위함 // // This file is licenced under a Creative Commons license: // http://creativecommons.org/licenses/by-nc-sa/2.0/kr/ ///////////////////////////////////////////////2009. 01. 13 ohyecloudy@gmail.com #define [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li>문제 링크 : <a href="http://uva.onlinejudge.org/external/101/10189.html" target="_blank">http://uva.onlinejudge.org/external/101/10189.html</a></li>
<li>응시 유저 수 : 8828</li>
<li>해결한 유저 비율 : 64.23%</li>
</ul>
<p><img src="https://lh5.googleusercontent.com/-ywe63VGm9uM/TwmHixx4lnI/AAAAAAAAJww/jgYg11jC5xU/s640/temp_thumb.jpg" alt="" width="640" height="42" /></p>
<p><span id="more-23"></span></p>
<p>&nbsp;</p>
<p>소스코드</p>
<pre class="brush:cpp">////////////////////////////////////////////////////////////////////////////////
// UVa Online Judge(http://icpcres.ecs.baylor.edu/onlinejudge/)
//
// problem : 10189 - Minesweeper
// (http://uva.onlinejudge.org/external/101/10189.html)
//
// OOP, Unit test, STL을 연습하기 위함
//
// This file is licenced under a Creative Commons license:
// http://creativecommons.org/licenses/by-nc-sa/2.0/kr/
///////////////////////////////////////////////2009. 01. 13 ohyecloudy@gmail.com

#define UNIT_TEST 0

#if UNIT_TEST
#	include &lt;gtest/gtest.h&gt;
#endif

#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;string&gt;
#include &lt;algorithm&gt;

//-----------------------------------------------------------------------------V
// submit code
class MineField
{
	// public-------------------------------------------------------------------
public:
	explicit MineField(int height, int width, int fieldNumber)
		: m_height(height), m_width(width), m_fieldNumber(fieldNumber)
	{
		m_mineLocationList.reserve(width*height);

		m_field.resize(width);
		for (field::iterator iter = m_field.begin(); iter != m_field.end(); ++iter)
		{
			std::vector&lt;char&gt;&amp; col = *iter;
			col.resize(height);
			std::fill( col.begin(), col.end(), '0');
		}
	}

	void Sweep()
	{
		for (mine_location_list::const_iterator iter = m_mineLocationList.begin();
			iter != m_mineLocationList.end(); ++iter)
		{
			const mine_location&amp; location = *iter;
			m_field[location.first][location.second] = MINE_MARK;
			UpdateMineAround(location.first, location.second);
		}

		m_mineLocationList.clear();
	}

	std::istream&amp; operator&lt;&lt; (std::istream&amp; ist)
	{
		char input;

		for (int i = 0; i &lt; m_height; ++i)
		{
			for (int j = 0; j &lt; m_width; ++j)
			{
				ist &gt;&gt; input;
				if (input == MINE_MARK)		AddMine( j, i );
			}
		}

		return ist;
	}

	std::ostream&amp; operator&gt;&gt; (std::ostream&amp; ost) const
	{
		ost &lt;&lt; "Field #" &lt;&lt; m_fieldNumber &lt;&lt; ":" &lt;&lt; std::endl;
		for (int i = 0; i &lt; m_height; ++i)
		{
			for (int j = 0; j &lt; m_width; ++j)
			{
				ost &lt;&lt; GetField(j, i);
			}

			ost &lt;&lt; std::endl;
		}

		return ost;
	}

	// protected----------------------------------------------------------------
protected:
	const static char							MINE_MARK;

protected:
	void AddMine(int x, int y)
	{
		if (m_field[x][y] != MINE_MARK )
		{
			m_mineLocationList.push_back( mine_location_value(x,y) );
		}
	}

	const char GetField(int x, int y) const		{ return m_field[x][y]; }

	// private------------------------------------------------------------------
private:
	int m_width, m_height, m_fieldNumber;

	typedef std::pair&lt;int, int&gt;					mine_location;
	typedef	std::vector&lt;mine_location&gt;			mine_location_list;
	typedef mine_location_list::value_type		mine_location_value;
	mine_location_list							m_mineLocationList;

	// 인접한 mine 개수가 최대 8이다. 2자리수가 될 수 없으므로 char 선택.
	typedef std::vector&lt; std::vector&lt;char&gt; &gt;	field;
	field										m_field;

private:
	void IncreaseMineSweep(int x, int y)
	{
		if (m_field[x][y] != MINE_MARK )	m_field[x][y]++;
	}

	void UpdateMineAround(int x, int y)
	{
		bool bTop		= (y-1 &gt;= 0)		? true : false;
		bool bBottom	= (y+1 &lt; m_height)	? true : false;
		bool bLeft		= (x-1 &gt;= 0)		? true : false;
		bool bRight		= (x+1 &lt; m_width)	? true : false;

		// horizon, vertical
		if (bTop)				IncreaseMineSweep(x,	y-1);
		if (bBottom)			IncreaseMineSweep(x,	y+1);
		if (bLeft)				IncreaseMineSweep(x-1,	y);
		if (bRight)				IncreaseMineSweep(x+1,	y);

		// diagonal
		if (bTop &amp;&amp; bLeft)		IncreaseMineSweep(x-1,	y-1);
		if (bTop &amp;&amp; bRight)		IncreaseMineSweep(x+1,	y-1);
		if (bBottom &amp;&amp; bLeft)	IncreaseMineSweep(x-1,	y+1);
		if (bBottom &amp;&amp; bRight)	IncreaseMineSweep(x+1,	y+1);
	}
};

const char MineField::MINE_MARK = '*';

std::istream&amp; operator&gt;&gt; (std::istream&amp; ist, MineField&amp; mineField)
{
	mineField &lt;&lt; ist;
	return ist;
}

std::ostream&amp; operator&lt;&lt; (std::ostream&amp; ost, const MineField&amp; mineField)
{
	mineField &gt;&gt; ost;
	return ost;
}

//-----------------------------------------------------------------------------A

#if UNIT_TEST
//-----------------------------------------------------------------------------V
// test code
class TestMineField : public MineField
{
public:
	explicit TestMineField(int width, int height, int fieldNumber)
		: MineField(width, height, fieldNumber)
	{}

	// delegate
	using MineField::AddMine;
	using MineField::GetField;
	using MineField::MINE_MARK;
};

TEST(MineField, Sweep1x1Field)
{
	TestMineField	mineField( 1, 1, 1 );
	mineField.AddMine( 0, 0 );
	mineField.Sweep();

	ASSERT_EQ(TestMineField::MINE_MARK, mineField.GetField(0,0));
}

TEST(MineField, Sweep3x3FieldCenterMine)
{
	TestMineField	mineField( 3, 3, 1 );
	mineField.AddMine( 1, 1 );
	mineField.Sweep();

	ASSERT_EQ(TestMineField::MINE_MARK, mineField.GetField(1,1));
	ASSERT_EQ('1', mineField.GetField(0,0));
	ASSERT_EQ('1', mineField.GetField(0,1));
	ASSERT_EQ('1', mineField.GetField(0,2));
	ASSERT_EQ('1', mineField.GetField(1,0));
	ASSERT_EQ('1', mineField.GetField(1,2));
	ASSERT_EQ('1', mineField.GetField(2,0));
	ASSERT_EQ('1', mineField.GetField(2,1));
	ASSERT_EQ('1', mineField.GetField(2,2));
}

TEST(MineField, Sweep2x3FieldAdjacentTwoMine)
{
	TestMineField	mineField( 2, 3, 1 );
	mineField.AddMine( 0, 0 );
	mineField.AddMine( 1, 1 );
	mineField.Sweep();

	ASSERT_EQ(TestMineField::MINE_MARK, mineField.GetField(0,0));
	ASSERT_EQ(TestMineField::MINE_MARK, mineField.GetField(1,1));
	ASSERT_EQ('2', mineField.GetField(1,0));
	ASSERT_EQ('1', mineField.GetField(2,0));
	ASSERT_EQ('2', mineField.GetField(0,1));
	ASSERT_EQ('1', mineField.GetField(2,1));
}

//-----------------------------------------------------------------------------A
int main(int argc, char **argv)
{
	testing::InitGoogleTest(&amp;argc, argv);
	return RUN_ALL_TESTS();
}
#else
int main(int argc, char **argv)
{
	//-------------------------------------------------------------------------V
	// submit code
	int fieldNumber = 1;

	int row, col;
	while (std::cin &gt;&gt; row &gt;&gt; col)
	{
		if (row == 0 || col == 0)	break;

		MineField	mineField(row, col, fieldNumber);
		std::cin &gt;&gt; mineField;
		mineField.Sweep();

		if (fieldNumber != 1)		std::cout &lt;&lt; std::endl;
		std::cout &lt;&lt; mineField;
		++fieldNumber;
	}
	//-------------------------------------------------------------------------A
	return 0;
}
#endif</pre>
<p>MineSweeper를 class 이름으로 했는데, 지뢰를 제거하는 함수 네이밍이 애매했다. 그래서 <strong>MineField로 이름을 변경하고 지뢰를 제거하는 함수 이름을 Sweep()이라 정했다.</strong> row, col, field number로 MineField를 생성하고 Sweep()으로 지뢰를 제거, 네이밍을 잘한 것 같다.</p>
<p><strong>결과를 스트링으로 출력하려고 했는데, string 생성, 소멸 비용이 아까웠다.</strong> 그래서 <strong>output stream</strong>으로 출력했다. 또한 input 파싱을 클래스 외부에서 하고 AddMine 함수로 입력하려고 했는데, input 값이 이상하게 들어오지 않는다는 전제 조건이 있기 때문에, 마음 편하게 클래스 내부에서 input stream을 받아서 파싱하는 걸로 변경했다.</p>
<p>MineField를 상속받은 TestMineField 클래스에서 MineField의 protected 멤버 함수를 호출하기 위해서 public 멤버 함수를 만들고 멤버 함수에서 protected 함수를 호출했었는데, 이렇게 손이 괴로울 필요 없이 <strong>using MineField::[protected member function] 으로 간단하게 delegate를 사용할 수 있다.</strong> Working effectively with legacy code 책에서 배웠는데, 테스트 클래스를 만들 때 유용하게 사용할 것 같다.</p>
<p>&nbsp;</p>
<p>예전 소스 코드</p>
<pre class="brush:cpp">//////////////////////////////////////////////////////////////////////////
// Minesweeper (UVa ID : 10189)
//
// Ohyecloudy ( Ohyecloudy@gmail.com )
// Accepted

#include &lt;iostream&gt;
using namespace std ;

char** field ;
int numRow, numCol ;

bool IsMine(int i, int j)
{
	if ( field[i][j] == '*' )
		return true ;
	else
		return false ;
}

void checkMineAround(int i, int j)
{
	// up is valid and not exist mine
	if ( i-1 &gt;= 0 &amp;&amp; !IsMine(i-1,j) )
		field[i-1][j]++ ;

	// down ..
	if ( i+1 &lt; numRow &amp;&amp; !IsMine(i+1, j) )
		field[i+1][j]++ ;

	// left ..
	if ( j-1 &gt;= 0 &amp;&amp; !IsMine(i, j-1) )
		field[i][j-1]++ ;

	// right ..
	if ( j+1 &lt; numCol &amp;&amp; !IsMine(i, j+1) )
		field[i][j+1]++ ;

	// up &amp; left ..
	if ( i-1 &gt;= 0 &amp;&amp; j-1 &gt;=0 &amp;&amp; !IsMine(i-1,j-1) )
		field[i-1][j-1]++ ;

	// up &amp; right ..
	if ( i-1 &gt;= 0 &amp;&amp; j+1 &lt; numCol &amp;&amp; !IsMine(i-1,j+1) )
		field[i-1][j+1]++ ;

	// down &amp; left ..
	if ( i+1 &lt; numRow &amp;&amp; j-1 &gt;= 0 &amp;&amp; !IsMine(i+1, j-1) )
		field[i+1][j-1]++ ;

	// down &amp; right ..
	if ( i+1 &lt; numRow &amp;&amp; j+1 &lt; numCol &amp;&amp; !IsMine(i+1, j+1) )
		field[i+1][j+1]++ ;
}

void BuildField()
{
	for ( int i = 0 ; i &lt; numRow ; ++i )
	{
		for ( int j = 0 ; j &lt; numCol ; ++j )
		{
			if ( field[i][j] == '*' )
				checkMineAround(i,j) ;
		}
	}
}

main()
{
	char temp[101] ;
	int num = 1 ;

	while( cin &gt;&gt; numRow &gt;&gt; numCol )
	{
		if ( numRow == 0 &amp;&amp; numCol == 0 )
			break ;

		if ( num != 1 )
			cout &lt;&lt; endl ;

		field = new char*[numRow] ;

		for ( int i = 0 ; i &lt; numRow ; ++i )
		{
			field[i] = new char[numCol] ;

			cin &gt;&gt; temp ;

			for ( int k = 0 ; k &lt; numCol ; ++k )
			{
				if ( temp[k] == '.' )
					field[i][k] = '0' ;
				else if ( temp[k] == '*' )
					field[i][k] = temp[k] ;
			}
		}

		BuildField() ;

		cout &lt;&lt; "Field #" &lt;&lt; num &lt;&lt; ":" &lt;&lt; endl ;

		for ( int j = 0 ; j &lt; numRow ; ++j )
		{
			for ( int k = 0 ; k &lt; numCol ; ++k )
				cout &lt;&lt; field[j][k] ;

			cout &lt;&lt; endl ;
		}

		for ( int l = 0 ; l &lt; numRow ; ++l )
			delete [] field[l] ;
		delete [] field ;

		num++ ;
	}
}</pre>
<p>언젠지 모르는 예전 코드. 보니깐 재미있다. 나중에 이 문제를 다시 풀어볼 때는 어떻게 작성할까?</p>
<p>&nbsp;</p>
<div class="acc_license"><a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"><img src="http://i.creativecommons.org/l/by-nc-sa/3.0/88x31.png" alt="by-nc-sa" /></a></div><!--<rdf:RDF xmlns="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><Work rdf:about=""><license rdf:resource="http://creativecommons.org/licenses/by-nc-sa/3.0/" /></Work><License rdf:about="http://creativecommons.org/licenses/by-nc-sa/3.0/"><requires rdf:resource="http://creativecommons.org/ns#Attribution" /><permits rdf:resource="http://creativecommons.org/ns#Reproduction" /><permits rdf:resource="http://creativecommons.org/ns#Distribution" /><permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /><requires rdf:resource="http://creativecommons.org/ns#ShareAlike" /><prohibits rdf:resource="http://creativecommons.org/ns#CommercialUse" /><requires rdf:resource="http://creativecommons.org/ns#Notice" /></License></rdf:RDF>-->]]></content:encoded>
			<wfw:commentRss>http://ohyecloudy.com/algo/archives/23/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ACM 100 (UVa ID) : The 3n + 1 problem</title>
		<link>http://ohyecloudy.com/algo/archives/5?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=acm-100-uva-id-the-3n-1-problem</link>
		<comments>http://ohyecloudy.com/algo/archives/5#comments</comments>
		<pubDate>Fri, 02 Jan 2009 23:57:32 +0000</pubDate>
		<dc:creator>ohyecloudy</dc:creator>
				<category><![CDATA[Volume I]]></category>
		<category><![CDATA[ad hoc]]></category>

		<guid isPermaLink="false">http://ohyecloudy.com/algo/?p=5</guid>
		<description><![CDATA[문제 링크 : http://uva.onlinejudge.org/external/1/100.html 응시 유저 수 : 44310 해결한 유저 비율 : 72.97% 소스 코드 //////////////////////////////////////////////////////////////////////////////// // UVa Online Judge(http://icpcres.ecs.baylor.edu/onlinejudge/) // // problem : 100 - The 3n + 1 problem // (http://uva.onlinejudge.org/external/1/100.html) // // OOP, Unit test, STL을 연습하기 위함 // // This file is licenced under a Creative Commons license: // http://creativecommons.org/licenses/by-nc-sa/2.0/kr/ [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li>문제 링크 : <a href="http://uva.onlinejudge.org/external/1/100.html" target="_blank">http://uva.onlinejudge.org/external/1/100.html</a></li>
<li>응시 유저 수 : 44310</li>
<li>해결한 유저 비율 : 72.97%</li>
</ul>
<p><a href="https://picasaweb.google.com/lh/photo/Rsnze9v1vScGZdhREhNw7RjKjL_S5HiV0-13YIuHFbQ?feat=embedwebsite"><img src="https://lh5.googleusercontent.com/-xCA4OEQU5SY/TvyHLlvqusI/AAAAAAAAJkk/rxR8Ka5sElA/s640/image_thumb_2.png" alt="" width="640" height="23" /></a><br />
<a href="https://picasaweb.google.com/lh/photo/SuyWyKz_EjegOBAyuO7_HBjKjL_S5HiV0-13YIuHFbQ?feat=embedwebsite"><img src="https://lh3.googleusercontent.com/-7gJ8OlX4ID8/TvyHLuz84bI/AAAAAAAAJko/HJaRG8Kvpw8/s640/image_thumb_3.png" alt="" width="640" height="24" /></a></p>
<p><span id="more-5"></span></p>
<p>소스 코드</p>
<pre class="brush:cpp">////////////////////////////////////////////////////////////////////////////////
// UVa Online Judge(http://icpcres.ecs.baylor.edu/onlinejudge/)
//
// problem : 100 - The 3n + 1 problem
// (http://uva.onlinejudge.org/external/1/100.html)
//
// OOP, Unit test, STL을 연습하기 위함
//
// This file is licenced under a Creative Commons license:
// http://creativecommons.org/licenses/by-nc-sa/2.0/kr/
///////////////////////////////////////////////2009. 01. 02 ohyecloudy@gmail.com
//////////////////////////////////////////////////////http://ohyecloudy.com/algo

#define UNIT_TEST 0

#if UNIT_TEST
#	include &lt;gtest/gtest.h&gt;
#endif

#include &lt;iostream&gt;
#include &lt;limits&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt;

#include &lt;cassert&gt;
//-----------------------------------------------------------------------------V
// submit code
class The3nPlus1Generator
{
public:
	explicit The3nPlus1Generator(int leftBorder, int rightBorder)
	{
		m_minBorder = std::min(leftBorder, rightBorder);
		m_maxBorder = std::max(leftBorder, rightBorder);
	}

	int	GetMaximumCycleLength()
	{
		m_cacheCount.resize(m_maxBorder-m_minBorder+1);
		std::fill(m_cacheCount.begin(), m_cacheCount.end(), 0);

		int maxCycleLength = std::numeric_limits&lt;int&gt;::min();
		for ( int i = m_minBorder; i &lt;= m_maxBorder; ++i )
		{
			maxCycleLength = std::max(GetCycleLength(i), maxCycleLength);
		}

		return maxCycleLength;
	}

private:
	int						m_minBorder, m_maxBorder;
	std::vector&lt;int&gt;		m_cacheCount;

private:
	int GetCycleLength(int number)
	{
		assert(number &gt;= 1);
		if (number &lt; 1)			return 0;

		int cycle = 0;
		int currentNumber = number;
		while (currentNumber != 1)
		{
			//-----------------------------------------------------------------V
			// cycle length를 캐싱해서 퍼포먼스를 높인다.
			if (m_minBorder &lt;= currentNumber &amp;&amp; currentNumber &lt;= m_maxBorder)
			{
				int currentNumberIndex = currentNumber-m_minBorder;

				// 캐시된 cycle length count가 있으면 사용한다.
				if (m_cacheCount[currentNumberIndex] &gt; 0)
				{
					int retCycle = cycle + m_cacheCount[currentNumberIndex];

					return retCycle;
				}
				else if (currentNumber != number &amp;&amp;
						m_cacheCount[currentNumberIndex] == 0)
				{
					// 캐시된 cycle length count가 없으면
					// 바로 그 숫자의 cycle length를 구한다.
					// 무한 루프를 방지하기 위해 숫자가 다른지 확인.
					m_cacheCount[currentNumberIndex] =
						GetCycleLength(currentNumber);

					return cycle + m_cacheCount[currentNumberIndex];
				}
			}
			//-----------------------------------------------------------------A

			cycle++;

			if (currentNumber % 2 == 1)
			{
				currentNumber = currentNumber * 3 + 1;	// odd
			}
			else
			{
				currentNumber /= 2;						// even
			}
		}

		// 1일때 싸이클 횟수를 더해준다.
		cycle++;

		return cycle;
	}
};
//-----------------------------------------------------------------------------A

#if UNIT_TEST
//-----------------------------------------------------------------------------V
// test code
TEST(The3nPlus1Generator, SameInputBorder)
{
	EXPECT_EQ( 1, The3nPlus1Generator(1,1).GetMaximumCycleLength());
	EXPECT_EQ( 16, The3nPlus1Generator(22,22).GetMaximumCycleLength());
}

TEST(The3nPlus1Generator, ProblemSample)
{
	EXPECT_EQ( 20, The3nPlus1Generator(1,10).GetMaximumCycleLength());
	EXPECT_EQ( 125, The3nPlus1Generator(100,200).GetMaximumCycleLength());
	EXPECT_EQ( 89, The3nPlus1Generator(201,210).GetMaximumCycleLength());
	EXPECT_EQ( 174, The3nPlus1Generator(900,1000).GetMaximumCycleLength());
}

TEST(The3nPlus1Generator, ProblemSampleReserveInput)
{
	EXPECT_EQ( 20, The3nPlus1Generator(10,1).GetMaximumCycleLength());
	EXPECT_EQ( 125, The3nPlus1Generator(200,100).GetMaximumCycleLength());
	EXPECT_EQ( 89, The3nPlus1Generator(210,201).GetMaximumCycleLength());
	EXPECT_EQ( 174, The3nPlus1Generator(1000,900).GetMaximumCycleLength());
}

//-----------------------------------------------------------------------------A
int main(int argc, char **argv)
{
	testing::InitGoogleTest(&amp;argc, argv);
	return RUN_ALL_TESTS();
}
#else
int main(int argc, char **argv)
{
	//-------------------------------------------------------------------------V
	// submit code
	int leftBorder, rightBorder;
	while ( std::cin &gt;&gt; leftBorder &gt;&gt; rightBorder )
	{
		std::cout &lt;&lt; leftBorder &lt;&lt; " " &lt;&lt; rightBorder &lt;&lt; " "
			&lt;&lt; The3nPlus1Generator(leftBorder, rightBorder).
				GetMaximumCycleLength()
			&lt;&lt; std::endl;
	}	

	//-------------------------------------------------------------------------A
	return 0;
}
#endif</pre>
<p>입력값이 반드시 min, max 순으로 들어오지 않는다. 이것만 주의하면 된다. cycle length를 캐싱하니 6배 퍼포먼스 향상이 있다.</p>
<p>옛날 옛적 코드.</p>
<pre class="brush:cpp">#include &lt;iostream&gt;
using std::cout ;
using std::cin ;
using std::endl ;

long* icycleLength ;
long numTerm ;

long cycleLength(long input, long start, long end )
{
	long current = input ;
	long cycleLength = 0 ;

	while ( current != 1 )
	{
		if ( current &gt;= start &amp;&amp; current &lt;= end &amp;&amp; icycleLength[current-start] != -1 )
		{
			cycleLength += icycleLength[current-start] -1 ;
			// -1의 이유는 while loop 끝나고 1을 포함하기 위해 1더하는 것이랑
			// icycleLength array의 값이 1을 포함하고 있는 것이 중복 되기 때문.
			break ;
		}

		if ( current % 2 == 0 ) // even
		{
			current /= 2 ;
			cycleLength++ ;
		}
		else // odd
		{
			current = current * 3 + 1 ;
			cycleLength++ ;
		}
	}

	cycleLength++ ;
	/// include 1

	return cycleLength ;
}

// start~end 사이의 모든 cycle계산
// return cycle
long calcyclelength(long start, long end)
{
	long i ;

	numTerm = end-start + 1 ;

	icycleLength = new long[numTerm] ;
	for ( i = 0 ; i &lt; numTerm ; ++i )
		icycleLength[i] = -1 ;

	// start의 cycleLength 계산.
	long max = cycleLength( start, start, end ) ;
	icycleLength[0] = max ;

	for ( i = 1 ; i &lt; numTerm ; ++i )
	{
		long temp = cycleLength(i+start, start, end) ;
		icycleLength[ i ] = temp ;

		if ( temp &gt; max )
			max = temp ;
	}

	return max ;
}

main()
{
	long start , end, retVal ;

	while ( cin &gt;&gt; start &gt;&gt; end )
	{
		retVal = calcyclelength(start, end) ;
		cout &lt;&lt; start &lt;&lt; " " &lt;&lt; end &lt;&lt; " " &lt;&lt; retVal &lt;&lt; endl ;
	}

	delete[] icycleLength ;
}</pre>
<div class="acc_license"><a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"><img src="http://i.creativecommons.org/l/by-nc-sa/3.0/88x31.png" alt="by-nc-sa" /></a></div><!--<rdf:RDF xmlns="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><Work rdf:about=""><license rdf:resource="http://creativecommons.org/licenses/by-nc-sa/3.0/" /></Work><License rdf:about="http://creativecommons.org/licenses/by-nc-sa/3.0/"><requires rdf:resource="http://creativecommons.org/ns#Attribution" /><permits rdf:resource="http://creativecommons.org/ns#Reproduction" /><permits rdf:resource="http://creativecommons.org/ns#Distribution" /><permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /><requires rdf:resource="http://creativecommons.org/ns#ShareAlike" /><prohibits rdf:resource="http://creativecommons.org/ns#CommercialUse" /><requires rdf:resource="http://creativecommons.org/ns#Notice" /></License></rdf:RDF>-->]]></content:encoded>
			<wfw:commentRss>http://ohyecloudy.com/algo/archives/5/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Code Template</title>
		<link>http://ohyecloudy.com/algo/archives/42?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=code-template</link>
		<comments>http://ohyecloudy.com/algo/archives/42#comments</comments>
		<pubDate>Thu, 01 Jan 2009 22:00:15 +0000</pubDate>
		<dc:creator>ohyecloudy</dc:creator>
				<category><![CDATA[출발점]]></category>

		<guid isPermaLink="false">http://ohyecloudy.com/algo/?p=42</guid>
		<description><![CDATA[//////////////////////////////////////////////////////////////////////////////// // UVa Online Judge(http://uva.onlinejudge.org/) // // problem : number problem (http://) // // - OOP, Unit test, STL을 남발한다. // - 속도보다는 읽기 좋게 작성한다. // // This file is licenced under a Creative Commons license: // http://creativecommons.org/licenses/by-nc-sa/2.0/kr/ ////////////////////////////////////////////2009. 00. 00 ohyecloudy at gmail.com //////////////////////////////////////////////////////http://ohyecloudy.com/algo #ifdef ONLINE_JUDGE # define UNIT_TEST 0 #else # define [...]]]></description>
			<content:encoded><![CDATA[<pre class="brush:cpp">////////////////////////////////////////////////////////////////////////////////
// UVa Online Judge(http://uva.onlinejudge.org/)
//
// problem : number problem (http://)
//
// - OOP, Unit test, STL을 남발한다.
// - 속도보다는 읽기 좋게 작성한다.
//
// This file is licenced under a Creative Commons license:
// http://creativecommons.org/licenses/by-nc-sa/2.0/kr/
////////////////////////////////////////////2009. 00. 00 ohyecloudy at gmail.com
//////////////////////////////////////////////////////http://ohyecloudy.com/algo

#ifdef ONLINE_JUDGE
#   define UNIT_TEST 0
#else
#   define UNIT_TEST 1
#endif  

#if UNIT_TEST
#	include &lt;gtest/gtest.h&gt;
#endif

//#############################################################################V
// submit code

//#############################################################################A

#if UNIT_TEST
//#############################################################################V
// test code

//#############################################################################A
int main(int argc, char **argv)
{
	testing::InitGoogleTest(&amp;argc, argv);
	return RUN_ALL_TESTS();
}
#else
int main()
{
	//#########################################################################V
	// submit code

	//#########################################################################A
	return 0;
}
#endif</pre>
<p>&nbsp;</p>
<div class="acc_license"><a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"><img src="http://i.creativecommons.org/l/by-nc-sa/3.0/88x31.png" alt="by-nc-sa" /></a></div><!--<rdf:RDF xmlns="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><Work rdf:about=""><license rdf:resource="http://creativecommons.org/licenses/by-nc-sa/3.0/" /></Work><License rdf:about="http://creativecommons.org/licenses/by-nc-sa/3.0/"><requires rdf:resource="http://creativecommons.org/ns#Attribution" /><permits rdf:resource="http://creativecommons.org/ns#Reproduction" /><permits rdf:resource="http://creativecommons.org/ns#Distribution" /><permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /><requires rdf:resource="http://creativecommons.org/ns#ShareAlike" /><prohibits rdf:resource="http://creativecommons.org/ns#CommercialUse" /><requires rdf:resource="http://creativecommons.org/ns#Notice" /></License></rdf:RDF>-->]]></content:encoded>
			<wfw:commentRss>http://ohyecloudy.com/algo/archives/42/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

