[ Programmers ] 2018 KAKAO BLIND RECRUITMENT - [3차] n진수 게임 (Java)

ma.caron_g·2021년 12월 13일
0

Lv.2 - Programmers

목록 보기
10/14
post-thumbnail

1. Problem 📃

[ n진수 게임 ]

https://programmers.co.kr/learn/courses/30/lessons/17687


[ 문제 설명 ]

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로 출력한다.


2. Example 📚

[ 입출력 예시 ]

ntmpresult
2421"0111"
161621"02468ACE11111111"
161622"13579BDF01234567"

3. Solution 🔑

TRY 1.

  1. while문으로 튜브가 말한 값이 t값과 같아질 때 가지 돌린다.몇 진수를 표현하는 n을 받고,
    switch(n)문을 통해
    2진수는 Integer.toBinaryString(num).split("");으로 진수를 배열(BOH)로 저장
    16진수는 Integer.toHexString(num).split("");으로 진수를 배열(BOH)로 저장

  2. 저장된 진수값을 for 하나씩 확인하며 몇 번째 턴인지 나타내는 변수(turn)이 p와 같다면
    만들어 놓은 StringBuilder()에 해당 값을 append()시킨다.
    turn값이 p와 같지 않다면 turn값을 증가(++)시키면서 돌고, 인원수(m)을 넘어서면 다시 1로 초기화해준다.

  3. 수의 진수를 확인했으면 다음 수(num)을 증가(++)시켜 그 다음 수(num)의 진수를 다시 저장하고 확인.

  4. 내가 원하는 길이의 리스트의 길이가 되면 게임이 끝나게 할 boolean변수 값을 바꿔주고 break; 후 while문에서 boolean 값이 특정 값이 되면 while문 또한 빠져나오도록 한다.

  5. 최종적으로 나온 StringBuilder()의 값을 answer에 toString()을 이용하여 String클래스로 바꾸고 toUpperCase()를 이용하여 알파벳은 대문자로 바꾸어 반환해준다.

TRY 2.

오류적인 부분을 알 수 없어서 다시 코드를 짜기로 했다.
간편하게 한번에 모든 n진수로 표현된 값을 StringBuilder()에 담아 p번째 턴에 해당하는 값만 다른 StringBuilder()에 담아서 반환해주는 방법으로 접근해보았다.


1. 0부터 증가할 수(num)의 진수를 담으며서 조금이라도 시간을 줄이고자 진수를 담을 StringBuilder()에는 내가 말해야하는 개수(t)와 게임에 참가하는 멤버 수(m)을 곱한 값이 넘어가면 그만 담게하였다.
그 이유는 내가 t개 말했으면 내 이전 순서의 사람들은 나와 같은 t번을 말했을 것이고,
다음 사람들은 t-1번 말했을 것이다.
이를 이용해서 좀 더 줄여보고자 (t*m)번에서 멤버 수 만큼 한 번 빼주고, 내 순서인 p번까지 나올 수 있도록하였다.
(다 같이 (t-1)번 말했을 것이며, 나와 내 이전 사람들이 말한 개수는 p번일 것이므로)


2. 진수를 담은 StringBuilder값을 내가 말해야하는 t번 확인하여 (i*m + p-1)번 째 값들을 새로운 StringBuilder에 담고 최종값을 toString()으로 String클래스로 만들고 toUpperCase()를 이용하여 담긴 문자는 대문자로 바꾸어 answer에 담아 answer값을 반환한다.


TRY 3.

아래에 말 할 문자를 확인하는거는 간결하게 표현한거 같은데 "시간초과" 오류가 발생하여
진수를 담는 식에 문제가 있다고 생각하였다.
프로그래머스 1단계를 풀 때 Integer.parseInt(진수값, n진수)"로 표현하여 진수값을 10진수로 바꾸어 줬던 것이 생각났는데 반대로 하려면 Integer.toString(10진수, n진수)를 이용하면 10진수 값을 n진수로 표현 가능하다는 부분을 알았다.

  • (Integer.parseInt(10진수, n진수))로는 n진수로 표현 불가능

  1. 위에 TRY 2에서 언급했듯, 10진수 값(num)을 StringBuilder의 길이가(t*m - m+p)보다 작으면 10진수 값(num)을 0부터 증가(++)시키면서 Integer.toString(10진수, n진수)를 이용하여 담아준다.

  2. TRY 2와 동일.

4. Code 💻

TRY 1. (런타임 에러)

import java.util.Arrays;

class Solution {
	
    public String solution(int n, int t, int m, int p) {
    	String answer = "";
    	StringBuilder sb = new StringBuilder();
        boolean flag = true;
        //진법 n
        //미리 구할 숫자의 갯수 t
        //게임에 참가하는 인원 m
        //튜브의 순서 p
        int num = 0;
        
        int turn = 1;
        
    	while(true) {
    		String[] BOH = null;
    		switch(n) {
    		case 2 :
    			BOH = Integer.toBinaryString(num).split("");
    			break;
    		case 16 :
    			BOH = Integer.toHexString(num).split("");
    			break;
    		}
    		
    		for(int i=0; i<BOH.length; i++) {
    			if(turn == p) {
    				sb.append(BOH[i]);
    				if(sb.length()==t) {
					flag = false;
					break;
				}
    				turn++;
    				if(turn > m) {
    					turn = 1;
    				}
    			}
    			else {
    				turn++;
    				if(turn > m) {
    					turn = 1;
    				}
    			}
		}
		num++;

		if(flag == false) {
				break;
		}
    		
	}
	return answer = sb.toString().toUpperCase();
    }
}

TRY 2. (시간 초과)

class Solution {
	
    public String solution(int n, int t, int m, int p) {
    	String answer = "";
    	StringBuilder sb = new StringBuilder();
    	StringBuilder Antilo = new StringBuilder();
        int num = 0;
        
    	while(Antilo.length() < t * m - m + p) {
    		switch(n) {
    		case 2 :
    			Antilo.append(Integer.toBinaryString(num));
    			break;
    		case 8 :
    			Antilo.append(Integer.toOctalString(num));
    			break;
    		case 16 :
    			Antilo.append(Integer.toHexString(num));
    			break;
    		}
    		num++;
    	}
    	for(int i=0; i<t; i++) {
    		sb.append(Antilo.charAt(i*m+p-1));
    	}
    	answer = sb.toString().toUpperCase();
    	return answer;
    }
}

TRY 3.

class Solution {
	
	public String solution(int n, int t, int m, int p) {
		String answer = "";
		StringBuilder sb = new StringBuilder();
		StringBuilder Antilo = new StringBuilder();
		int num = 0;
		while(Antilo.length() < t * m - m + p) {
			Antilo.append(Integer.toString(num, n));
			num++;
		}
		for(int i=0; i<t; i++) {
			sb.append(Antilo.charAt(i*m+p-1));
		}
	answer = sb.toString().toUpperCase();
	return answer;
	}
}

5. Growth 🍄

[ n진수를 10진수로 변경할 때 ]
- Integer.parseInt(n진수 값, n);

[ 10진수를 n진수로 변경할 때 ]
- Integer.toString(10진수, n);
profile
다른 사람이 만든 것을 소비하는 활동보다, 내가 생산적인 활동을 하는 시간이 더 많도록 생활화 하자.

0개의 댓글