본문 바로가기
C

[C]백준 05.1차원배열(10818, 2562, 2577, 3052, 1546, 8958, 4344)

by 열지희공 2022. 1. 8.

백준 10818

내코드

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

int main() {
	int n;
	scanf("%d", &n);
	int* arr = malloc(sizeof(int) * n);
	for (int i = 0; i < n; i++) {
		scanf("%d", &arr[i]);
	}
	int min = arr[0];
	int max = arr[0];
	for (int i = 0; i < n; i++) {
		if (arr[i] < min) {
			min = arr[i];
		}
		if (arr[i] > max) {
			max = arr[i];
		}
	}
	printf("%d %d", min, max);
	return 0;
}

풀이과정

입력받은 n개의 값만큼 정수가 주어지기 때문에 동적할당을 이용하여 일차원 배열에 공간을 할당하였다. 그 후 min, max에 배열의 첫번째 값을 넣어둔 뒤 반복문을 돌려 만약 해당하는 배열의 값이 min보다 작다면 min에 그 배열의 값을 넣고, 해당하는 배열의 값이 max보다 크다면 max에 그 배열의 값을 넣어 min, max 값을 구하였다. 

일차원 배열의 크기를 동적으로 사용하는 방법: 

  • 자료형 *포인터이름 = malloc(sizeof(자료형) * 크기);

<출처: https://dojang.io/mod/page/view.php?id=317 >

 

백준 2562

내코드

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main() {
	int arr[9];
	for (int i = 0; i < 9; i++) {
		scanf("%d", &arr[i]);
	}
	int max = arr[0];
	int cnt = 0;
	for (int i = 0; i < 9; i++) {
		if (arr[i] > max) {
			max = arr[i];
			cnt = i;
		}
	}
	printf("%d\n", max);
	printf("%d", cnt+1);

	return 0;
}

이 문제는 처음에 틀렸었던 문제이다. 아래에 틀렸던 코드를 첨부하겠다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main() {
	int arr[9];
	for (int i = 0; i < 9; i++) {
		scanf("%d", &arr[i]);
	}
	int max = arr[0];
	int cnt = 0;
	for (int i = 0; i < 9; i++) {
		if (arr[i] > max) {
			max = arr[i];
			cnt = i + 1;
		}
	}
	printf("%d\n", max);
	printf("%d\n", cnt);

	return 0;
}

두 코드의 차이는 반복문을 돌리며 max를 찾고 그 위치를 표시하기 위해 cnt에 값을 부여하는 부분이다. 틀린코드에서는 반복문 안의 조건문 내부에서 cnt에 i+1의 값을 부여하여 나중에 cnt값만 출력해도 되도록 했다. 하지만 이부분에서 내가 생각하지 못했던 부분은 최대값이 배열의 첫번째에 위치할 때이다. 만약 최대값이 배열의 첫번째에 위치한다면 반복문을 돌릴때 어떤 i에서도 조건문을 만족하지 못하게 되고 나중에 cnt 값이 0으로 출력되게 된다. 그래서 이부분을 수정하기 위해서 조건문 안에서 cnt에 i+1이 아닌 i값을 부여하고, 나중에 cnt+1값을 출력하도록 했다.

밑에 첨부할 코드는 내가 틀린부분이 어디인지 모르겠어서 문제에 대해 구글링을 했을 때 찾은 방법이다. 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main() {
	int arr[9];
	int max = 0;
	int cnt = 0;
	for (int i = 0; i < 9; i++) {
		scanf("%d", &arr[i]);
		if (arr[i] > max) {
			max = arr[i];
			cnt = i + 1;
		}
	}
	
	printf("%d\n", max);
	printf("%d", cnt);

	return 0;
}

max와 cnt를 0으로 설정해 두는 것이다. 이렇게 하면 배열의 첫번째 값도 조건문 안으로 들어가 수행되기 때문에 제외된 상황없이 모든 상황에서 올바르게 작동된다. 또한 굳이 반복문을 두번 사용하지 않고 수를 입력받는 반복문에서 max를 찾는다면 더욱 간결한 코드로 작성이 가능하다. 출처의 게시물에서 위와 같은 해결책을 생각할 수 있었다.

<출처: https://gururuglasses.tistory.com/72 , https://rightbellboy.tistory.com/97 >

 

백준 2577

내코드

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main() {
	int a, b, c;
	int result;
	scanf("%d", &a);
	scanf("%d", &b);
	scanf("%d", &c);
	result = a * b * c;
	
	int num[10] = { 0, };
	int x;
	while (result != 0) {
		x = result % 10;
		result = result / 10;
		num[x]++;
	}
	for (int i = 0; i < 10; i++) {
		printf("%d\n", num[i]);
	}

	return 0;
}

