

영학이의 패를 뜻하는 두 개의 정수 A, B가 주어진다. (1 ≤ A, B ≤ 10)
영학이가 이길 확률을 소수점 이하 셋 째 자리까지 반올림해서 출력하시오.
반드시 뒤따르는 0도 출력해야 한다. 예를 들어, '0.700'을 출력했다면 정답이고, '0.7'을 출력했다면 오답이다.
1 1
0.941
list에 1~10까지의 숫자 카드를 2개씩 넣어둔다.
입력받은 숫자(내가 가지고 있는 카드)를 list에서 제외해준다.
내가 가지고 있는 카드가 같은 숫자일 시, isDdang(땡인지 아닌지)를 true로 설정해준다.
내가 땡일 때는 내가 질 case를 계산해서 전체 case에서 빼주는 게 계산이 단순하고, 내가 끗일 때는 상대가 질 case를 계산해주는 게 계산이 단순함.
내가 N땡일 때 : 1) N을 계산해준다. (내가 가지고 있는 카드 값) 2) 전체 카드 중에 N보다 크면서 두 카드가 같은 숫자일 때 cases를 1씩 증가시켜준다. (이때 for문의 범위는 size()-1로 해야한다. (마지막은 확인할 필요가 없음. -> 바로 앞 index와 같지 않을 경우 의미가 없고, 앞에서 같다고 판단했으면 이미 cases가 올라갔기 때문에))
내가 N끗일 때 : 1) N을 계산해준다. (내가 가지고 있는 카드 합에서 10으로 나눈 나머지) 2) 이중 for문을 이용해 두 카드의 합의 일의자리가 N보다 작고 둘의 값이 같지 않을 때 cases를 1 증가시켜준다.
(이때 for문을 도는 index i와 j는 같으면 안 된다. (카드가 중복되면 안 되기 때문에) 또한, [1, 9]와 [9, 1]은 같은 경우이므로, 제외해줘야 한다. (모든 경우는 왼쪽 숫자가 오른쪽 숫자보다 더 작거나 같도록 (i<=j) 조건을 넣어 제외시켜주었다.))
전체 경우의 수 153(18C2)에서 현재 cases가 나올 확률을 계산하여 소수점 3자리까지 출력해준다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
public class Main {
public static void main(String[] args) throws IOException {
List<Integer> all_card = new ArrayList<>(Arrays.asList(1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] input = br.readLine().split(" ");
int card1 = Integer.parseInt(input[0]);
int card2 = Integer.parseInt(input[1]);
all_card.remove(Integer.valueOf(card1));
all_card.remove(Integer.valueOf(card2));
boolean isDdang = (card1==card2);
double cases = 0;
int my = 0; // 땡/끗 앞에 붙는 숫자
if(isDdang) {
my = card1;
for(int i=0; i<all_card.size()-1; i++) {
if(all_card.get(i+1)==all_card.get(i) && all_card.get(i)>card1) {
cases++;
}
}
cases = 153-cases;
} else {
my = (card1+card2)%10;
for(int i=0; i<all_card.size(); i++) {
for(int j=0; j<all_card.size(); j++) {
if(i==j) continue;
if(i<=j) {
if((((all_card.get(i)+all_card.get(j))%10)<my) && all_card.get(i)!=all_card.get(j)) {
cases++;
}
}
}
}
}
double probability = cases/153;
System.out.printf("%.3f", probability);
}
}
일단 처음 문제를 접했을 때 확률 계산하는 부분에서 이해를 잘 못했다. 왜 1 1을 입력했을 때 0.941 확률인지 이해를 하지 못했다. 문제 자체가 제출한 사람도 적어서 참고할만한 것도 마땅하지 않았는데, 질문게시판에서 힌트를 받아서 풀이할 수 있었다. 내가 땡일 때 계산은 정말 쉬운 편인데, 끗일 때 계산이 쉽지 않았다. 사실 아직 이해를 못하는 부분 중에 하나는 이길 확률이라 내가 비길 때도 포함해서 계산했는데 비길 때를 제외해야 값이 나와서 그렇게 제출했다. 비기는 건 지는 게 아니라 넘어가는건가... (흐음) 이 문제를 풀면서 조합을 내가 잘 모르고 있구나를 느껴서 조합 관련 문제도 몇 개 더 풀어봐야겠다라는 걸 느꼈다. 그리고 여러모로 몰랐던 부분이 있었기 때문에 정리하고 가겠다.
remove(int index)
remove() 메소드의 파라미터로 int를 전달하면,
해당 index의 값이 삭제됩니다.
remove(Object o)
remove() 메소드의 파라미터로 Object 객체를 전달하면,
List에서 해당 객체를 찾아서 첫 번째로 나오는 값만 삭제합니다.
값을 삭제하면 true를 리턴하고, 만약 삭제할 값이 없으면 false를 리턴합니다.
만약 list 중에 1을 삭제하고 싶을 경우 어떻게 할까
all_card.remove(Integer.valueOf(card1));
이번 코드에서는 다음과 같이 Integer 객체를 전달했다.
파라미터로 넘겨 준 Collection 객체에 담긴 element를 모두 삭제합니다.
즉, [1, 2, 3, 4, 5, 5] 배열에서 5를 전부 삭제하고 싶을 땐 removeAll을 사용해주면 된다.
List<Integer> all_card = Arrays.asList(1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10);
처음 코드를 작성할 때 다음과 같이 list를 만들어줬다.
Exception in thread "main" java.lang.UnsupportedOperationException
코드를 실행하고 나니 지원하지 않는 연산이라는 에러가 떴다.
이를 찾아보니 asList를 사용할 경우 add/remove를 사용할 수 없다고 한다. List 객체를 생성할 때 요소를 제거 할 수 없는 고정된 목록으로 생성하기 때문이다.
add/remove를 사용하기 위해서는
List<Integer> all_card = new ArrayList<>(Arrays.asList(1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10));
다음과 같이 ArraysList 나 LinkedList 등의 컬렉션 클래스로 한번 Wrapping 해서 사용하면 된다.