1. 문제, 실행결과 예시
별찍기는 반복문을 활용하는 가장 대표적인 문제라고 생각한다. 사실 프로그래밍을 하다보면 수학적으로 규칙을 구하고, 일반화를 시켜 그 식을 적용하는 코드를 짜야할 때가 많은데, 아마 별찍기가 이런 부분을 연습하는데 있어서 정말 좋은 문제라고 생각한다(지극히 개인적인 생각입니다). 사실 스택을 풀다가 갑자기 별찍기를 푸는 이유는, 단계별로 풀기에서, 실습 1번부터 차례로 푸는 것을 목표로 잡았기 때문이다. 소프트웨어 마에스트로 코딩테스트를 대비하기 위함도 있고, 나름의 목표를 잡는 것도 좋다고 생각하기 때문이다. 다음은 이번에 푼 문제와 실행결과 예시이다.
출처: https://www.acmicpc.net/problem/2523
출처: https://www.acmicpc.net/problem/2446
2. 문제풀이 - 2523번
일단 줄수를 정하는 공식은 간단하다. 입력된 값이 N이라고 했을 때, N * 2 - 1 줄을 출력하면 된다. 이 문제 같은 경우는 중간까지 별의 수가 늘어나고, 그 뒤에는 별의 수가 계속 줄어드는 모습을 가지는 것이 특징이다. 그래서 나는 이 두 부분을 나누어서 출력하는 방법을 선택하였다. 아래의 그림은 출력공식을 보라색과, 파란색으로 나눈것이다.
*
**
***
**
*
위에, 실행 예시를 봤을 때, 보라색 부분의 출력은 매우 간단하다. 첫번째 줄에는 별을 하나 찍고, 두번째 줄에는 별을 두번 찍는 식으로 하면 된다. 파란색부분은 어떻게 해야할까? 나름 별찍기 유형의 문제를 풀면서 느낀점은 같은 for문 안에서 i의 값은 증가하지만, 찍어야하는 별의 값이 줄어들어야 한다면, 큰 수에서 i를 빼주는 방식으로 생각하면 답이 나온다는 것이다. 아마 한 번에 알아듣기에는 쉽지 않을 것이다. 사실 이 부분은 그냥 문제를 많이 풀어보는 방법밖에 없다.
본론으로 넘어가서, 다시 파란색 부분의 출력 형식을 설명하자면, 들어온 값이 num이고, 줄의 순서가 i일때, num - ( i - num)이라는 공식으로 별의 갯수를 구할 수 있다. 다음은 내가 작성한 코드이다.
#include <stdio.h>
int main(void) {
int input;
scanf("%d", &input);
int down = input - (input / 2);
int up = input / 2;
if (input != 1)
input = input * 2;
for (int i = 0; i < input; i++) {
if (i % 2) {
for (int j = 0; j < up; j++)
printf(" *");
}
else {
for (int j = 0; j < down; j++)
printf("* ");
}
printf("\n");
}
return 0;
}
2. 문제풀이 - 2446번
별찍기에서 가장 중요한 점은 위에서도 말했지만, 규칙을 찾고, 일반화하여, 그 공식을 사용하여 프로그램을 작성하는 것이다. 나는 이런 문제가 나오면 다음과 같은 표를 만든다.
출력되는 별의 모양 | for문에서 i의 값 | 출력되어야 하는 공백의 수 | 출력되어야 하는 별의 수 |
********* | 0 | 0 | 9 |
******* | 1 | 1 | 7 |
***** | 2 | 2 | 5 |
*** | 3 | 3 | 3 |
* | 4 | 4 | 1 |
*** | 5 | 3 | 3 |
***** | 6 | 2 | 5 |
******* | 7 | 1 | 7 |
********* | 8 | 0 | 9 |
어차피, for문안에서 놀 것이고, 한 층마다 주어지는 i의 값을 가지고 위의 별의 갯수, 공백의 갯수를 구해야한다. 결국 별의 갯수, 공백의 갯수 그리고 i와의 관계를 파악하는 것이 중요하다. 앞서 풀었던 방법처럼 보라색과 파란색으로 나누어서 규칙을 찾고 그에 맞게 출력하였다. 들어오는 값은 input이고 size는 input * 2 - 1이라고 하겠다.
출력 되어야 하는 공백의 수는 보라색 부분에서는 i의 값과 같다. 그리고 별의 갯수는 size - (i * 2) 라는 공식으로 구할 수 있다. 다음은 중요의 파란색이다. 사실 파란색 부분을 구할 때, 나름 시간이 들었다. 결론은 이런 공식을 사용하면 구할 수 있게 된다. input - (i - input + 2) 그럼 마지막으로 파란색의 별 부분이다. 직관적으로 풀어나갔을 때는 ((i + 1) * 2 - 1) - (input * 2) + 2 이런 식이 나왔고, 그대로 사용하였다. 다음은 나의 코드이다.
#include <stdio.h>
int main(void) {
int input;
scanf("%d", &input);
int size = input * 2 - 1;
for (int i = 0; i < size; i++) {
if (i < input) {
for (int j = 0; j < i; j++)
printf(" ");
for (int j = 0; j < size - (i * 2); j++)
printf("*");
}
else {
for (int j = 0; j < input - (i - input + 2); j++)
printf(" ");
for (int j = 0; j < ((i + 1) * 2 - 1) - (input * 2) + 2; j++)
printf("*");
}
printf("\n");
}
return 0;
}
3. 결어
최근 업로드가 뜸하긴 했다. 시험기간이서 그런거지만 이것도 핑계라면 핑계라고 생각할 수 있을 것 같다. 사실 시험문제를 업로드하고, 풀이를 올리고 싶었지만, 시간이 될지 모르겠다...... 지금의 목표는 소프트웨어 마에스트로 합격이다. 꼭 이루고 싶다.
'programming > 알고리즘 풀이' 카테고리의 다른 글
[백준 알고리즘] 8958번 OX퀴즈 (0) | 2020.06.19 |
---|---|
[백준 알고리즘] 10996번 - 별 찍기 21 (0) | 2020.06.19 |
[백준 알고리즘] 4949번 - 균형잡힌 세상 (런타임에러) (0) | 2020.05.23 |
[백준 알고리즘] 9012번 - 괄호 검사 코드 (0) | 2020.05.13 |
[백준 알고리즘] 10773번 (0) | 2020.05.13 |