내코드에 대해 설명하자면

먼저 num배열은 1부터 9까지의 숫자가 각각 몇번 쓰였는지 표시할 배열이다. 처음에 문제를 보고 a, b, c 곱의 길이를 구한 다음 그 길이만큼 반복문을 돌려야하나 고민했었고 더 간단하게 풀고 싶어서 정수의 자릿수를 구하는 법을 찾아봤다. 찾아보니 주어진 수가 0이 되지 않을 때까지 10으로 나눠가면서 그 수를 세는 방법이었다. 나도 이를 이용해 문제를 풀었다. 우선 a, b, c 곱의 결과를 10으로 나눈 나머지 값, 즉 1의 자리 수를 구했다. 고맙게도 이 문제에서는 0부터 9까지 몇번 쓰였는지를 구하는 문제였기에 각 배열에 들어있는 값이 해당 인덱스의 숫자가 몇번 쓰였는지 나타내는 것으로 생각하면 됐다. (예를 들어 num[1]에 들어있는 값은 1이 몇번쓰였는지, num[5]에 들어있는 값은 5가 몇번쓰였는지 나타내는 것이다.) 다시 풀이과정으로 돌아와 곱의 결과를 10으로 나눈 나머지 값, 즉 1의 자리 수를 num의 인덱스에 넣어 해당 인덱스의 값을 1증가시켰다. 그리고 곱의 결과를 10으로 나눠서 1의 자리 수를 버렸다. 이를 곱의 결과인 result가 0이 되지 않을 때까지 반복하여 모든 자리의 수를 확인하였고, 마지막으로 num의 모든 값을 출력했다.

처음에 위의 논리를 가지고 코드를 짰었는 데 틀렸다. 아래는 틀린 코드이다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main() {
	int a, b, c;
	int result;
	scanf("%d", &a);
	scanf("%d", &b);
	scanf("%d", &c);
	result = a * b * c;
	
	int num[10] = { 0, };
	int x;
	while (result != 0) {
		result = result / 10;
		x = result % 10;
		num[x]++;
	}
	for (int i = 0; i < 10; i++) {
		printf("%d\n", num[i]);
	}

	return 0;
}

틀린코드와 맞은코드의 차이는 while문 안 코드의 순서이다. 두 코드는 비슷해보이지만 틀린코드는 곱의 결과인 result를 10으로 나눈 뒤 그 10으로 나눈 result의 1의 자리를 확인하는 순서이므로 결과적으로 틀리게 됐다. 이 문제로 코드의 순서가 얼마나 중요한지를 다시한번 느낄 수 있었다. 

 

백준 3052

내코드

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main() {
	int input[10];
	for (int i = 0; i < 10; i++) {
		scanf("%d", &input[i]);
	}
	int rmd[10];
	for (int i = 0; i < 10; i++) {
		rmd[i] = 42;
	}
	int tmp;
	int flag = 0;
	for (int i = 0; i < 10; i++) {
		tmp = input[i] % 42;
		for (int j = 0; j < flag + 1; j++) {
			if (rmd[j] != tmp) {
				if (rmd[j] == 42) {
					rmd[j] = tmp;
					flag++;
					break;
				}
			}
			else
				break;

		}
	}
	printf("%d", flag);
	return 0;
}

풀이과정

rmd배열은 입력값을 42로 나눈 서로 다른 나머지를 저장할 배열이고 42로 초기화했다.(42에 별의미는 없고 42로 나눈 나머지 값으로 나올 수 없기에 42로 설정했다.) flag는 rmd 배열에 기존의 나머지와는 다른 새로운 나머지 값이 들어온다면 저장되어야 할 위치를 나타내는 변수이고 0으로 초기화 했다. 또 tmp 변수는 입력값을 42로 나눈 값을 임시로 저장할 변수이다. rmd 배열에 서로 다른 나머지만을 저장하기 위해서는 어떤 값(tmp)이 기존과는 다른 새로운 값인지 아닌지를 판단해야 한다. 그러기 위해서는 flag 전까지 check하여 같은 값이 있는지 없는지를 확인해야 한다. 그리고 그 tmp가 새로운 값일 시 flag에 저장되어야 하기에 반복문은 0부터 flag까지 총 flag+1만큼 반복했다. 반복문을 돌며 tmp값이 rmd 배열의 값과  같은지 아닌지를 판단한다. 만약 tmp값이 배열의 값과 같지 않으면서 그 배열의 값이 42라면 tmp는 기존의 나머지와는 다른 새로운 값이라는 의미이다. 그래서 그 위치(flag)에 tmp를 저장하고 flag값을 1증가시킨 후 break한다. 새로운 나머지들이 rmd 배열 인덱스의 0부터 flag-1 까지 채워져있으므로 새로운 값의 개수는 flag이다. 

 

