#include <vector>
#include <string>
#include <map>
#include <iostream>
class InputProcessor
{
public:
// break type
enum BREAK_CONDITION
{
BREAK_EOF = 0,
BREAK_ENTER,
BREAK_ZERO,
BREAK_TOTAL
};
// »ý¼ºÀÚ / ¼Ò¸êÀÚ
InputProcessor(BREAK_CONDITION _eBreak) { eBreakCondition_ = _eBreak; }
virtual ~InputProcessor() {}
// ÀÎÅÍÆäÀ̽º
virtual void process() = 0;
virtual int getDataIndexCount() = 0;
virtual const std::vector<int>* getDigits(int _nIndex) = 0;
virtual const std::vector<std::string>* getChars(int _nIndex) = 0;
// Test¸¦ À§ÇÑ ÇÔ¼ö
virtual void addTestInput(const char* pSzTestData) = 0;
protected:
// break condition
BREAK_CONDITION eBreakCondition_;
// data manipulator
// ·ÎÄà ÅÛÇø´ Ŭ·¡½º´Â ¸í½ÃÀû ƯȰ¡ Çã¿ëµÇÁö ¾Ê°í ºÎºÐƯȸ¸ Çã¿ëµÈ´Ù. ±×¿¡ ´ëÇÑ ²Ç¼ö
// cf. ºñÁÖ¾ó½ºÆ©µð¿À È®ÀåÀ¸·Î ·ÎÄÃŬ·¡½ºÀÇ ¸í½ÃÀû ƯȰ¡ Çã¿ëµÈ´Ù.
template< typename T, typename PartialSpecialization = bool >
struct SDataManipulator{};
template< typename PartialSpecialization >
struct SDataManipulator< int, PartialSpecialization >
{
static int convertData(char* _pSzData){ return atoi( _pSzData ); }
static const int getZero(){return 0;}
static const std::vector<int>* getDigits(std::vector< std::vector<int>* >& _refVecData, int _nIndex)
{
return _refVecData[ _nIndex ];
}
static const std::vector<std::string>* getChars(std::vector< std::vector<int>* >& _refVecData, int _nIndex)
{
return 0;
}
};
template< typename PartialSpecialization >
struct SDataManipulator< std::string, PartialSpecialization >
{
static char* convertData(char* _pSzData){ return _pSzData; }
static const char* getZero(){ return "0";}
static const std::vector<int>* getDigits(std::vector< std::vector<std::string>* >& _refVecData, int _nIndex)
{
return 0;
}
static const std::vector<std::string>* getChars(std::vector< std::vector<std::string>* >& _refVecData, int _nIndex)
{
return _refVecData[ _nIndex ];
}
};
// multiline data
template< typename T >
struct SInputData
{
// data container
std::vector< std::vector<T>* > aVecVecData;
// get data
void processData(BREAK_CONDITION _eBreak, const char* _pSzManualData )
{
char buf[512];
bool bLoop = true;
while( bLoop )
{
if( _pSzManualData == 0 )
{
// ¶óÀÎÀ¸·Î ÀԷ¹ޱâ
if( gets( buf ) == 0 )
return;
}
else
{
strcpy(buf, _pSzManualData);
bLoop = false;
}
std::vector<T>* pVector = new std::vector<T>;
char* pSzEach = strtok(buf, " ");
while (pSzEach!= 0)
{
pVector->push_back( SDataManipulator<T>::convertData( pSzEach ) );
pSzEach = strtok(0, " ");
}
// Zero Break
if( _eBreak == BREAK_ZERO && pVector->size() == 2 )
{
if( (*pVector)[0] == SDataManipulator<T>::getZero() && (*pVector)[1] == SDataManipulator<T>::getZero() )
{
delete pVector;
return;
}
}
aVecVecData.push_back( pVector );
// Enter Break
if( _eBreak == BREAK_ENTER )
return;
}
}
// clear data
void clearData()
{
int nSize = (int)aVecVecData.size();
for( int i = 0; i < nSize; ++i)
{
delete aVecVecData[i];
}
aVecVecData.clear();
}
};
};
template< typename T >
class InputProcessorImpl : public InputProcessor
{
public:
InputProcessorImpl(BREAK_CONDITION _eBreak) : InputProcessor(_eBreak) {}
virtual ~InputProcessorImpl(){ aData_.clearData(); }
virtual void process()
{
if( aData_.aVecVecData.empty() == false )
aData_.clearData();
aData_.processData( eBreakCondition_, 0);
}
virtual const std::vector<int>* getDigits(int _nIndex)
{
if( _nIndex < 0 || aData_.aVecVecData.empty() || _nIndex >= getDataIndexCount() )
return 0;
return InputProcessor::SDataManipulator<T>::getDigits(aData_.aVecVecData, _nIndex);
}
virtual const std::vector<std::string>* getChars(int _nIndex)
{
if( _nIndex < 0 || aData_.aVecVecData.empty() || _nIndex >= getDataIndexCount() )
return 0;
return InputProcessor::SDataManipulator<T>::getChars(aData_.aVecVecData, _nIndex);
}
virtual int getDataIndexCount()
{
return (int)aData_.aVecVecData.size();
}
virtual void addTestInput(const char* pSzTestData)
{
aData_.processData(InputProcessor::BREAK_EOF, pSzTestData );
}
private:
InputProcessor::SInputData< T > aData_;
};
//////////////////////////////////////////////////////////////////////
//
// Code Dojo Interface
//
//////////////////////////////////////////////////////////////////////
class CodeDojo
{
public:
CodeDojo() {}
virtual ~CodeDojo() {}
virtual void solveTheProblem( InputProcessor* _pInput ) = 0;
};
class CodeDojoLCDDisplay : public CodeDojo
{
private:
struct DISPLAY_DIGIT
{
DISPLAY_DIGIT(int _nNumber)
{
switch( _nNumber )
{
case 0:
{
m_bTOPHori = true;
m_bMiddleHori = false;
m_bBottomHori = true;
m_bFirstVerticalLeft = true;
m_bFirstVerticalRight = true;
m_bSecondVerticalLeft = true;
m_bSecondVerticalRight = true;
}
break;
case 1:
{
m_bTOPHori = false;
m_bMiddleHori = false;
m_bBottomHori = false;
m_bFirstVerticalLeft = false;
m_bFirstVerticalRight = true;
m_bSecondVerticalLeft = false;
m_bSecondVerticalRight = true;
}
break;
case 2:
{
m_bTOPHori = true;
m_bMiddleHori = true;
m_bBottomHori = true;
m_bFirstVerticalLeft = false;
m_bFirstVerticalRight = true;
m_bSecondVerticalLeft = true;
m_bSecondVerticalRight = false;
}
break;
case 3:
{
m_bTOPHori = true;
m_bMiddleHori = true;
m_bBottomHori = true;
m_bFirstVerticalLeft = false;
m_bFirstVerticalRight = true;
m_bSecondVerticalLeft = false;
m_bSecondVerticalRight = true;
}
break;
case 4:
{
m_bTOPHori = false;
m_bMiddleHori = true;
m_bBottomHori = false;
m_bFirstVerticalLeft = true;
m_bFirstVerticalRight = true;
m_bSecondVerticalLeft = false;
m_bSecondVerticalRight = true;
}
break;
case 5:
{
m_bTOPHori = true;
m_bMiddleHori = true;
m_bBottomHori = true;
m_bFirstVerticalLeft = true;
m_bFirstVerticalRight = false;
m_bSecondVerticalLeft = false;
m_bSecondVerticalRight = true;
}
break;
case 6:
{
m_bTOPHori = true;
m_bMiddleHori = true;
m_bBottomHori = true;
m_bFirstVerticalLeft = true;
m_bFirstVerticalRight = false;
m_bSecondVerticalLeft = true;
m_bSecondVerticalRight = true;
}
break;
case 7:
{
m_bTOPHori = true;
m_bMiddleHori = false;
m_bBottomHori = false;
m_bFirstVerticalLeft = false;
m_bFirstVerticalRight = true;
m_bSecondVerticalLeft = false;
m_bSecondVerticalRight = true;
}
break;
case 8:
{
m_bTOPHori = true;
m_bMiddleHori = true;
m_bBottomHori = true;
m_bFirstVerticalLeft = true;
m_bFirstVerticalRight = true;
m_bSecondVerticalLeft = true;
m_bSecondVerticalRight = true;
}
break;
case 9:
{
m_bTOPHori = true;
m_bMiddleHori = true;
m_bBottomHori = true;
m_bFirstVerticalLeft = true;
m_bFirstVerticalRight = true;
m_bSecondVerticalLeft = false;
m_bSecondVerticalRight = true;
}
break;
}
}
bool m_bTOPHori;
bool m_bMiddleHori;
bool m_bBottomHori;
bool m_bFirstVerticalLeft;
bool m_bFirstVerticalRight;
bool m_bSecondVerticalLeft;
bool m_bSecondVerticalRight;
};
public:
virtual void solveTheProblem( InputProcessor* _pInput )
{
_pInput->process();
int nLineCount = _pInput->getDataIndexCount();
for(int i = 0; i < nLineCount; ++i)
{
// check input
const std::vector<int>* pInputDigits = _pInput->getDigits(i);
if(pInputDigits->size() != 2)
{
printf("Invalid Input");
return;
}
// element for display : size, number, dispaly letter.
int nSizeToDisplay = pInputDigits->at(0);
int nNumberToDisplay = pInputDigits->at(1);
std::vector<DISPLAY_DIGIT> displayDigits;
// check input
if( (nNumberToDisplay > 99999999 || nNumberToDisplay < 0) ||
(nSizeToDisplay > 10 || nSizeToDisplay < 1) )
{
printf("Invalid Input");
return;
}
// build dispaly-digits from input number
buildDisplayDigits_(nNumberToDisplay, displayDigits);
// display
display_(nSizeToDisplay, displayDigits);
printf("\n\n");
}
}
private:
void buildDisplayDigits_(int _nNumber, std::vector<DISPLAY_DIGIT>& _vecDispalyDigits )
{
char szBuf[10];
sprintf( szBuf, "%d", _nNumber );
std::string strNumber = szBuf;
int nCount = (int)strNumber.size();
for(int i = 0; i < nCount; ++i)
{
_vecDispalyDigits.push_back( DISPLAY_DIGIT(strNumber[i] - '0') );
}
}
void display_(int _nSize, const std::vector<DISPLAY_DIGIT>& _vecDispalyDigits)
{
int nDisplayLoopCount = calcDisplayLoopCount_(_nSize);
for( int i = 0; i < nDisplayLoopCount; ++i )
{
DISPLAY_POS ePos = calcDisplayPos_(_nSize, nDisplayLoopCount, i);
char* pBuff = makeDipslayBuffFromPos_(ePos, _nSize, _vecDispalyDigits);
printf(pBuff);
delete pBuff;
if( i < nDisplayLoopCount-1 )
printf("\n");
}
}
enum DISPLAY_POS
{
E_TOP = 0,
E_TOP_MIDDLE,
E_MIDDLE,
E_MIDDLE_BOTTOM,
E_BOTTOM
};
int calcDisplayLoopCount_(int _nDisplaySize)
{
// óÀ½ - Áß°£ - ³¡ ÀÌ 3°³ µé¾î°¡°í
// °¡¿îµ¥ µÎ°³ µé¾î°¡´Â°ÍÀº ÀÔ·ÂµÈ »çÀÌÁîÀÇ µÎ¹è
// -- -- --
// | | | | | |
// | | | | | |
// -- -- -- --
// | | | | |
// | | | | |
// -- -- --
return _nDisplaySize*2 + 3;
}
DISPLAY_POS calcDisplayPos_(int _nDisplaySize, int _nDisplayLoopCount, int _nCurrnetIndex)
{
DISPLAY_POS ePos;
if( _nCurrnetIndex == 0 )
{
ePos = E_TOP;
}
else if( _nCurrnetIndex == _nDisplaySize + 1 )
{
ePos = E_MIDDLE;
}
else if( _nCurrnetIndex == _nDisplayLoopCount - 1 )
{
ePos = E_BOTTOM;
}
else if( _nCurrnetIndex < _nDisplaySize + 1 )
{
ePos = E_TOP_MIDDLE;
}
else
{
ePos = E_MIDDLE_BOTTOM;
}
return ePos;
}
char* makeDipslayBuffFromPos_(DISPLAY_POS _ePos, int _nDisplaySize, const std::vector<DISPLAY_DIGIT>& _vecDispalyDigits)
{
int nCount = (int)_vecDispalyDigits.size();
int nBufSize = nCount * (_nDisplaySize + 2) + (nCount - 1);
char* pSzBuf;
pSzBuf = new char[nBufSize + 1];
memset(pSzBuf, ' ', nBufSize);
pSzBuf[nBufSize] = '\0';
for(int i = 0; i < nCount; ++i)
{
const DISPLAY_DIGIT& digit = _vecDispalyDigits[i];
int nStartIndex = i * (_nDisplaySize + 2) + i;
switch( _ePos )
{
case E_TOP:
{
if(digit.m_bTOPHori)
{
nStartIndex += 1;
for( int j = 0; j < _nDisplaySize; ++j )
{
pSzBuf[j+nStartIndex] = '-';
}
}
}
break;
case E_TOP_MIDDLE:
{
if(digit.m_bFirstVerticalLeft)
{
pSzBuf[nStartIndex] = '|';
}
if(digit.m_bFirstVerticalRight)
{
pSzBuf[nStartIndex + _nDisplaySize + 1] = '|';
}
}
break;
case E_MIDDLE:
{
if(digit.m_bMiddleHori)
{
nStartIndex += 1;
for( int j = 0; j < _nDisplaySize; ++j )
{
pSzBuf[j+nStartIndex] = '-';
}
}
}
break;
case E_MIDDLE_BOTTOM:
{
if(digit.m_bSecondVerticalLeft)
{
pSzBuf[nStartIndex] = '|';
}
if(digit.m_bSecondVerticalRight)
{
pSzBuf[nStartIndex + _nDisplaySize + 1] = '|';
}
}
break;
case E_BOTTOM:
{
if(digit.m_bBottomHori)
{
nStartIndex += 1;
for( int j = 0; j < _nDisplaySize; ++j )
{
pSzBuf[j+nStartIndex] = '-';
}
}
}
break;
}
}
return pSzBuf;
}
};
int main()
{
InputProcessor* pInput = new InputProcessorImpl<int>(InputProcessor::BREAK_ZERO);
CodeDojo* pCodeDojo = new CodeDojoLCDDisplay;
// ¹®Á¦ Ç®±â
pCodeDojo->solveTheProblem( pInput );
delete pCodeDojo;
delete pInput;
return 0;
}
|