개발/자료구조, 알고리즘

[코딩 테스트] 소프티어(Softeer) 연습 문제 - 전광판

growing-dev 2023. 2. 16. 21:46
반응형

코딩 테스트를 위한 소프티어(Softeer) 연습 문제 중 전광판 문제를 풀어보고 리뷰해 본다.

 

연습 문제 - 전광판

  • 난이도 : level 2
  • 정답률 : 74%

 

https://softeer.ai/practice/info.do?idx=1&eid=624 

 

Softeer

연습문제를 담을 Set을 선택해주세요. 취소 확인

softeer.ai

 

문제 해설

하나의 숫자를 표현하기 위해 디지털 전구로 표현된 전광판이 출력되는 문제이다. 디지털 숫자를 표현하는 방식으로 아래와 같이 0부터 9까지 표시가 된다. 이런 패턴을 이해하고 두 개의 숫자 A와 B를 입력받고 A에서 B로 변경될 때 변경되는 전구의 개수를 판단하는 문제이다. 최대 5자리 숫자의 A와 B가 주어지며 A와 B의 숫자는 자릿수가 다를 수 있다.

디지털 숫자 표현

문제에서 고려해야 하는 포인트는 아래와 같다.

  • 디지털 숫자를 어떤 식으로 구분하고 표현할 것인가
  • 자리수가 다를 때는 어떻게 처리할 것인가
  • 아무것도 켜지지 않은 것과 0을 어떻게 구분할 것인가
  • 두 개 숫자의 다른 부분을 어떻게 비교할 것인가
  • 다른 문제와 다르게 입력을 여러 개 받는다.

 

내가 생각한 방식은 아래와 같다

  • 0부터 9까지의 숫자를 9가지의 패턴으로 미리 저장해 놓는다. 나의 경우는 맨 위부터 배열의 0번째 index라고 생각하고 오른쪽 시계방향으로 한 바퀴 돌면서 bit로 표현하도록 생각했고 맨 마지막이 중간에 위치한 가로의 표현이다. 즉 0은 1111110, 1은 0110000  이런 식으로 7개의 전구를 하나의 bit로 표현했다. 이는 사람마다 어떻게 정의하느냐에 따라 결정되는 것이다.
  • for문으로 자리수를자릿수를 판단한다. for문에서 loop를 돌면서 10으로 나눈 나머지를 현재 자리의 숫자, 그리고 10을 나눈 몫을 그다음 loop의 인자로 넘겨주게 되면서 자릿수를 저장한다. 자릿수가 존재할 때는 그대로 저장하고 자릿수가 끝나면 바로 break 해서 09881과 같은 경우 처음 만의 자릿수에 해당하는 숫자는 0으로 초기화된 채로 남도록 구현했다.
  • 0과 아무것도 켜지지 않은 것은 얼핏 생각하면 같은 것으로 취급될 수 있다. 나도 여기서 약간 헷갈린 포인트이기도 하다. 즉 0으로 켜진 디지털 숫자 0과 아무것도 켜지지 않은 숫자는 다르다. 아무것도 켜지지 않으면 0000000이 될 것이고 숫자 0은 1111110이 될 것이다. 배열을 처리하면서 조심해야 할 포인트였다.
  • 두 숫자의 다른 부분은 각 숫자를 5개의 배열로 한 자리 숫자로 표현한 뒤에 각 자리의 숫자를 XOR 비교한 다음 각 자리 숫자가 1이라면 다르다고 판단해서 카운트하였다.
  • 입력을 여러번 받는 경우에 대해서 처리를 잘해야 한다. 특히 Global 변수를 사용하게 되면 매 테스트 케이스마다 초기화를 해줘야 해서 조심해야 한다. 즉 로컬 변수를 사용하는 것이 좋다.

입/출력은 아래와 같고 이런 조심해야 할 포인트들을 고려해서 구현한 코드는 아래와 같다.

 

입력

2
1 2
9881 10724

 

출력

5
11

 

위 예제에서 1과 2를 비교했을 때는 0110000 과 1101101 이여서 두 개의 bit의 차이를 비교하면 5개 여서 최초 결과는 5가 된다. 같은 방식으로 9881과 10724를 비교하는데, 그냥 9881이 아니고 X9881이라는 것에 조심해야 한다. 즉 9881의 첫자리 숫자는 9가 아니가 아무것도 켜지지 않은 전구를 타나 내는 X 즉 0000000이라는 것이다.

 

코드

#include<iostream>

using namespace std;
                 //no  1   2    3   4   5   6   7     8    9    0
int num_arr[11] = {0, 48, 109, 121, 51, 91, 95, 114, 127, 123, 126};

int calculate(int A, int B) {
	//divide 5 arr
	int a[5]{};
	int b[5]{};
	for(int i = 4; i >= 0; i--) {
		if (A % 10 == 0) a[i] = 10;
		else a[i] = A % 10;
		A /= 10;
		if (A == 0) break;
	}

	for (int i = 4; i >= 0; i--) {
		if (B % 10 == 0) b[i] = 10;
		else b[i] = B % 10;
		B /= 10;
		if (B == 0) break;
	}

	//compare using ^ to count a,b which is index of num_arr
	int comp[5]{};
	for (int i = 0; i < 5; i++) {
		comp[i] = num_arr[a[i]] ^ num_arr[b[i]];
	}

	//count comp and sum
	int sum = 0;
	for (int j = 0; j < 5; j++) {
		for (int i = 0; i < 7; i++) {
			if ((comp[j] & 1) == 1) sum++;
			comp[j] = comp[j] >>1;
		}
	}
	return sum;
}

int main(int argc, char** argv)
{
	int N;
	int A, B;
	cin >> N;
	for (int i = 0; i < N; i++) {
		cin >> A >> B;
		int result = calculate(A,B);
		cout << result << endl;
	}

	return 0;
}

 

결론

있을 법한 문제이다. 디지털 숫자를 표현하고 bit 연산과 간단한 함정이 몇가지 숨어 있었다. level2 답게 특별히 시간 복잡도에 대한 고민을 하지 않아서 크게 어렵진 않았지만 bit 연산과 예외처리하는데 다소 시간이 걸렸다. 나름 재미있는 문제였던 것 같다.

반응형