본문 바로가기

C++ in Windows/Challenges

ICPC 대비 문제 6. 인터프리터(interpreter)

>> 문제 6. 인터프리터(interpreter)

 

PC/UVa ID: 110106/10033, 인기도: B, 성공률: 낮음, 레벨: 2

 

어떤 컴퓨터에 열 개의 레지스터와 1,000워드 분량의 램(RAM)이 있다. 각 레지스터 또는 램 위치에는 0 이상 999 이하의 세 자리 정수가 저장된다. 명령어는 세 자리 정수로 인코딩되며 램에 저장된다. 인코딩은 다음과 같다.

 

100

종료

2dn

d 레지스터를 n으로 설정(0이상 9이하)

3dn

d 레지스터에 n 더함

4dn

d 레지스터에 n 곱함

5ds

d 레지스터를 s 레지스터의 값으로 설정

6ds

s 레지스터의 값을 d레지스터에 더함

7ds

d 레지스터에 s 레지스터의 값을 곱함

8da

d 레지스터를 a 레지스터에 저장된 주소의 램에 들어있는 값으로 설정

9sa

a 레지스터에 저장된 주소의 램에 s 레지스터의 값을 대입

0ds

s 레지스터에 0이 들어있지 않으면 d 레지스터에 있는 위치로 이동

 

모든 레지스터의 초기값은 000이다. 램에 저장되는 초기 값은 표준 입력으로부터 들어온다. 처음으로 실행될 명령은 주소가 0인 램에 들어있다. 모든 결과는 값이 1,000이 넘어가면 1,000으로 나눈 나머지로 줄어든다.

 

>> 입력

입력은 입력 케이스의 개수를 나타내는 양의 정수 한 개가 들어있는 줄로 시작되며 그 줄에는 그 숫자밖에 입력되지 않는다. 그 뒤에는 빈 줄이 하나 들어가고 서로 다른 입력 케이스 사이에는 빈 줄 두 개가 입력된다. 각 입력 케이스는 최대 1,000개의 부호가 없는 세 자리 정수로 구성되며 그 숫자들은 0부터 시작하는 연속된 램 위치에 저장되는 내용을 나타낸다. 값이 지정되지 않는 램 위치는 000으로 초기화 된다.

 

>> 출력

각 테스트 케이스마다 하나씩 정수를 출력한다. 출력되는 정수는 종료 명령어에 이르기까지(종료 명령어 포함) 실행된 명령어의 개수다. 프로그램이 종료된다고 미리 가정해도 된다. 케이스가 여러 개 있는 경우에는 각 출력 사이에 빈 줄을 출력한다.

 

>> 입력예

1

 

299

492

495

399

492

495

399

283

279

689

078

100

000

000

000

 

>> 출력예

16



소스보기
#include <iostream>
#include <string>

using namespace std;

void main (void)
{
	typedef struct {
		int Register[10];
		int memory[1000]; 
	}interpreter;

	interpreter itp;
	int	numCase = 0;
	
	string str;
	
	getline(cin, str);
	numCase = atoi(str.c_str());

	for (int caseCnt = 0; caseCnt < numCase; caseCnt++)
	{
		string str;
		
		getline(cin, str);
		
		getline(cin, str);
		
		memset(&itp, 0, sizeof(itp));

		int totPC = 0;		// 입력된 명령어의수.
		
		while(str.length() > 0 )
		{
			itp.memory[totPC++] = atoi(str.c_str()) % 1000;
	
			getline(cin, str);
		}
		
		bool flag = true;	// 연산 loop 강제종료를 위해
		int excnt = 0, pc = 0;
		
		while(pc <= totPC && flag)
		{
			// a는 10의 자리 명령어
			int a = (itp.memory[pc]/10) % 10;
			// b는 1의 자리 명령어.
			int b = itp.memory[pc] % 10;
			// c는 100의 자리 명령어.
			int c = itp.memory[pc] / 1000;

			pc++;

			switch ( c )
			{
				case 1:
					// 종료
					flag = false;
					break;
				case 2:
					// d 레지스터를 n으로 설정(0이상 9이하)
					itp.Register[a] = b;
					break;
				case 3:
					// d 레지스터에 n 더함.
					itp.Register[a] += b;
					break;
				case 4:
					// d 레지스터에 n곱함.
					itp.Register[a] *= b;
					break;
				case 5:
					// d 레지스터를 s 레지스터의 값으로 설정.
					itp.Register[a] = itp.Register[b];
					break;
				case 6:
					// s 레지스터의 값을 d레지스터에 더함
					itp.Register[a] += itp.Register[b];
					break;
				case 7:
					// d 레지스터에 s 레지스터의 값을 곱함
					itp.Register[a] *= itp.Register[b];
					break;
				case 8:
					// d 레지스터를 a 레지스터에 저장된 
					// 주소의 램에 들어있는 값으로 설정.
					itp.Register[a] = itp.memory[itp.Register[b]];
					break;
				case 9:
					// a 레지스터에 저장된 주소의 램에
					// s 레지스터의 값을 대입
					itp.memory[itp.Register[b]] = itp.Register[a];
					break;
				case 0:
					// s 레지스터에 0이 들어있지 않으면
					// d 레지스터에 있는 위치로 이동.
					if ( itp.Register[b] != 0 )
						pc = itp.Register[a];
					break;
			}
			++excnt;
		}

		cout << excnt << "\n";
		getline(cin, str);
	}
	
}





처음 문제를 읽었을때 이해가 잘 안가 고민좀 했다.