<문제>
https://www.acmicpc.net/problem/2577
<처음 시도한 잘못된 풀이>
#include<stdio.h>
int main(void)
{
int arr[3];
for (int i = 0; i < 3; i++)
scanf("%d",&arr[i]);
char sum[10] = { arr[0] * arr[1] * arr[2] };
for (int i = 0; i < 10; i++)
{
printf("%d\n",sum[i]);
}
return 0;
}
처음 문제를 구상할때, 숫자의 갯수를 어떻게 구할지에 대해서는 생각이 났지만, 그것을 구하기위한 중간과정이 잘 생각이 나지 않았다. 문자열의 배열요소들을 통해 0부터 9까지의 반복을 통해 각 숫자원소가 몇번 쓰였는지를 구하려 하였었지만 풀지 못하였다. 그래서 이 문제에대한 여러 풀이를 보았고, 이해를 통해 아래 코드를 작성해보았다.
<정답 코드>
#include<stdio.h>
int main(void)
{
int arr[3];
int sum = 1;
int num[10] = { 0, };
int res;
for (int i = 0; i < 3; i++) {
scanf("%d", &arr[i]);
sum *= arr[i];
}
for (int j = 0; sum > 0; j++) {
res = sum % 10;
num[res] += 1;
sum /= 10;
}
for (int k = 0; k < 10; k++) {
printf("%d\n", num[k]);
}
return 0;
}
int num[10] = { 0, }; 을 통해 배열의 모든 요소값들을 0으로 초기화 해주었다. int num[10]; 처럼 0으로 초기화 해주지 않고 선언만 해준뒤 위 코드를 실행기키면 어떻게 될까? 초기화를 시켜주지 않고 연산을 진행하였기때문에 의미없는 쓰레기값이 나오게 된다. 그러므로 꼭 초기화를 시켜주고 값을 출력해야만 한다. int num[10] = { 0 }; 과 같은 코드를 작성해주어도 0 값으로 자동 초기화가 된다.
sum *= arr[i]; 의 코드는 *=의 복합대입 연산자가 사용이 되었다. sum = arr[ 0 ]* arr[ 1 ]*arr[ 2 ]의 sum값과 같다.
for (int j = 0; sum > 0 ; j++): for문의 조건식이 들어가는 자리에 sum>0의 조건을 넣어주었고, sum = 0일때 반복문이 종료가 된다. for문의 선언식 과 증감식이 필요한 이유는 반복문을 돌려주기 위함이라고 생각하면 된다.
res = sum % 10; sum(세수의 곱)을 10으로 나눈 나머지 값을 res에 저장해준다. 10으로 나누어줌으로써 sum값의 일의 자리의 숫자가 나머지로 나오게 된다. 위 반복문을 돌리면 하나의 숫자도 빠짐없이 나머지로 나오게 됨을 볼 수 있다.
num[res] += 1; res라는 수가 num 배열의 인덱스 넘버가 되고, 그 인덱스 넘버의 배열은 그 해당 숫자의 개수를 말해주는 배열이다. += 1 의 연산이 있기에 가능하다.
sum /= 10; sum의 나머지를 구했고, 그때 몫에 남아있는 수가 sum의 일의 자리를 제외한 수 이다. 계속 같은 sum을 나누면 모든 숫자의 개수를 구할 수도 없고 반복문도 끝낼 수 없기때문에, 일의 자리를 제외한 수를 그 다음 sum으로 정해줘 생각한대로 구현이 가능하게 해주는 역할을 해준다 볼 수 있다.
이해를 돕기 위해 아래와 같이 표를 통해 예를 작성해 보았습니다.
ex ) sum = 1577 | sum%10 = 7, res = 7 | num[res] += 1; 7의 개수는 한개 |
sum/10 = 157, sum = 157 | sum%10 = 7, res = 7 | num[res] += 1; num[7] = 2 |
sum/10 = 15 ,sum = 15 | sum%10 = 5, res = 5 | num[5] += 1 |
sum/10 = 1, sum = 1 | sum%10 = 1, res=1 | num[1] += 1 |
sum/10 = 0 이면 | 조건식에 의해 반복문 종료. | X |