
어느 영화감독이 시리즈를 제작하는데, 흔하게 1,2편으로 표기하는 것이 싫다고 666이 들어간 자연수 순서대로 시리즈를 제작한다는 스토리이다.
초등학교 저학년 때 어디선가 보았던 '책상은 책상이다' 라는 단편이 기억난다. 주인공은 삶이 너무 지루하다며, 침대를 의자라고 부르고 의자를 시계라고 부르는 힙스터가 되버린다. 이런 기행을 계속하던 주인공이 원래 사물의 이름을 까먹게 되고 타인과 대화가 불가능한 수준에 다다르는 내용까진 기억이 나는데, 후에 잘못을 뉘우치고 다시 광명을 찾는지는 모르겠다. 만약 아니라면 초등학교 저학년에게는 꽤나 비극적인 내용이 아닐 수 없겠다. 아무튼 이 영화감독이나 책상은 책상이다의 주인공이나, 창의성 점수는 높게 주지만 적당히 할 필요가 있다. 나 또한 반골기질이 강한 사람이지만, 기본적인 사회적 합의는 지키면서 사는 것이 좋겠다.
아무튼 이 영화감독이 정한 시리즈의 규칙은
1편 = 666
2편 = 1666
3편 = 2666
.
.
.
7편 = 6660
8편 = 6661
이런식이다
최적화 방법은 모르겠고, 카테고리도 '부르트 포스' 에 있기 때문에, 무식하고 미련한 방식으로 해결한다. 사실 일반적인 알고리즘 문제에서 이중 반복문 미만은 최적화에 크게 포커스를 둘 필요도 없을 것이다. 숫자를 666부터 1씩 더해가면서 '666'이 들어있으면 카운트를 해준다. 카운트와 입력받은 숫자가 일치하면 출력해주면 된다.
처음에는 int를 유지하면서 해결하려고 했다. 10으로 나눈 나머지가 숫자 6이면 수를 한번 세주고 아니면 0으로 초기화 해준다. 이렇게 하면 연속적으로 6이 있어야만 0으로 초기화 되지 않는데, 3까지 도달하면 그 수는 '666'이 포함됐다고 할 수 있겠다. 그렇게 제출해서 한번 틀리고 문자열로 치환해서 검사하면 훨씬 편할 것 같다는 생각을 했다.
1씩 더해주며 검사하는 것은 똑같지만, 문자열로 바꾸니 인덱스를 돌면 되니 훨씬 편했다. 인덱스를 돌다가 일단 '6'이 나오면, 이후에 두번 다 6이 나오는 지 체크했다.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int beast_num_checker(char *beast_num)
{
int i;
i = 0;
while (beast_num[i])
{
if (beast_num[i] && beast_num[i] == '6')
{
if (beast_num[i + 1] && beast_num[i+1] == '6')
{
if (beast_num[i+2] && beast_num[i+2] == '6')
return (1);
}
}
i++;
}
return (0);
}
char *itoa(int a)
{
int num;
int cnt;
char *itoa_num;
num = a;
cnt = 0;
while (num != 0)
{
num /= 10;
cnt++;
}
itoa_num = malloc(cnt + 1);
itoa_num[cnt] = '0';
cnt--;
while (cnt >= 0)
{
itoa_num[cnt] = (a % 10) + '0';
a /= 10;
cnt--;
}
return (itoa_num);
}
int main()
{
int a;
int num;
int cnt;
int beast_num;
beast_num = 666;
cnt = 0;
num = 0;
while (1)
{
a = getc(stdin);
if (a == 'n')
break;
num = num * 10 + (a - '0');
}
while (1)
{
if (beast_num_checker(itoa(beast_num)))
{
cnt++;
if (cnt == num)
break;
}
beast_num++;
}
printf("%d", beast_num);
}
구현은 위에 설명한 것이 다이고. 오히려 특이사항이 있다면, 최대한 로우레벨로 구현하기 위해 scanf를 사용하지 않은 것과 itoa 부분이다.
getc를 통해서 표준입력으로 부터 한글자씩 입력 받았다. getc함수는 문자의 아스키 코드를 int형으로 반환해주기 때문에, 1 은 49 2는 50으로 반환되는 식이다. 그래서 반환값에서 문자 '0' 즉 48을 빼줘야 진짜 int형으로 저장이 된다. 그리고 숫자를 입력 받을 때 마다 이전 숫자에 10을 곱한 후 더해주어서 10진수의 자릿수 연산을 해주었다. getc를 통해 읽어온 문자가 개행문자일 때 반복문 탈출 조건을 줬기 때문에, enter를 누르면 입력이 종료된다.
itoa 부분도 비슷한데, getc를 통해 받은 값을 0이 될때까지 10으로 나누어 보면서 자릿수를 체크하고 malloc을 통해 자릿수 +1 만큼 메모리를 할당해준다. 맨 마지막 인덱스에는 null문자를 넣어주고, 10의 나머지 연산을 통해 숫자를 문자열에 거꾸로 넣어준다.
num = 123 으로 치면 123을 10으로 나눈 나머지 3을 넣어주고, num에는 123 을 10으로 나눈 12로 초기화 해준다. 다시 12를 10으로 나눈 나머지 2를 넣어주고 앞의 과정을 반복해주면 된다. 나머지 연산을 활용하기 때문에 거꾸로 넣어줘야 한다.
문자열에 넣어줄 때는 아까 getc와는 반대로, 문자 '0' 만큼의 값을 더해줘서 문자열에 넣어줘야 숫자가 의미하는 문자로서 문자열에 넣어줄 수 있다.
'알고리즘-문제' 카테고리의 다른 글
구름톤 챌린지 3주 차 문제 13 학습 일기 (0) | 2024.02.18 |
---|---|
구름톤 챌린지 4주 차 문제 17 학습 일기 (0) | 2024.02.18 |
백준 1753 최단경로 (0) | 2024.02.18 |
백준 1074 Z C언어 (0) | 2024.02.18 |
백준 숫자카드 2 java (0) | 2024.02.18 |