단어 공부
백준 문제
[Bronze I] 단어 공부 - 1157
성능 요약
메모리: 1972 KB, 시간: 12 ms
분류
구현, 문자열
제출 일자
2023년 12월 25일 20:50:42
문제 설명
알파벳 대소문자로 된 단어가 주어지면, 이 단어에서 가장 많이 사용된 알파벳이 무엇인지 알아내는 프로그램을 작성하시오. 단, 대문자와 소문자를 구분하지 않는다.
입력
첫째 줄에 알파벳 대소문자로 이루어진 단어가 주어진다. 주어지는 단어의 길이는 1,000,000을 넘지 않는다.
출력
첫째 줄에 이 단어에서 가장 많이 사용된 알파벳을 대문자로 출력한다. 단, 가장 많이 사용된 알파벳이 여러 개 존재하는 경우에는 ?를 출력한다.
TIL
- 모든 예제에 대해 맞고, 알고리즘 구현 또한 틀리지 않은 것 같다면 다음 두 가지 extreme Case를 고려하자.
- 입력이 최소인 경우 ex) 0이 입력인 경우의 구현 부재 -> 예외 처리
- 입력이 최대인 경우 ex) 오버플로우 발생 -> 자료형을 체크
FeedBack
자료형에의 표현 범위를 주의하자.
특히 진짜 왜 안 되지… 라는 논리 에러에는 extreme-case에서의 자료형이 문제가 될 수 있다.
내 접근
char 자료형을 중간에 써서 오버플로우가 발생하여 계속 틀렸었다.
내 코드
내 것보다는 되게 세련되게 코드를 짠 분이 있길래 그분 거를 소개한다.
-
‘A’는 65, ‘a’는 ‘97’이다. 즉 이들은 32만큼 차이가 난다. 다시 말해 왼쪽에서 5번째 비트만 켜주면 된다.
이분은 이 지식을 활용하여 전처리문으로 비트 마스킹을 하여 구현하였다.
존나 섹시해 - 나는 가장 많이 나온 알파벳을 초기에 미리 설정해 두지 않으면 구현 불가능할 것이라 생각하여 지저분하게 코드로 작성하였는데, 이분은 대입 연산을 그냥 두 번 하여 해결하였다.
정말 깔끔하다. - 마무리 return 문 또한 삼항 연산자를 이용해 깔끔하다.
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
/**
* Capitals: 1 << 5 bit off.
* A: 0100 0001
* Z: 0101 1010
*
* Non-capitals: 1 << 5 bit on.
* a: 0110 0001
* z: 0111 1010
*/
#define ASCII_CHAR_UPPER(ch) (ch & ~(1 << 5))
char word[1000000];
char most_frequent_char(char *string);
int main(int argc, char *argv[]) {
fread(word, 1, 1000000, stdin);
printf("%c\n", most_frequent_char(word));
return 0;
}
char most_frequent_char(char *string) {
size_t counts[26] = {0,};
size_t string_len = strlen(string);
// Count.
for (size_t i = 0; i < string_len; ++i) {
counts[ASCII_CHAR_UPPER(string[i]) - 'A'] += 1;
}
size_t count_max = 0;
char most_frequent = '\0';
char duplicated = '\0';
// Get max.
// No duplications allowed.
for (size_t i = 0; i < 26; ++i) {
if (counts[i] == count_max) {
duplicated = most_frequent = i + 'A';
}
else if (counts[i] > count_max) {
count_max = counts[i];
most_frequent = i + 'A';
}
}
return (most_frequent == duplicated) ? '?' : most_frequent;
}
- 어떤 논리적인 오류가 있어 현재는 돌아가지 않는 코드이다. 얻어갈 인사이트만 얻어 가도록 하자.
Leave a comment