0. 들어가기에 앞서...
별 찍기. 프로그래밍 공부만 하면 단골로 등장하는 문제인 것 같다.
별 찍기만 보면 대학교 때 들었던 교양 프로그래밍 수업 생각이 난다.
교양 필수로 들었던 프로그래밍 수업의 기말 시험으로,
파이썬으로 별 스페이스 별 스페이스가 여러 줄에 교차하게 찍는 문제를 풀지 못했던 게 떠오른다.
(왜 안 돼지 고민하고선 그 문제 안 풀고 전체 문제의 반절만 겨우 풀었는데, 반만 풀어도 A+이었다)
이후에 독학으로 C언어를 공부할 때 피라미드를 찍어보기도 했고, 삼각형 모양으로 별을 찍는 것도 생각보다 쉽게 할 수 있었다.
지금 서술하는 심화과제 또한 받은 당일 풀어내기는 했지만, 해당 문제를 해결하기 위한 과정이 인상적이어서 기록해보고자 한다.
심화 과제 1. 입력을 통한 다이아몬드 출력 기능 구현
출력할 다이아몬드 형태를 사용자로부터 입력 받은 후, 만약 짝수일경우 홀수를 다시 입력하라고 유저에게 무한 반복으로 요구한다.
홀수가 입력되었을 경우, 다이아몬드 중간 부분이 유저의 입력과 같은 다이아몬드를 출력하는 프로그램 제작.
실행 예시 :
위와 같은 조건으로 다이아몬드 출력 기능을 만들고자 한다.
사실 이전에 피라미드 쌓기나 삼각형 모양으로 별 찍기 등은 독학으로 해 본 적 있었지만 다이아몬드는 쉽게 감이 잡히지 않았다.
하지만 막막하게 문제를 들여다보기만 하지 말고,
우선 과제에 제시된 조건과 구현해야 할 기능을 살펴 보았다.
필요한 기능
1. 출력할 다이아몬드 형태를 사용자로부터 입력 받은 후, 만약 짝수일 경우 "홀수를 다시 입력하라"고 유저에게 무한 반복으로 요구한다.
2. 홀수가 입력되었을 경우, 다이아몬드 중간 부분이 유저의 입력과 같은 다이아몬드를 출력하는 프로그램 제작.
우선은 제시된 조건과 그림으로 표시된 예시까지 포함하여 필요한 기능을 나눠 보았다.
- 입력 기능
1.1) 맨 위에 "출력할 다이아몬드 개수를 홀수로 입력 :"
1.2) 짝수일 경우 "홀수를 입력하세요"라는 텍스트를 출력 (무한 반복)
ㄴ 숫자가 아닌 문자열 입력도 이 방법에 포함
1.3) 1일 경우 "1이 아닌 값을 입력하세요" 라는 텍스트를 출력 (무한 반복)
1.4) 1이 아닌 홀수가 입력되었을 때 2의 단계로 넘어간다.- 출력 기능
출력 기능은 당장 감이 잡히지 않으니 우선 입력 기능부터 구현해 보자.
입력 기능을 구현하기 위해 필요한 기능은 다음과 같다.
- 무한 반복
- 문자열 입력 시 숫자로 변환
- 짝수와 홀수 구분, 1 구분
이를 지금까지 배운 정보로 아래와 같이 작성하기로 했다.
- While(true) 사용
- ReadLine()으로 입력 받고 TryParse로 int형 변환
- (입력값) != 1 이고, (입력값) % 2 == 1일 때 다이아몬드 만들기가 실행됨
이를 통해 아래와 같이 코드를 작성하였다.
static void Main(string[] args)
{
Console.WriteLine("출력할 다이아몬드를 홀수로 입력:"); // 최초 1회 출력
while (true)
{
int inputNum;
int.TryParse(Console.ReadLine(), out inputNum); // 사용자 입력
if (inputNum == 1) // 1일 경우를 제일 먼저 확인 후, 홀수 여부 확인
{
Console.WriteLine("1이 아닌 값을 입력하시오.");
}
else if(inputNum % 2 == 1) // 홀수이면 다이아몬드 출력
{
Console.WriteLine("다이아몬드 출력");
break; // 다이아몬드 출력시 프로그램 종료
}
else // 그 외의 모든 상황은 재입력 요구
{
Console.WriteLine("홀수를 입력하시오.");
}
}
}
이렇게 짜고 일단 실행시켜 보자.
원하는 대로 기능이 잘 구현되는 걸 확인했다. 여기까지는 제법 빠르게 구현할 수 있었다.
여기서부턴 메모장을 꺼내 기록해보며, 생각을 정리해보기 시작했다.
다이아몬드 - 7을 입력했을 때
공백을 -로 표시
---* 공백 3 별 1 공백 : 입력값/2 별 : 1부터 입력값까지 홀수 번 입력
--*** 공백 2 별 3 공백 : 입력값/2 -1 별 : 1부터 입력값까지 홀수 번 입력(3)
-***** 공백 1 별 5 공백 : 입력값/2 -1 -1 별 : 1부터 입력값까지 홀수 번 입력(5)
******* 공백 0 별 7 공백 : 입력값/2 -1 -1 -1 별 : 1부터 입력값까지 홀수 번 입력(7)
-***** 공백 1 별 5 다시 역순?
--*** 공백 2 별 3
---* 공백 3 별 1
아래 부분을 구현할 방법이 떠오르진 않았지만,
우선 네 번째 줄까지의 규칙을 정리하면 다음과 같다.
- 별 찍기와 공백 찍기는 4번 반복해야 한다, 정확히는 (입력값)/2 + 1 번 만큼 반복한다.
- 안쪽의 별찍기와 공백찍기는 공백 -> 별찍기 순서로 진행한다.
- 공백은 (입력값)/2 - (몫) 부터 시작하여 0까지 반복한다.
- 별은 1, 3, 5, (입력값) 까지 진행한다.
이렇게 정리하고 코드를 짜 보았다. 이 정도로 정리했건만 이것마저도 상당한 시행 착오를 겪었다.
// 다이아몬드 윗 부분을 만들 코드.
for (int i = 1; i <= inputNum / 2 + 1; i++)
{
for (int j = inputNum / 2 - (i - 1); j >= 1; j--)
{
Console.Write(" ");
}
for (int k = 1; k <= 2 * (i - 1) + 1; k++)
{
Console.Write("*");
}
Console.WriteLine();
}
특히나 공백을 찍는 게 어려웠는데, 처음엔 tempNum이라는 변수를 만들어서 제작하려 했지만 이것이 불필요한 것임을 제작 과정 중에 깨달았다.
반복문 속에 넣는 초기식인 int i 또한 변수라는 점에 착안해 비교적 식을 간단하게 만들 수 있었다.
우선은 이걸 실행시켜서 정상 작동하는지 확인해보자.
일단 위쪽 반절까지는 만드는 데 성공한 것 같다.
(아직은 다이아몬드가 아니라 피라미드를 찍는 사람이지만)
그러면 아래쪽 나머지 부분을 만들려면 어떻게 해야 하지?
이 부분은 !로 마이너스 부호로 바꾸거나 하는 생각도 해봤지만, 조건을 전부 반전시키는 것이 불가능했다.
한참을 머리를 쥐어짜다가 문득 이런 생각이 들었다.
'위쪽 반절은 성공했잖아. 이 부분은 그대로 두고, 아래쪽 반절을 만드는 반복문을 하나 더 만들면 되잖아?'
지금 생각하면 별 것 아닌 것일 수도 있지만, 단순히 기능을 잘게 쪼개는 것이 아닌,
작업도 상황에 따라 쪼갤 수도 있다는 아이디어에 도달한 것이다.
---* 공백 3 별 1
--*** 공백 2 별 3
-***** 공백 1 별 5
******* 공백 0 별 7
-----------------------
-***** 공백 1 별 5
--*** 공백 2 별 3
---* 공백 3 별 1 // 이제 아래 부분만 구현하면 된다.
이제 방법을 생각해냈으니 아래 부분의 반복문도 작성하면 된다.
// 다이아몬드의 아랫부분을 만들 코드.
for(int i = 1; i <= inputNum/2; i++)
{
for (int j = 1; j <= i ; j++)
{
Console.Write(" ");
}
for (int k = 1; k <= inputNum - 2 * i;k++)
{
Console.Write("*");
}
Console.WriteLine();
}
위에서 이미 피라미드를 찍어봤기 때문에, 역피라미드를 만드는 것은 어렵지 않았다.
이렇게 작성하고서 실행 시켜봤다.
결론은... 다이아몬드 찍는 거 혼자서 만들었다고 자랑하고 싶은 게 아니다.
이러한 심화 과제를 수행하면서 느낀 점이 많았고 배운 점이 많았던 것을 기록하고자 한다.
- 프로그래밍이 어떤 과정으로 이루어지는지, 어떠한 사고 과정이 필요한지 깨닫게 되었다.
1.1) 어떤 문제에 봉착했을 때, "문제를 쪼개는 것"부터 시작하자.
1.2) 이렇게 문제를 쪼개고 난 후 해결할 수 있는 부분부터 차근차근 생각해 보자.
1.3) 출력 과정이란 부분 자체도 쪼갤 수 있다는 것을 알게 되었다. 괜히 너무 복잡한 방법을 생각하지 말고 간결하고 이해하기 쉬운 코드를 작성하는 방법과 노하우가 필요하다.
- 그저 개인 감상평이다. 혼자서 끙끙 앓다가도 결국 문제를 해결하니 너무도 기분이 좋았다.
이런 기분을 앞으로 프로그래밍 하는 과정에서 잊지 않도록 하자.