반복문의 활용이다. 띠용하면서, C#의 다른 기능들에 대해서 명시를 하려고 했지만 중간에 내가 정리해 놓은 반복문의 활용에 대해서 어떻게 이러한 생각을 가졌는지에 대해서 기록하고 미래에 내가 이 글을 다시 본다면 어떤 생각을 할지가 궁금해서 이렇게 글을 작성해야겠다 생각했다.
계단식 별짓기 부터 다이야몬드 별짓기, 다이야몬드 별짓기 경량하기 순서로 글을 작성하겠다.
namespace BuildingStar
{
internal class Program
{
static char star = '*';
static char blank = ' ';
static void Main(string[] args)
{
int num = 5;
BuildingStarPatten1(num);
BuildingStarSimplePatten1(num);
}
static void BuildingStarPatten1(int num)
{
Console.WriteLine("==========1");
for (int i = 0; i < num; i++)
{
for (int j = 0; j < i + 1; j++)
Console.Write(star);
Console.WriteLine();
}
}
static void BuildingStarSimplePatten1(int num)
{
Console.WriteLine("==========1");
for (int i = 0; i < num; i++)
Console.WriteLine(new string(star, i + 1));
}
}
}
==========1
*
**
***
****
*****
==========1
*
**
***
****
*****
이러한 식으로 별을 짓기를 한다.
해당 줄의 번호 만큼 별을 출력한다.namespace BuildingStar
{
internal class Program
{
static char star = '*';
static char blank = ' ';
static void Main(string[] args)
{
int num = 5;
BuildingStarPatten2(num);
BuildingStarSimplePatten2(num);
}
static void BuildingStarPatten2(int num)
{
Console.WriteLine("==========2");
for (int i = 0; i < num; i++)
{
for (int j = 0; j < num - (i + 1); j++)
Console.Write(blank);
for (int j = 0; j < i + 1; j++)
Console.Write(star);
Console.WriteLine();
}
}
static void BuildingStarSimplePatten2(int num)
{
Console.WriteLine("==========2");
for (int i = 1; i <= num; i++)
Console.WriteLine(new string(blank, num - i) + new string(star, i));
}
}
}
==========2
*
**
***
****
*****
==========1
*
**
***
****
*****
이러한 식으로 별을 짓기를 한다.
최대 줄 - 현재 줄의 번호 이다. 해당 줄의 번호 만큼 별을 출력한다.namespace BuildingStar
{
internal class Program
{
static char star = '*';
static char blank = ' ';
static void Main(string[] args)
{
int num = 5;
BuildingStarPatten3(num);
BuildingStarSimplePatten3(num);
}
static void BuildingStarPatten3(int num)
{
Console.WriteLine("==========3");
for (int i = 0; i < num; i++)
{
for (int j = 0; j < num - i; j++)
Console.Write(star);
Console.WriteLine();
}
}
static void BuildingStarSimplePatten3(int num)
{
Console.WriteLine("==========3");
for (int i = 0; i < num; i++)
Console.WriteLine(new string(star, num - i));
}
}
}
==========3
*****
****
***
**
*
==========3
*****
****
***
**
*
이러한 식으로 별을 짓기를 한다.
최대 줄 - 해당 줄의 번호 + 1 만큼 별을 출력한다.namespace BuildingStar
{
internal class Program
{
static char star = '*';
static char blank = ' ';
static void Main(string[] args)
{
int num = 5;
BuildingStarPatten4(num);
BuildingStarSimplePatten4(num);
}
static void BuildingStarPatten4(int num)
{
Console.WriteLine("==========4");
for (int i = 0; i < num; i++)
{
for (int j = 0; j < i + 1; j++)
Console.Write(blank);
for (int j = 0; j < num - i; j++)
Console.Write(star);
Console.WriteLine();
}
}
static void BuildingStarSimplePatten4(int num)
{
Console.WriteLine("==========4");
for (int i = 0; i < num; i++)
Console.WriteLine(new string(blank, i) + new string(star, num - i));
}
}
}
==========4
*****
****
***
**
*
==========4
*****
****
***
**
*
이러한 식으로 별을 짓기를 한다.
현재 줄의 번호 - 1 이다. 최대 줄 - 해당 줄의 번호 + 1 만큼 별을 출력한다.위의 계단 식 별짓기는 문제 없이 넘어 왔다. 그런데 다이야몬드라니??? 다이아~몬~드~...? (선넘네)
뭐 접근 방법 같은 경우는 위 아래를 따로 출력하자는 생각이여서 별짓기 기본이라고 하고 아래에 적었다.
namespace BuildingStar
{
internal class Program
{
static char star = '*';
static char blank = ' ';
static void Main(string[] args)
{
int num = 7;
Console.WriteLine("\nBuilding Star Diamond Patten Func");
BuildingStarDiamondPatten1(num);
}
static void BuildingStarDiamondPatten1(int num)
{
if (num <= 1 || num % 2 == 0) return;
int i = 0;
int topRow = (num / 2) + 1;
int botRow = (num / 2);
Console.WriteLine("for문 6개");
// 위쪽
for (i = 0; i < topRow; i++)
{
for (int j = 0; j < topRow - (i + 1); j++)
Console.Write(blank);
for (int j = 0; j < (i * 2) + 1; j++)
Console.Write(star);
Console.WriteLine();
}
// 아래쪽
for (i = 0; i < botRow; i++)
{
for (int j = 0; j < i + 1; j++)
{
Console.Write(blank);
}
for (int j = 0; j < (botRow - i) * 2 - 1; j++)
{
Console.Write(star);
}
Console.WriteLine();
}
}
}
}
Building Star Diamond Patten Func
for문 6개
*
***
*****
*******
*****
***
*
일단 다이아몬드 별짓기 같은 경우는 조건은 1과 짝수를 제외하고 입력을 받는것이다.
그렇다면 이제 생각해볼 것은? "다이아몬드면 별이 늘어나다가 줄어드는 시점의 분기를 어떻게 처리하는가" 가 이 다이아몬드의 핵심이라고 생각한다.
그래서 위쪽과 아래쪽을 나누어 생각하기로 하였다. 위에서 늘어나는 위쪽 홀수 처리, 아래는 줄어들기 시작하는 짝수 처리를 맡겨야하고 처리를 한다면 아래의 코드와 같이 쉽게 구상이 된다.
namespace BuildingStar
{
internal class Program
{
static char star = '*';
static char blank = ' ';
static void Main(string[] args)
{
int num = 7;
Console.WriteLine("\nBuilding Star Diamond Patten Func");
BuildingStarDiamondPatten2(num);
}
static void BuildingStarDiamondPatten2(int num)
{
if (num <= 1 || num % 2 == 0) return;
int bCount = 0;
int sCount = 0;
int half = num / 2 + 1;
Console.WriteLine("for문 3개");
for (int i = 0; i < num; i++)
{
if (half <= i)
{
bCount = i - num / 2; // -2 -1 0 1 2
sCount = (num - i) * 2 - 1; // 9 7 5 2 1
}
else
{
bCount = num / 2 - i; // 2 1 0 -1 2
sCount = i * 2 + 1; // 1 3 5 7 9
}
for (int j = 0; j < bCount; j++)
Console.Write(blank);
for (int j = 0; j < sCount; j++)
Console.Write(star);
Console.WriteLine();
}
}
}
}
Building Star Diamond Patten Func
for문 3개
*
***
*****
*******
*****
***
*
이렇게 해서 분기를 나누고 위와 아래의 출력 처리를 한곳에서 하게 되면서, for 문의 3개만 사용할 수 있게 되었다.
문제는 이제 이 코드를 줄여보는 것이다. 그럼 전환되는 분기말고도 규칙성을 찾아야된다.
찾은 규칙은 빈칸은 위와 아래가 같다이다. 그럼 이렇게 찾은 규칙을 코드로 작성한것이 아래의 코드이다.
namespace BuildingStar
{
internal class Program
{
static char star = '*';
static char blank = ' ';
static void Main(string[] args)
{
int num = 7;
Console.WriteLine("\nBuilding Star Diamond Patten Func");
BuildingStarDiamondPatten3(num);
}
static void BuildingStarDiamondPatten3(int num)
{
if (num <= 1 || num % 2 == 0) return;
Console.WriteLine("for문 1개");
int half = num / 2;
for (int i = 0; i < num; i++)
{
// 중간을 기준으로 대칭적인 빈칸 개수
int bCount = Math.Abs(half - i); // 3, 2, 1, 0, 1, 2, 3
// 전체 개수에서 빈칸을 제외한 별 개수
int sCount = num - 2 * bCount; // 1, 3, 5, 7, 5, 3, 1
Console.WriteLine(new string(blank, bCount) + new string(star, sCount));
}
}
}
}
Building Star Diamond Patten Func
for문 1개
*
***
*****
*******
*****
***
*
이렇게 분기를 찾고, 해당 분기가 되어가면서 전환되는 규칙을 찾아서 활용하였다. 이번 코드의 핵신은 빈칸이다. 왜 위 코드의 빈칸이 핵심일까? 빈칸은 분명 줄어들다가 마이너스로 줄어든다. 그래도 부호를 제거 시 숫자는 대칭을 이룬다는 점이 주목할 점이다.
그런데 이 곳에서 봐야될 것은 그 빈칸의 숫자다.
이 빈칸의 수가 전체 줄수 - 2 * 빈칸의 수 를 한다면 해당 줄에 그려야될 별의 수가 나온다.
당연한 결과라고 할수 있다. 에초에 위에서 절반을 구하는 코드에서의 3과 절반 값에서 감소, 증가를 하는 빈칸의 수는 전체 줄수를 2로 나누었들 때 결정이 났다고 볼수 있다. 2와 절대값이 해당 코드의 핵심이라고 생각한다. (에초에 정수로 값을 받아서 기존의 값보다 작은 짝수로 나누는 상황이 연출되서 곱하기 3를 해도 최대 줄수를 넘길 수 없다. 넘어가게 설정을 해도 star 찍는 수는 음수로 넘어가게 된다.)
같은 기능이여도 더욱 간단하게 코드를 작성할 수 있다. 그러한 이유는 내가 하고자하는 것의 규칙성이 존재하는지 와 변화가 일어나는 시점 을 관찰하는 관점과 시야가 중요하다는 것을 알게 되었다. 이 뒤에는 열거형과 구조체 등을 포스팅을 하겠다. 언능 포스팅하고 이렇게 생각을 할만한 거를 다시 포스팅하겠다.
규칙성이 존재하는지
변화가 일어나는 시점