[java] 자바의 정석 연습문제 ch05

5-1. 다음은 배열을 선언하거나 초기화한 것이다. 잘못된 것을 고르고 그 이유를 설명하시오.

a. int [] arr[];

b. int [] arr2 = {1,2,3};

c. int [] arr3 = new int[5];

d. int [] arr4 = new int[5]{1,2,3,4,5};  //Cannot define dimension expressions when an array initializer is provided

e. int arr5[5];  //Syntax error on token "5", delete this token

f. int[] arr6[] = new int[3][];


d. 배열을 초기화할 때 크기를 표현해서 정의 할 수 없다.

e. 문법 오류.




5-2. 다음과 같은 배열이 있을 때, arr[3].length의 값은 얼마인가? 2

-----------------------------------------------------------

int[][] arr = {

{5,5,5,5,5,},

{10,10,10},

{20,20,20,20},

{30,30}

};

------------------------------------------------------------

-> arr[3] ({30,30}) 방의 길이를 나타내므로 2이다.


5-3. 배열 arr에 담긴 모든 값을 더하는 프로그램을 완성하시오.

-----------------------------------------------------------

int[]arr = {10,20,30,40,50};

int sum = 0;

 

for(int i=0;i<arr.length;i++)

sum += arr[i];

 

System.out.println("sum = "+sum);

-----------------------------------------------------------

-> 배열의 시작인 0부터 배열의 최종 길이를 나타내는 length를 써써 모든 방의 원소에 접근하며, 각 원소를 sum 변수에 더해준다.


5-4. 2차원 배열 arr에 담긴 모든 값의 총 합과 평균을 구하는 프로그램을 완성하시오.

-----------------------------------------------------------

int[][] arr = {

{5,5,5,5,5},

{10,10,10,10,10},

{20,20,20,20,20},

{30,30,30,30,30}

};

 

int total = 0;

float average = 0;

int count = 0;  //원소의 총 개수를 구하기 위한 카운트 변수

for(int i=0;i<arr.length;i++){

for(int j=0;j<arr[i].length;j++){

total += arr[i][j];

count++;

}

}

average = (float)total/count;

 

System.out.println("total = "+total);

System.out.println("average = "+average);

-----------------------------------------------------------

-> 2차원 배열이므로 for문을 중첩으로 사용해 각각 행과 열로 지정해주어 모든 원소에 접근한다. 그리고 각 원소의 값을 total에 더해주어 총합을 구하며, count 변수를 두어 각 원소의 개수만큼 증가시킨후 총합과 나누어 평균을 구한다.

5-5. 다음은 1과 9사이의 중복되지 않은 숫자로 이루어진 3자리 숫자를 만들어내는 프로그램이다. (1)~(2)에 알맞은 코드를 넣어서 프로그램을 완성하시오.

[참고] Math.random()을 사용했기 때문에 실행 결과와 다를 수 있다.

-----------------------------------------------------------

int[] ballArr = {1,2,3,4,5,6,7,8,9};

int[] ball3 = new int[3];

 

// 배열 ballArr의 임의의 요소 2개를 골라서 위치를 바꾼다. 20번 반복

for(int x=0;x<20;x++){

int i = (int)(Math.random()*ballArr.length);

int j = (int)(Math.random()*ballArr.length);

int tmp = 0;

 

tmp = ballArr[i];

ballArr[i] = ballArr[j];

ballArr[j] = tmp;

}

 

// 배열 ballArr의 앞에서 3개의 수를 배열 ball3로 복사한다.

System.arraycopy(ballArr, 0, ball3, 0, 3);

 

for(int i=0;i<ball3.length;i++)

System.out.print(ball3[i]);

-----------------------------------------------------------

-> (1) i번째방과 j번째방의 원소를 바꿔야하므로 임시변수인 tmp를 선언하여 swap해주었다.
(2)arraycopy()함수를 사용하여 ballArr의 0~2번째 방에 있는 원소를 ball3로 복사한다.


5-6. 다음은 거스름돈을 몇 개의 동전으로 지불할 수 있는지를 계산하는 문제이다. 변수 money의 금액을 동전으로 바꾸었을 때 각각 몇 개의 동전이 필요한지 계산해서 출력하라. 단, 가능한 한 적은 수의 동전으로 거슬러 주어야한다. (1)에 알맞은 코드를 넣어서 프로그램을 완성하시오.

[hint] 나눗셈 연산자와 나머지 연산자를 사용해야 한다.

-----------------------------------------------------------

int[] coinUnit = {500,100,50,10};

 

int money = 2680;

System.out.println("money = "+money);

 