문제를 푸는 시간도 오래걸렸고 풀고 나서 맞았음에도 코드가 너무 복잡한 게 아닌가라는 생각이 들어 다른 사람들의 코드를 찾아보니 훨씬 간결하고 논리도 간단했다. 왤케 복잡하게 생각했을까.. 

#include <stdio.h>

int main(void) {
    
    int input, result=0;
    int remain[10];
    
    for(int i=0; i<10; i++) {
        scanf("%d", &input);
        remain[i] = (input % 42);
    }
    
    for(int i=0; i<10; i++) {
        int count=0; // 초기화
        for(int j=i+1; j<10; j++) { // 서로 같은 수일 경우
            if(remain[i] == remain[j]) count++;
        }
        if (count == 0) result++; // 같은 수가 없을 경우 개수를 세준다
    }
    
   printf("%d", result);
}

remain[i]에 input을 42로 나눈 값을 저장하고 반복문을 이용하여 서로 같은 수가 있는지 체크하고 같은 수가 없을 경우 result 값을 증가시키는 방법이다. 또 이미 같은지 체크한 부분은 제외하고 체크하기 위해 이중 반복문중 안쪽 반복문에서 j를 i+1부터 9까지 증가시킨것 같다. 

<출처: https://develop247.tistory.com/14 >

 

백준 1546

내코드

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

int main() {
	int n;
	scanf("%d", &n);
	float* score = malloc(sizeof(float) * n);
	for (int i = 0; i < n; i++) {
		scanf("%f", &score[i]);
	}
	float max = 0;
	for (int i = 0; i < n; i++) {
		if (score[i] > max) {
			max = score[i];
		}
	}
	float final = 0.0;
	for (int i = 0; i < n; i++) {
		score[i] = (score[i] / max) * 100;
		final += score[i];
	}
	printf("%.2f", final / n);
	
	return 0;
}

 

백준 8958

내코드

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

int main() {

	char a, b;
	b = 'O';
	int ret;
	int n;
	scanf("%d\n", &n);
	int* arr = malloc(sizeof(int) * n);
	for (int i = 0; i < n; i++) {
		int score = 0;
		int final = 0;
		while (1) {
			scanf("%c", &a);
			ret = a - b;
			if (ret == -69) {
				break;
			}
			if (ret == 0) {
				score++;
			}
			else
				score = 0;
			final += score;
		}
		arr[i] = final;
	}
	for (int i = 0; i < n; i++) {
		printf("%d\n", arr[i]);
	}
	return 0;
}

이 문제는 각 테스트 케이스의 길이가 가변적이라 언제까지 입력받아야 되는지 설정하는게 어려웠다. 그래서 그냥 while(1)로 무한루프를 돌렸다. 입력들이 \n개행문자로 구분되기 때문에 아스키코드에서 \n개행문자와 O를 찾았다. 둘의 차이는 -69여서 만약 scanf로 입력받은 문자와 b('O')의 차이인 ret이 -69라면 break하도록 조건문을 설정했다. 만약 ret이 0이라면 입력된 값이 O라는 의미이기에 score를 1증가했고 0이 아니라면 X라는 의미이기에 score를 0으로 설정했다. 또 final += score 코드를 통해 해당 문제의 점수를 더하였다.

이 문제도 문제의 의도와 달리 푼 것 같아서 다른 사람의 풀이를 찾아봤더니 테스트케이스를 string에 저장하고 strlen을 이용해 그 만큼 반복하여 비교하는 방법이 있었다.

<출처: https://develop247.tistory.com/16 >

아래는 찾아본 방법으로 다시 작성한 코드이다. 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main() {
	int n;
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		char s[80];
		scanf("%s", s);
		int score = 0;
		int final = 0;
		for (int i = 0; i < strlen(s); i++) {
			if (s[i] == 'O') {
				score++;
			}
			else
				score = 0;
			final += score;
		}
		printf("%d\n", final);
	}
	return 0;
}

 

 

백준 4344

내코드

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

int main() {
	int c;
	scanf("%d\n", &c);
	for (int i = 0; i < c; i++) {
		int n;
		scanf("%d", &n);
		int* arr = malloc(sizeof(int) * n);
		float avg = 0;
		for (int i = 0; i < n; i++) {
			scanf("%d", &arr[i]);
			avg += arr[i];
		}
		avg = avg / n;
		int cnt = 0;
		for (int i = 0; i < n; i++) {
			if (arr[i] > avg) {
				cnt++;
			}
		}
		float ratio = (float)cnt / n * 100;
		printf("%.3f%%\n", ratio);
	}

	return 0;
}

%를 출력하려면 %%이렇게 두번 써야한다.