게임 클라이언트 개발/알고리즘 문제

[3차] n진수 게임 (2018 카카오, 구현)

주운녕 2025. 1. 9. 00:42

문제 설명
N진수 게임
튜브가 활동하는 코딩 동아리에서는 전통적으로 해오는 게임이 있다. 이 게임은 여러 사람이 둥글게 앉아서 숫자를 하나씩 차례대로 말하는 게임인데, 규칙은 다음과 같다.

숫자를 0부터 시작해서 차례대로 말한다. 첫 번째 사람은 0, 두 번째 사람은 1, … 열 번째 사람은 9를 말한다.
10 이상의 숫자부터는 한 자리씩 끊어서 말한다. 즉 열한 번째 사람은 10의 첫 자리인 1, 열두 번째 사람은 둘째 자리인 0을 말한다.
이렇게 게임을 진행할 경우,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4, …
순으로 숫자를 말하면 된다.

한편 코딩 동아리 일원들은 컴퓨터를 다루는 사람답게 이진수로 이 게임을 진행하기도 하는데, 이 경우에는
0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, …
순으로 숫자를 말하면 된다.

이진수로 진행하는 게임에 익숙해져 질려가던 사람들은 좀 더 난이도를 높이기 위해 이진법에서 십육진법까지 모든 진법으로 게임을 진행해보기로 했다. 숫자 게임이 익숙하지 않은 튜브는 게임에 져서 벌칙을 받는 굴욕을 피하기 위해, 자신이 말해야 하는 숫자를 스마트폰에 미리 출력해주는 프로그램을 만들려고 한다. 튜브의 프로그램을 구현하라.

입력 형식
진법 n, 미리 구할 숫자의 갯수 t, 게임에 참가하는 인원 m, 튜브의 순서 p 가 주어진다.

2 ≦ n ≦ 16
0 < t ≦ 1000
2 ≦ m ≦ 100
1 ≦ p ≦ m
출력 형식
튜브가 말해야 하는 숫자 t개를 공백 없이 차례대로 나타낸 문자열. 단, 10~15는 각각 대문자 A~F로 출력한다.

입출력 예제
n t m p result
2 4 2 1 "0111"
16 16 2 1 "02468ACE11111111"
16 16 2 2 "13579BDF01234567"


문제 풀이

- 해야할 것
1. 숫자 몇까지 n진법을 변환할 것인지 구해야함
2. 변환하는 방법 세우기
3. 순회하면서 몇번째 자리수를 가져와야하는지 구해야한다.

풀이 방법
1. 인원 m, 구할 숫자 개수: t
ㄴ 변환하여 수집한 숫자의 개수가 t * m 보다 커지면 그만 수집한다.
ㄴ 변환하면서 체크해야함
2. 변환하는 함수 (TranferToNFormation)
3. 순회하며 자리 뽑기

 

느낀점

차분히 정리하고 순서대로 구현하면 된다.

 

개선점

- 10 이상을 16진법으로 표현할 때는 변환식 세우지말고 그냥 string num = "0123456789ABCDEF"; 을 이용하면 된다.

- n진법으로 나타낼 때에는 대상 num이 0인 경우 0반환 따로 해주고, 그 외는 몫이 0보다 클동안 계속 나머지를 넣어주면된다.

ㄴ 이후 직접 반대방향으로 뒤집지 말고 reverse 함수를 이용한다.

	string transfered;
	if (curNum == 0)
		return "0";
	while (curNum > 0)
	{
		transfered += num[curNum % nFormation];
		curNum /= nFormation; // 몫
	}
    reverse(transfered.begin(), transfered.end());

 

개선 전 코드

#include <string>
#include <vector>

using namespace std;

string CheckAndChangeToAlpha(int num)
{
	string str;
	if (num >= 10)
	{
		char temp = 'A' + num - 10;
		str += temp;
		return str;
	}

	return to_string(num);
}

string TranferToNFormation(int idx, int nFormation)
{
	string transfered;
	int cur = idx;
	while (true)
	{
		int m = cur / nFormation; // 몫
		int n = cur % nFormation; // 나머지

		if (m / nFormation > 0)
		{
			transfered += CheckAndChangeToAlpha(n);
			cur = m;
		}
		else
		{
			transfered += CheckAndChangeToAlpha(n);
			if (m > 0)
				transfered += CheckAndChangeToAlpha(m);
			break;
		}
	}
	string temp;
	int start = transfered.length() - 1;
	for (int j = start; j >= 0; j--)
		temp += transfered[j];

	return temp;
}

string solution(int n, int t, int m, int p) {
	string answer = "";

	int maxSize = t * m;
	int idx = 0;
	string transfer;
	while (true)
	{
		transfer += TranferToNFormation(idx, n);
  		if (transfer.length() > maxSize)
			break;
		idx++;
	}

	int cnt = 0;
	for (int i = 0; i < transfer.length(); i++)
	{
		if (answer.length() == t)
			break;
		cnt++;
		if (cnt == p)
			answer += transfer[i];
		if (cnt == m)
			cnt = 0;
	}
	return answer;
}

 

개선 후 코드

#include <string>
#include <vector>
#include <algorithm>

using namespace std;

string num = "0123456789ABCDEF";
string TranferToNFormation(int curNum, int nFormation)
{
	string transfered;
	if (curNum == 0)
		return "0";
	while (curNum > 0)
	{
		transfered += num[curNum % nFormation];
		curNum /= nFormation; // 몫
	}
	reverse(transfered.begin(), transfered.end());
	return transfered;
}

string solution(int n, int t, int m, int p) {
	string answer = "";
	int maxSize = t * m;
	int idx = 0;
	string transfer;
	while (true)
	{
		transfer += TranferToNFormation(idx, n);
  		if (transfer.length() > maxSize)
			break;
		idx++;
	}

	int cnt = 0;
	for (int i = 0; i < transfer.length(); i++)
	{
		if (answer.length() == t)
			break;
		cnt++;
		if (cnt == p)
			answer += transfer[i];
		if (cnt == m)
			cnt = 0;
	}
	return answer;
}