for(int i=0;i<coinUnit.length;i++){

System.out.println(coinUnit[i]+"Won : "+money/coinUnit[i]);

money %= (money/coinUnit[i])*coinUnit[i];

}

-----------------------------------------------------------

-> 동전이 들어있는 coinUnit배열을 처음부터 끝방까지 돌면서 해당 원소의 값과 money의 값을 나눈 몫으로 필요한 동전의 개수를 구하였고, money는 해당 동전의 개수*동전의 값으로 나눈 나머지의 값을 취하게하여 연산하였다.


5-7. 문제 5-6에 동전의 개수를 추가한 프로그램이다. 커맨드라인으로부터 거슬러 줄 금액을 입력받아 계산한다. 보유한 동전의 개수로 거스름돈을 지불할 수 없으면, ‘거스름돈이 부족합니다.’라고 출력하고 종료한다. 지불할 돈이 충분히 있으면, 거스름돈을 지불한 만큼 가진 돈에서 빼고 남은 동전의 개수를 화면에 출력한다. (1)에 알맞은 코드를 넣어서 프로그램을 완성하시오.

-----------------------------------------------------------

if(args.length != 1){

System.out.println("USAGE: java Exercise5_7 3120");

System.exit(0);

}

 

// 문자열을 숫자로 변환한다. 입력한 값이 숫자가 아닐 경우 예외가 발생한다.

int money = Integer.parseInt(args[0]);

 

System.out.println("money = "+money);

 

int[] coinUnit = {500,100,50,10};

int[] coin = {5,5,5,5};

 

for(int i=0;i<coinUnit.length;i++){

int coinNum = 0;

 

/*

* (1) 아래의 로직에 맞게 코드를 작성하시오.

* 1. 금액을 동전단위로 나눠서 필요한 동전의 개수를 구한다.

* 2. 배열 coin에서 coinNum만큼의 동전을 뺀다.

* (만일 충분한 동전이 없다면 배열 coin에 있는 만큼만 뺀다.

* 3. 금액에서 동전의 개수와 동전단위를 곱한 값을 뺀다.

*/

coinNum = money/coinUnit[i];

if(coin[i] < coinNum){

coinNum = coin[i];

coin[i] = 0;

}

else

coin[i] -= coinNum;

money -= coinNum*coinUnit[i];

 

System.out.println(coinUnit[i]+"Won : "+coinNum);

}

 

if(money > 0){

System.out.println("거스름돈이 부족합니다.");

System.exit(0);

}

System.out.println("= 남은 동전의 개수 =");

for(int i=0;i<coinUnit.length;i++)

System.out.println(coinUnit[i]+"Won : "+coin[i]);

-----------------------------------------------------------

-> 동전의 몫과 거슬러주고 남은 돈의 값을 계산하는 원리는 위의 문제와 동일하다. 다만, 여기서는 거슬러줄 동전의 개수가 한정적이므로 필요한 동전의 개수가 가지고 있는 동전의 개수보다 많으면 가지고 있는 동전의 개수 만큼만 내어주도록 조건문을 사용해 처리해 주었다.


5-8. 다음은 배열 answer에 담긴 데이터를 읽고 각 숫자의 개수를 세어서 개수만큼 ‘*’을 찍어서 그래프를 그리는 프로그램이다. (1)~(2)에 알맞은 코드를 넣어서 완성하시오.


[참고] 문제에 나와있는 보기 for문이 이해가 안됨. 출력 예시문 또한 이해가 안됨. 따라서 문제 보기에만 충실하여 품

-----------------------------------------------------------

int[] answer = {1,4,4,3,1,4,4,2,1,3,2};

int[] counter = new int[4];

 

// 수키 버전

for(int i=0;i<answer.length;i++){

System.out.print(answer[i]+" : ");

for(int j=0;j<answer[i];j++){

System.out.print('*');

}

System.out.println();

}

 

// 원본 보기

/*

for(int i=0;i<answer.length;i++){

// (1) 알맞은 코드를 넣어 완성하시오.

}

for(int i=0;i<counter.length;i++){

// (2) 알맞은 코드를 넣어 완성하시오.

System.out.println();

}

*/

-----------------------------------------------------------

-> 문제가 이해되질않아 counter의 변수에 있는 원소의 값 만큼 반복분을 돌리며 *를 출력하도록 하였다.


5-9. 주어진 배열을 시계방향으로 90도 회전시켜서 출력하는 프로그램을 완성하시오.

-----------------------------------------------------------

char[][] star = {

{'*','*',' ',' ',' '},

{'*','*',' ',' ',' '},

{'*','*','*','*','*'},

{'*','*','*','*','*'},

};

 

