<문제>
타노스는 프로그램의 균형을 위해서는 리스트의 원소 절반을 무작위로 삭제해야 한다고 믿고 있다.
타노스가 손가락을 튕겼을 때(프로그램을 실행했을 때) 입력된 리스트에서 절반의 원소를 무작위로 삭제하여 리턴하는 인피니티 건틀렛 프로그램을 작성하시오. (무작위 삭제이므로 입력값이 같아도 출력값이 매번 달라야 합니다)
<조건>
Scanner 이용
<입력 예시>
[2, 3, 1, 6, 5, 7]
<출력 예시 1>
[2, 5, 7]
<출력 예시 2>
[3, 6, 5]
<참고>
리스트의 원소가 홀수개일 경우 절반의 확률로 절반보다 많은 원소가 삭제되거나 절반보다 적은 원소가 삭제되어야 합니다.
(만약 리스트의 원소가 7개라면 절반의 확률로 3개 또는 4개의 원소가 삭제됨)
<달거북씨 코드>
package april3W;
import java.util.ArrayList;
import java.util.Scanner;
public class Thanos_Jack{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
ArrayList<Integer> arList = new ArrayList<>();
while (true) {
System.out.println("원소 리스트에 들어갈 숫자를 입력하세요. 나가기 : q");
String num;
// 숫자와 q 외에 다른 문자가 들어갔을 때 예외처리
try {
// ArrayList에 들어갈 숫자 입력받기
num = sc.next();
if(num.equalsIgnoreCase("q")) {
System.out.println("숫자 입력을 종료합니다.");
break;
}
// 입력받은 숫자 ArrayList에 담기
arList.add(Integer.parseInt(num));
} catch (NumberFormatException e) {
System.out.println("잘못 입력했습니다.");
continue;
}
}
// 입력받은 원소리스트 출력
System.out.print("\n>>> 원소 리스트 [ ");
for (int i = 0; i < arList.size(); i++) {
System.out.print(arList.get(i) + " ");
}
System.out.println(" ]"); // arList size : 3
// arList에서 어느 자리의 원소를 지울지 결정하는 인덱스 배열
// arList의 절반을 지워야하므로, arList size의 반을 길이로 할당한다.
int[] index = new int[arList.size()/2];
// arList의 원소가 홀수일 경우 추가적인 작업을 위한 변수
int r;
// arList가 홀수인 경우
if(arList.size()%2 != 0) {
// 랜덤으로 0 또는 1을 받는다.(50%로의 확률로 가정)
r = Util.getInstance().random(0, 1);
// r이 0인 경우엔 조건식을 충족하지 않아 for문이 돌아가지 않는다.
// 즉, for문은 돌아가지 않거나 딱 한 번 돌아간다.
for (int i = 0; i < r; i++) {
index[i] = Util.getInstance().random(0, arList.size()-1);
arList.remove(index[i]); // 0~3 자리 중 하나가 랜덤으로 지워진다.
}
}
// 만약 1이 나왔다면 현재 arList는 처음 받은 size보다 1 작은 상태
// 0이라면 처음 size 그대로
// 인덱스의 길이만큼 for문을 돌려서 인덱스 배열은 채워주고,
// 받아온 인덱스로 arList의 특정 위치의 값을 지워준다.
for (int i = 0; i < index.length(); i++) {
index[i] = Util.getInstance().random(0, arList.size()-1);
arList.remove(index[i]);
}
System.out.println("===========================================================");
System.out.print("핑거스냅 후, 원소 리스트 [ ");
for (int i = 0; i < arList.size(); i++) {
System.out.print(arList.get(i) + " ");
}
System.out.println(" ]");
}
}
<해설>
1.
리스트에 원소가 몇 개까지 들어가는지, 주어진 크기가 없으므로 ArrayList 사용하여 입력받는다.
2.
숫자 외 다른 문자열이 들어갈 경우를 예외처리해주고 String 타입으로 받은 num을 Integer로 형변환시켜준다.
3.
인덱스 배열의 크기를 ArrayList 사이즈의 절반 크기로 지정한다.
이 배열의 길이로 아래에서 원소를 지울 때 몇 개를 지우는지 결정된다.
4.
원소의 개수가 짝수인 경우, 인덱스의 길이만큼 for문을 돌면서 랜덤으로 인덱스 배열을 채워준다.
배열 안에 들어가는 숫자는 0보다 크고 ArrayList 사이즈보다 하나 작다.
즉, ArrayList의 인덱스 번호(0부터 arList.size()-1 사이의 값)를 값으로 갖고, 해당 인덱스의 ArrayList 원소를 지워준다.
5. 홀수인 경우, 50%의 확률로 0과 1을 랜덤 부여하여 1일 경우 원소를 추가로 지워준다.
기본적으로 다른 스터디원들도 코드의 틀은 비슷비슷 함. 다만 50%의 확률로 절반 이상이 삭제되도록 구현하는 코드들이 저마다 달랐다.
달거북씨의 경우,
// arList가 홀수인 경우
if(arList.size()%2 != 0) {
// 랜덤으로 0 또는 1을 받는다.(50%로의 확률로 가정)
r = Util.getInstance().random(0, 1);
// r이 0인 경우엔 조건식을 충족하지 않아 for문이 돌아가지 않는다.
// 즉, for문은 돌아가지 않거나 딱 한 번 돌아간다.
for (int i = 0; i < r; i++) {
index[i] = Util.getInstance().random(0, arList.size()-1);
arList.remove(index[i]); // 0~3 자리 중 하나가 랜덤으로 지워진다.
}
랜덤으로 0과 1이 부여되는 확률이 50%라고 가정하고 1일 경우엔 for문 안으로 들어가 arList의 원소를 한 번 더 지워주는 코딩을 짰다.
스터디원 S씨의 경우,
if(rd.nextInt(2) == 0) {
// Math.ceil : 주어진 숫자보다 크거나 같은 숫자 중 가장 작은 숫자를 integer로 반환
a = (int)Math.ceil(arr.length/2.0);
}else {
// Math.floor : 숫자를 가장 가까운 정수 또는 지정된 유의값의 배수로 내린다.
// 음수일 경우 모드에 따라 0에 가까워지거나 0에서 멀어지는 방향으로 올림
a = (int)Math.floor(arr.length/2.0);
}
달거북씨와 동일하게 랜덤으로 0과 1을 부여한다.
이후 Math.ceil()과 Math.floor()를 사용해 arr.length의 절반만 지울지, 절반보다 많이 지울지를 결정했다.
Math.ceil()은 내림, Math.floor()는 올림이라고 생각하면 쉽다.
스터디원 Y씨의 경우,
(int)Math.round(Math.random() + thanos_list.length / 2);
Math.random()의 성격을 응용했다.
Math.random()은 0 이상 1 미만의 자연수이므로 0~0.99999...가 랜덤으로 부여된다.
이때 Math.round()를 씌워주면, 0.49999...까지는 0으로 내려지고, 0.5부터는 반올림되어 원소리스트에 1이 더해지게 된다.
'study > 코드리뷰' 카테고리의 다른 글
[4월 셋째주 STUDY] 코드리뷰2 (0) | 2022.04.25 |
---|---|
[4월 셋째주 STUDY] 코드리뷰1 (0) | 2022.04.25 |
0315 코드리뷰 Q2. 소개하기1 (0) | 2022.03.17 |
0315 코드리뷰 Q1. 소개하기1 (0) | 2022.03.17 |
220314 코드리뷰 Q2. 삼각형 넓이 구하기 (0) | 2022.03.17 |