자바 반복문 공부할 때 꼭 한번쯤 해 본다는 그 예제!
별 찍기.
자바 공부 초반에, 수업 중 for문을 엄청 빠르게 배웠었는데
그게 너무 이해가 안 가서 힘들었던 기억이 난다.
(제가 문과라서요... 라고 하기엔 다른 문과 친구들은 곧잘 이해했었음)
근데 지금은 눈 감고도 반복문 돌릴 수 있는 거 보면,
그냥 이 개념이 나에게 생소했던 듯 하다.
당시 새벽까지 찍고 또 찍어냈던 수많은 별들을 추억하며-
나처럼, '무슨 말인지 알겠는데 모르겠다' 싶은 이들을 위해
좀더 쉽게 차근차근 별 찍기 과정을 기록해 본다.
순한 맛 하나, 매콤한 맛 하나 두 가지로 풀이!
이중 for문을 사용한 별 찍기 - 순한 맛
줄을 바꾸면서 별표만 하나씩 늘려 가는 예제이다.
얘가 어떻게 반복문인지를 뜯어 보면,
크게 봐서는, 무언가가 5번 반복되면서 5줄짜리 결과물을 만들어내고 있다.
그럼 일단 이렇게 짤 수 있다.
// 1. 총 몇 줄 돌리나? 5줄!
for (int i=0; i<5; i++) {
} // 1번 for문 닫음
그리고 작게 봐서는,
별 X 1 / 별 X 2 / 별 X 3 / 별 X 4 / 별 X 5, 이렇게 별 하나가 반복되고 있다.
익숙하지 않을 때는 이렇게 단순한 별나무도 식을 짜기 쉽지 않으니,
엑셀이나 노트의 힘을 빌어 정리를 하면 눈에 잘 들어온다.
위 예제는 별도의 공백이 없이 별만 반복되므로 두 개만 파악하자!
(i) 몇 번째 줄? | (j) 별 몇 개? |
1 | 1 |
2 | 2 |
. . . |
. . . |
5 | 5 |
감사하게도 참 간단하다!
i = j 가 아닌가!
규칙을 발견했으니 반복문을 설계해 본다.
// 1. 총 몇 줄 돌리나? 5줄!
for (int i=0; i<5; i++) {
// 2. 별표의 변화 : 1-2-3-4-5
for (int k=0; k< i+1; k++) {
System.out.print("*");
}
//별표가 원하는 갯수만큼 찍히고 나면 줄바꿈을 해야 한다.
System.out.println();
} // 1번 for문 닫음
주의할 점 : 별표가 반복될 땐 줄바꿈 없이 반복되므로 print'ln' 아님.
대신 별표 반복이 끝난 후 줄을 바꿔줘야 하니 줄바꿈용 println 하나 넣기!
Q. 별표도 1-2-3-4-5개 순으로 늘어나니까,
i반복문과 똑같이 k<5 로 범위를 잡으면 안 되나요?
A. 안 됩니다. 그럼 모든 줄에 별이 5개씩 찍히니까요!
i의 값이 바뀌면 k도 그 값에 맞추어서 바뀌도록 해야 해요!
- 첫번째 줄일 땐 한 개, 두번째 줄일 땐 두 개, 이렇게 :)
줄 번호 | 별의 개수 | 별의 범위 | ||
1번 줄 | i=0 | 별 1개 | k=0 | k<1 |
2번 줄 | i=1 | 별 2개 | k=0, k=1 | k<2 |
3번 줄 | i=2 | 별 3개 | k=0, k=1, k=2 | k<3 |
. . . |
||||
5번 줄 | i=4 | 별 5개 | k=0, k=1, k=2, k=3, k=4 | k<5 |
어려울 땐 이렇게 풀어서 생각하면 됨!
i값과 k범위만 떼어놓고 보면,
0일때 1, 1일때 2, ... , 4일때 5의 규칙이 보인다.
for (int k=0; k< i+1; k++) {}
그래서 별표를 위한 반복문 k에서, k의 범위식이 k+1이 된 것이다!
별표 예제의 핵심은, 자바에 빙의해서
한 줄 한 줄씩 코드 순서대로 따라가며 값을 확인해 보는 것이다.
이중 for문을 사용한 별 찍기 - 매콤한 맛
매운 맛이 아니라 매콤한 맛이라고 명명한 이유는
작정하고 어려우려면 훨씬 어려운 예제들도 있어서.
그치만 이 예제를 찍을 수 있으면 충분한 것 같아서 우선은 요 녀석을 골랐다!
얘 역시 무언가가 5줄 반복되는 예제이기 때문에
// 1. 총 몇 줄 돌리나? 5줄!
for (int i=0; i<5; i++) {
} // 1번 for문 닫음
여기까지는 똑같다.
그런데...
이 예제에서는 별표가 1, 2, 3, 4, 5가 아닌
1, 3, 5, 7, 9로 2개씩 증가하며
무엇보다 '공백'이라는 빌런이 등장한다. (노란 색 블럭)
모든 줄은 [공백] + [별표] 순서대로 등장한다.
공백과 별표는 포함관계가 아니라 그냥 전-후 관계로 반복시켜주면 되겠다.
공백이 들어간 예제 계산이 헷갈릴 때는, 오른쪽 그림처럼
엑셀에 별표를 그리고 공백을 색칠한 뒤 시작하면 좀 쉽다.
줄 번호 |
별의 개수 | 공백의 개수 | |
1번 줄 | i=0 | 별 1개 | 4칸 |
2번 줄 | i=1 | 별 3개 | 3칸 |
3번 줄 | i=2 | 별 5개 | 2칸 |
4번 줄 | i=3 | 별 7개 | 1칸 |
5번 줄 | i=4 | 별 9개 | 0칸 |
확실히... 어려워졌다.....!
공백이 등장한 것도 짜증나는데 왜 거꾸로 줄어들고 난리.
하지만 역시 한 줄씩 찬찬히 뜯어보면 할 수 있다.
위의 순한 맛 예제를 통해서,
별, 공백 반복문(안쪽 for문들)은 줄 반복문(바깥 for문)과 따로 놀지 않고
바깥 for문의 i값이 변할 때 같이 범위가 변해주어야 한다는 것을 배웠으니
그것만 잊지 않으면 된다.
임의로 별 반복문은 j, 공백 반복문은 k라는 변수를 쓴다고 전제하자.
먼저 별부터 풀어보면,
줄 번호 |
별의 개수 | |
1번 줄 | i=0 | 별 1개 |
2번 줄 | i=1 | 별 3개 |
3번 줄 | i=2 | 별 5개 |
4번 줄 | i=3 | 별 7개 |
5번 줄 | i=4 | 별 9개 |
(i값이) 0일때 (j값은) 1,
1일때 3,
2일때 5,
3일때 7,
4일때 9
이 규칙을 찾아야 한다.
이럴 땐 대부분 i에 공차인 2를 곱해 준 다음에
더하든 빼든 해서 범위를 맞춰주면 된다.
0은 곱셈에서 도움이 안 되니까 제끼고 생각해 보면
1 * 2 + 1 = 3
2 * 2 + 1 = 5
3 * 2 + 1 = 7
찾았다!
i * 2 + 1 = j 이다. (0일 때도 적용된다. 4일 때도 된다.)
// 1. 총 몇 줄 돌리나? 5줄!
for (int i=0; i<5; i++) {
// 2. 공백의 변화 : 4-3-2-1-0
}
// 3. 별표의 변화 : 1-3-5-7-9
for (int k=0; k< 2*i +1; k++) {
System.out.print("*");
}
//공백과 별표가 한 차례씩 찍히고 나면 줄바꿈을 해야 한다.
System.out.println();
} // 1번 for문 닫음
- 순한 맛 예제와 마찬가지로, *이 반복될 땐 줄바꿈이 일어나면 안 된다.
그럼 이제 공백만 찾아주면 되는데...
줄 번호 |
공백의 개수 | |
1번 줄 | i=0 | 4칸 |
2번 줄 | i=1 | 3칸 |
3번 줄 | i=2 | 2칸 |
4번 줄 | i=3 | 1칸 |
5번 줄 | i=4 | 0칸 |
공백 반복문 k도, 별표 반복문 j와 마찬가지로
i값의 영향을 받아 범위가 결정되어야 한다는 것을 기억하고 규칙을 찾자
(i값이) 0일때 (k값은) 4,
1일때 3,
2일때 2,
3일때 1,
4일때 0
공차는 -1이다. 2나 3이 아니니까 곱셈을 할 필요는 없고
이렇게 값이 늘지 않고 줄어들 때는 i에도 음수를 붙여서 규칙을 찾으면 된다.
4 - 0 = 4
4 - 1 = 3
4 - 2 = 2
찾았다!
4 - i = k 이다.
i가 0일 때도, i가 4일 때도 적용된다.
그런데 여기서 잠깐,
우리가 반복문 범위를 설정할 때를 다시 떠올려본다.
만약, 3번 돌리고 싶은 반복문이 있다면
for (int m=0; m<3; m++){}
for (int m=1; m<=3; m++){}
이렇게 두 가지 방법이 있지 않은가!
(m을 0~2로 돌리거나 / m을 1~3으로 돌리거나)
위에서 찾은 4-i=k 를 우리가 쓰려는 j반복문에 적용시켜서
for (int j=0; j<4-i ; j++)
이렇게 표시하게 되면, j값의 범위는
i=0 일 때 j<4 (의 최대값은 3)
i=4일 때 j<0 이 되어서 (반복문 돌지 않음)
우리의 의도와 달라진다.
그러므로,
for (int j=0; j<=4-i ; j++) {}
for (int j=0; j<5-i ; j++) {}
4-i보다 "작거나 같다" 고 설정하거나,
맘 편히 5-i보다 "작다" 고 설정하면 된다.
이중 for문을 활용한 별표 예제를 짤 때 또 다른 팁!
i가 최소일 때의 시뮬레이션과 i가 최대일 때의 시뮬레이션으로
반드시 안쪽 for문의 범위가 맞는지 확인하자.
// 1. 총 몇 줄 돌리나? 5줄!
for (int i=0; i<5; i++) {
// 2. 공백의 변화 : 4-3-2-1-0
for (int j=0; j<5-i ; j++) {
System.out.print(" ");
}
// 3. 별표의 변화 : 1-3-5-7-9
for (int k=0; k< 2*i +1; k++) {
System.out.print("*");
}
//공백과 별표가 한 차례씩 찍히고 나면 줄바꿈을 해야 한다.
System.out.println();
} // 1번 for문 닫음
한 단계씩 차근차근 적느라 조금 길어졌지만
이해하고 나면 명료하다.
이렇게 두 개의 별표 예제 완성!
'개발 > Java' 카테고리의 다른 글
자바 알고리즘 - 서울에서 김서방 찾기 (배열에서의 위치 찾기) (0) | 2021.03.31 |
---|---|
자바 알고리즘 - 자연수를 뒤집어 배열로 만들기 (0) | 2021.03.31 |
자바 반복문과 배열을 활용한 로또 조합 출력 예제 :) (0) | 2021.03.18 |
자바 데이터타입별 최대값과 최소값 출력하기 (MIN_VALUE, MAX_VALUE (0) | 2021.03.18 |
자바 명명 규칙, 개발자들 간의 암묵적인 약속! (0) | 2021.03.18 |