char[][] result = new char[star[0].length][star.length];

 

for(int i=0;i<star.length;i++){

for(int j=0;j<star[i].length;j++)

System.out.print(star[i][j]);

System.out.println();

}

System.out.println();

 

for(int i=0;i<star.length;i++){

for(int j=0;j<star[i].length;j++){

result[j][(star.length-1)-i] = star[i][j];

}

}

 

for(int i=0;i<result.length;i++){

for(int j=0;j<result[i].length;j++)

System.out.print(result[i][j]);

System.out.println();

}

-----------------------------------------------------------

-> 원본과 복사본의 차이점을 분석해본 결과
(0,2) -> (1,0)
(1,2) -> (1,1)
(2,2) -> (1,2)
(3,2) -> (1,3)
(4,2) -> (1,4)
.
.
.
(변하는 수,고정된 값) -> (고정된 값, 변하는 수) 로 나오는데 이 값이 나올 수 있게 써먹을만한게 뭐가 있나 봤더니
(j와 동일, 원본 배열의 길이 - 1과 동일) -> (i와 동일,j와 동일) 이더라.


5-10. 다음은 알파벳과 숫자를 아래에 주어진 암호표로 암호화하는 프로그램이다. (1)에 알맞은 코드를 넣어서 완성하시오.

-----------------------------------------------------------

char[] abcCode =

{'`','~','!','@','#','$','%','^','&','*',

'(',')','-','_','+','=','|','[',']','{',

'}',';',':',',','.','/'};

 

char[] numCode = {'q','w','e','r','t','y','u','i','o','p'};

 

String src = "abc123";

String result = "";

 

// 문자열 src의 문자를 charAt()으로 하나씩 읽어서 변환 후 result에 저장

for(int i=0;i<src.length();i++){

char ch = src.charAt(i);

if(ch >= '0' && ch <= '9')

result += numCode[ch-'0'];

else

result += abcCode[ch-'a'];

}

 

System.out.println("src : "+src);

System.out.println("result : "+result);

-----------------------------------------------------------

-> 읽어들인 문자가 숫자(0~9)라면 해당 값에서 문자0의 값을 빼주어 숫자 암호화방에서 그 값에 해당하는 암호문을result에 더해주었고, 그외의 문자는 소문자 알파벳으로 처리한다고 생각하며 a값을 빼주어 해당 알파벳에 해당하는 암호화방에서 암호를 가져와 더해주었다.


5-11. 주어진 2차원 배열의 데이터보다 가로와 세로로 1이 더 큰 배열을 생성해서 배열의 행과 열의 마지막 요소에 각 열과 행의 총합을 저장하고 출력하는 프로그램이다. (1)에 알맞은 코드를 넣어서 완성하시오.

-----------------------------------------------------------

int[][] score = {

{100,100,100},

{20,20,20},

{30,30,30},

{40,40,40},

{50,50,50},

};

 

int [][] result = new int[score.length+1][score[0].length+1];

 

for(int i=0;i<score.length;i++){

for(int j=0;j<score[i].length;j++){  // rowSum

result[i][j] = score[i][j];

result[i][score[i].length] += score[i][j];

}

for(int j=0;j<score.length;j++){  // colSum

if(i < score[i].length)

result[score.length][i] += score[j][i];

else

break;

}

if(i == score.length-1){  // 최종 합계

for(int j=0;j<score[i].length;j++)

result[i+1][score[i].length] += result[i+1][j];

}

}

 

for(int i=0;i<result.length;i++){

for(int j=0;j<result[i].length;j++)

System.out.printf("%4d",result[i][j]);

System.out.println();

}


-----------------------------------------------------------

-> 결과 배열을 기준으로 차이점을 분석해본 결과
row행 합계 : (i와 동일, 원본배열의 길이와 동일) = 원본배열을 순차적으로 돈다.
col열 합계 : 결과배열을 기준으로 값을 넣는다고 가정했을때 for문 한개만으로 규칙을 만드려고하니 원본배열의 열행을 넘어가버리는 에러가 발생하게 되었다. 따라서, for문을 한개 더 두어 열 합계를 따로 구했으며, 최종 행 합계를 위해 행(i)이 원본배열의 길이와 똑같다면 최종합계를 구하도록 하였다.
시작할때 결과배열 기준으로만 생각했기 때문에 불필요한 연산과 반복문이 추가되었다. 다른 사람의 코드를 보니 결과배열이 기준이 아닌 원본배열을 기준으로 규칙을 찾았던데 이런 접근 방법이 더 효율적인것 같다.