일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- Image Classification
- 소수판정
- SQL
- 프로그래머스연습문제
- 프로그래머스
- 논문리뷰
- 다이나믹프로그래밍
- 정수론
- 그리디
- 프로그래머스sql
- 백준
- 수학
- C
- 구현
- 자료구조
- 그리디알고리즘
- 정렬
- 사칙연산
- C++
- 프로그래머스코딩테스트
- 백준알고리즘
- 이분탐색
- 이진탐색
- 큐
- 브루트포스알고리즘
- 논문구현
- C언어
- 해시를사용한집합과맵
- 문자열
- MySQL
- Today
- Total
초보 개발자의 이야기, 릿허브
[C] 백준 1427번 소트인사이드 본문
1. 문제이해
https://www.acmicpc.net/problem/1427
1427번: 소트인사이드
첫째 줄에 정렬하고자하는 수 N이 주어진다. N은 1,000,000,000보다 작거나 같은 자연수이다.
www.acmicpc.net
정수를 입력받아, 각 자릿수를 내림차순으로 정렬하는 알고리즘을 구현하는 것이 목표이다.
2. 문제풀이
위 알고리즘을 구현하기 위해 두 가지 방법이 떠올라, 두 방법 모두 구현해보기로 했다.
첫번째 방법은, 정수를 입력받고 단순히 각 자릿수를 내림차순으로 정리하면 되는 거니까,
1. 9부터 0까지 내려오면서 일치하는 숫자가 있으면 그대로 출력하는 방식.
두번째 방법은, 정직하게 그대로 2. 값을 비교하여 정렬, 출력하는 방식이다.
첫번째 방식은 재학 중에 정렬을 구현하면서 본 방법인데, (어디서 봤는지 기억이 안난다..)
딱히 정해진 정렬방법이 있지 않을 때, 정말 유용한 것 같다.
3.소스코드
1-1. 첫번째 방법 (실패)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h> // atoi 함수 사용
int main() {
char arr[10]; // 입력받을 문자열 저장
int i, j;
char tmp;
scanf("%s", arr);
// 정렬 구현
for (i = 9; i >= 0; i--) {
for (j = 0; j < strlen(arr); j++) {
if (arr[j] == i) { // atoi 사용시 에러
printf("%c", arr[j]);
}
}
}
return 0;
}
위와 같이 코드를 작성해보니, 동작은 하지만 제대로 출력이 되지 않는 문제가 발생했다.
for문 사이사이에 확인용으로 print문을 넣어보았을 때,
제대로 동작이 되는 걸로 보아 if문에서 발생한 문제인것같아 몇시간을 끙끙댔던것같다..😫
문자열이라 제대로 비교가 안되는 걸까 하고 atoi함수도 사용해봤지만, 오히려 에러만 발생했다.
arr배열 전체가 아닌 arr[j]에 atoi함수를 사용한게 원인인것같다.
(찾아보니 atoi는 정확히는 char가 아닌 const char*, char[n]을 int로 변환해주는 것이고,
위와 같이 배열의 요소에 atoi를 적용하게 되면
const char*가 아닌 char를 가리키게 되므로 사용할 수 없다고 한다. 오늘도 하나 배웠다.😮)
atoi대신 강제적 변형을 사용해 (int)(arr[j])를 출력해보고 무엇이 문제인지 깨닫게 되었는데,
문제는 역시나 '문자'형태라는 점에 있었다.
if문 안에서 arr[j]와 i의 값이 같은지를 비교하는데, 만약 arr[j]값이 문자 '1'이라면,
이는 글자 '1'에 대한 아스키코드값으로 49가 된다는 점이 문제였다.
아스키코드 표를 보면, 문자 '1'(DC1)이 정수 49를 나타내고 있음을 볼 수 있다.
이후 숫자가 1씩 늘어나는데, 이 점을 이용해 코드를 살짝 수정해주었다.
1-2. 첫번째 방법 (성공)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main() {
char arr[10]; // 입력받을 문자열 저장
int i, j;
scanf("%s", arr);
// 정렬 구현
for (i = 9; i >= 0; i--) {
for (j = 0; j < strlen(arr); j++) {
if (arr[j] == i+48) { // 아스키코드
printf("%c", arr[j]);
}
}
}
return 0;
}
위의 아스키코드 표를 이용해, arr[j] == i 부분을 살짝 수정해주었다.
아스키코드 표의 반환값은 실제 정수보다 48이 더 크게 나왔으므로,
i부분에 48을 더해주었더니 오류가 해결되었다.
코드의 동작을 다시 설명해보자면, 정수를 문자열 형태로 입력받고 배열에 저장한 후,
for문을 통해 각각의 배열의 요소들을 9~0까지 내림차순으로 비교하여,
일치하는 것이 있으면 바로바로 출력하도록 구현했다.
2. 두 번째 방법 (성공)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <math.h>
int main() {
char arr[10]; // 입력받을 문자열 저장
int count = 0; // 문자열의 자리수
int i, k;
int j = 0;
int numarr[10]; // 각 자릿수의 숫자 저장
int tmp;
scanf("%s", arr);
// 입력받은 문자열을 정수로 변환, 저장
int num = atoi(arr); // 자리수 구하기위함
int num2 = atoi(arr); // 배열에 넣기위함
// 입력받은 문자열의 자리수 구하기
while (num > 0) {
count++;
num /= 10;
}
// 각 자리수의 숫자 배열에 넣기
for (i = count - 1; i >= 0; i--) {
numarr[j] = num2 / (pow(10,i));
num2 = num2 - ((pow(10, i))*(numarr[j]));
j++;
}
// 정렬
for (i = 0; i < count; i++) {
for (k = i; k < count; k++) {
if (numarr[i] < numarr[k]) {
tmp = numarr[i];
numarr[i] = numarr[k];
numarr[k] = tmp;
}
}
}
// 출력
for (i = 0; i < count; i++) {
printf("%d", numarr[i]);
}
return 0;
}
두번째 방법은 언뜻 보기에도 첫번째 방법보다 복잡한데,
사실 막상 구현해보니 이 방법이 시간이 더 적게 걸렸다.
(첫번째 방법은 어디서 틀렸는지 몰라서 한참 헤맸다..)
정수를 문자열 형태로 입력받고, num, num2라는 변수에 저장해
num은 몇자리 정수인지 구하는데 사용하고, num2는 다시 int형 배열에 넣어주기 위해 사용했다.
이후에는 int형 배열인 numarr에 저장된 값을 앞에서부터 비교하며 정렬하고, 출력해주었다.
오늘은 한 문제를 두가지 방법으로 풀어보았는데,
첫번째 방법같은 방식이 바로바로 머릿속에 떠오르면 좋겠지만,
두번째 방법도 나름대로 문제의 의미를 해석하고 구현하는 능력을 키우는데에는
도움이 되지 않을까... 하고 위로해본다..ㅎㅎ
아직까지는 초보인 단계라 이것저것 시행착오도 많이 겪고, 코드가 점점 길어지지만,
하나하나 노력하고 이뤄내가면 언젠가는 점차 좋아지지 않을까..?ㅎㅎ
그리고 C++이나 파이썬을 보면 내장함수를 이용해서 간단하게 구현할 수 있던데,
개인적으로 나는 내장함수는 되도록이면 나중에 사용하고 싶다..
기본적으로 어떻게 동작되는지 원리를 하나하나 구현해보고,
이해한 뒤에 내장함수를 써도 늦지 않다고 생각한다.(정말 개인적인 생각이다.)
코린이 탈출을 위한 그날까지, 화이팅😊
'코딩테스트 > 📗 백준 (BOJ)' 카테고리의 다른 글
[C] 백준 14467번 소가 길을 건너간 이유 1 (0) | 2021.07.24 |
---|---|
[C++] 백준 1436번 영화감독 숌 (0) | 2021.07.23 |
[C] 백준 14405번 피카츄 (0) | 2021.07.22 |
[C] 백준 2609번 최대공약수와 최소공배수 (0) | 2021.07.20 |
[C] 백준 1010번 다리놓기 (0) | 2021.07.19 |