활동/호기심

자바 for문을 이용한 '공포의 별 찍기 문제'

ByeongJun 2023. 8. 25. 16:02
반응형

학습 기록을 시작하기 앞서, 나는 뛰어난 개발자는 아니지만 꾸준한? 아니 끈질긴 개발자라는 문득 생각 들었다. 

 

이해 안된다고 그냥 넘어갔던 별 찍기 문제를 기어코 다시 마주했고 

'이걸 이제와서 또 하네.. 진작 해볼걸' 같은 한심한 생각도 들었지만 

그래도 피하지 않고 포기하지 않고 이해하려고 또 덤벼든

나 자신에게 오늘의 칭찬과 보상을 주기로 했다. ( TMI : 저녁에 낙성대입구에 고등어회 먹으러 갈 예정) 

 

자바를 초창기에 공부하면서 옆자리에 앉은 전공자에게 어떻게 하면 잘할 수 있냐 물으니 

돌아왔던 대답은 '무조건 찍어보지만 말고 일단 먼저 생각해보라는 것'이었는데 

 

그 말이 이제는 공감되는 것 같다. 


 

 

 

2차원 배열 별 찍기 

for(int i=0;i<3;i++){                        // i값이 '1'이라면 한 줄만 출력
	for(int j=0;j<5;j++){
		System.out.print("*");       // 안쪽 for문의 별(*) 5개 출력
	}
	System.out.println("");              // 한 줄 출력이 끝나면 줄 바꿔주는 역할 println("")
}

 

별 찍기 문제는 호락호락 하지 않기 때문에

이름대로(?) 별의별 모양을 찍어달라는 문제가 많다.


 

 

 

 

 

왼쪽 정렬된 별 찍기 

for(int i=1; i<6; i++){               // i값을 '0'으로 할 경우 처음에 아무것도 없는 '1'라인 출력
	for(int j=0; j<i; j++){       // i값은 '1'일 때 j값은 0부터 시작하며 점점 증가
		System.out.print("*");
	}
	System.out.println("");
}

 for (int i = 1; i < 6; i++)

바깥쪽 for문은 1부터 5까지의 값을 갖는 i를 반복하며, 각각의 값에 따라 한 줄을 출력한다. 

 

 

 

for (int i = 1; i <= 5; i++) {  // 1부터 5까지 반복하는 바깥쪽 루프
    for (int j = 0; j < i; j++) {  // i의 값에 따라 별(*)을 출력하는 안쪽 루프
        if (j < i) {  // 현재 위치의 j가 현재 i보다 작으면 참
            System.out.print("*");  // 별(*)을 출력
        } else if (i < j) {  // 현재 위치의 i가 현재 j보다 작으면 참 (항상 거짓)
            System.out.print("");  // 아무것도 출력하지 않음
        }
    }
    System.out.println();  // 한 줄이 끝날 때마다 줄바꿈
}

위의 코드는 동일한 결과를 출력하지만 조건문 if, else if를 사용했다는 점에서 차이가 있는데 

굳이 출력되지 않는 공백을 else if ( i < j )를 통해 " "을 찍어줬다. 

 

 

 

chat GPT를 통해 얻은 답변이니 가벼운 마음으로 참고하시길 

 

 

 

 

 

첫번째 자리에 별이 고정으로 박혀있는 5층 짜리 별탑을 찍어줬다면 

마지막 자리에 별이 고정으로 박혀있는 5층 짜리 별탑은 어떻게 찍을까? 

 

 

 

 

 

오른쪽 정렬된 별 찍기 

for (int i = 1; i <= 5; i++) {         // 1부터 5까지의 값을 가지는 바깥쪽 루프
    for (int j = 5; j > 0; j--) {      // 5부터 시작하여 1까지 감소하는 안쪽 루프
        if (i < j) {                   // 현재 i 값이 j 값보다 작으면 참
            System.out.print(" ");     // 공백 출력
        } else {
            System.out.print("*");     // 별(*) 출력
        }
    }
    System.out.println("");            // 한 줄이 끝날 때마다 줄바꿈
}

 

참고로 System.out.print(" ")에서 

"" (빈 문자열)과 "  " (공백) 두 가지의 차이점을 잘 구분하도록 한다.

 

그렇지 않으면 왼쪽과 같은 모양이 나올 수도 있다.

 


 

 

 

 

 

피라미드 모양 별 찍기 

중첩된 for문을 사용해 좌우 정렬된 삼각형 모양을 찍먹 해봤다면 

피라미드 모양으로 별 찍는 방법은 아래와 같다. 

 

for (int i = 0; i < 4; i++) {                 // 바깥쪽 루프: i는 0부터 3까지 반복
    for (int j = 0; j < 3 - i; j++) {         // 안쪽 루프 1: j는 0부터 (3 - i)까지 반복
        System.out.print(" ");  // 공백 출력
    }
    for (int j = 0; j < 2 * i + 1; j++) {     // 안쪽 루프 2: j는 0부터 (2 * i + 1)까지 반복
        System.out.print("*");                // 별(*) 출력
    }
    System.out.println("");                   // 한 줄 출력이 끝나면 줄바꿈
}

 

아래 표에서 3, 2, 1 숫자로 채워진 칸을 보면 밑으로 갈 수록 빈칸이 줄어드는 것을 볼 수 있다. 

 

3 3 3      
2 2    
1  

 

i = 0 일 때 첫번째 안쪽의 for문  for(int j=0;j<3-i;j++)  조건에 맞게 3 - i; 결과가 3이 나오는데 

이는 공백이 3번 출력된다는 것을 알 수 있다. 

 

그렇기 때문에 i = 1 일 경우는 3 - i; 의 결과는 2가 될 것이고 공백이 2번 출력되며

 

i = 3 일 경우에는 3 - 3 = 0

즉, 공백 없이 없기 때문에 두번째 안쪽 for문의  for (int j = 0; j < 2*i + 1; j++) 

조건에 맞는 별(*)이 7번 출력되는 것을 볼 수 있다. 

 

 

 

 

 

주어진 코드의 실행 과정을 나타낸 것이다.

(각 줄은 바깥쪽 for문의 반복 횟수 i를 나타냄)

  1. i가 0일 때:
    • 첫 번째 안쪽 for문(for (int j = 0; j < 3 - i; j++))에 의해 3 - 0 = 3번 공백 출력
    • 두 번째 안쪽 for문(for (int j = 0; j < 2 * i + 1; j++))에 의해 2 * 0 + 1 = 1번 별(*) 출력
  2. i가 1일 때:
    • 첫 번째 안쪽 for문(for (int j = 0; j < 3 - i; j++))에 의해 3 - 1 = 2번 공백 출력
    • 두 번째 안쪽 for문(for (int j = 0; j < 2 * i + 1; j++))에 의해 2 * 1 + 1 = 3번 별(*) 출력
  3. i가 2일 때:
    • 첫 번째 안쪽 for문(for (int j = 0; j < 3 - i; j++))에 의해 3 - 2 = 1번 공백 출력
    • 두 번째 안쪽 for문(for (int j = 0; j < 2 * i + 1; j++))에 의해 2 * 2 + 1 = 5번 별(*) 출력
  4. i가 3일 때:
    • 첫 번째 안쪽 for문(for (int j = 0; j < 3 - i; j++))에 의해 3 - 3 = 0번 공백 출력
    • 두 번째 안쪽 for문(for (int j = 0; j < 2 * i + 1; j++))에 의해 2 * 3 + 1 = 7번 별(*) 출력

 

반응형