import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
public class Main {
public static void main(String[] args) {
/*
Change the values for the first 3 variables, which are your servant's deck,
the number of cards in the pool and the card combination you need
*/
String servant_deck = "bbaaq";
int cards_pool = 15;
String hand_combination = "ba";
int buster_deck = 0;
int arts_deck = 0;
int quick_deck = 0;
int buster_hand = 0;
int arts_hand = 0;
int quick_hand = 0;
char[] deck_array = servant_deck.toLowerCase().toCharArray();
Arrays.sort(deck_array);
for (int i = 0; i < deck_array.length; i++) {
switch (deck_array[i]) {
case 'b':
buster_deck++;
break;
case 'a':
arts_deck++;
break;
case 'q':
quick_deck++;
break;
}
}
char[] hand_combination_array = hand_combination.toLowerCase().toCharArray();
for (int i = 0; i < hand_combination_array.length; i++) {
switch (hand_combination_array[i]) {
case 'b':
buster_hand++;
break;
case 'a':
arts_hand++;
break;
case 'q':
quick_hand++;
break;
}
}
int cards_remaining = Math.max(cards_pool - 5, 5);
int hand = hand_combination_array.length;
float max_combinations = factorial(cards_pool) / (factorial(cards_pool - 5) * factorial(5));
float buster_combinations = factorial(buster_deck) / (factorial(buster_deck - buster_hand) * factorial(buster_hand));
float arts_combinations = factorial(arts_deck) / (factorial(arts_deck - arts_hand) * factorial(arts_hand));
float quick_combinations = factorial(quick_deck) / (factorial(quick_deck - quick_hand) * factorial(quick_hand));
float draw_combinations = buster_combinations * arts_combinations * quick_combinations * (float) (factorial(cards_remaining) / (factorial(cards_remaining - 5 + hand) * factorial(5 - hand))) / max_combinations;
System.out.println("ONLY " + hand_combination.toUpperCase() + " out of a " + servant_deck.toUpperCase() + " deck: ");
System.out.println(draw_combinations * 100 + "%");
//removing different cards
StringBuilder deck_no_diffs = new StringBuilder();
boolean[] present_in_target = new boolean[256];
for (char c : hand_combination.toCharArray()) {
present_in_target[c] = true;
}
for (char c : deck_array) {
if (present_in_target[c]) {
deck_no_diffs.append(c);
}
}
//removing duplicates
List<Character> deck_list = new ArrayList<>();
for (char c : deck_no_diffs.toString().toCharArray()) {
deck_list.add(c);
}
for (int i = 0; i < hand_combination_array.length; i++) {
for (int j = 0; j < deck_list.size(); j++)
if (deck_list.get(j) == hand_combination_array[i]) {
deck_list.remove(j);
break;
}
}
HashSet<String> combinations = new HashSet<>();
for (int i = 0; i < deck_list.size(); i++) {
combinations.add("" + deck_list.get(i) + hand_combination);
}
String comb_deck = "";
for (int i = 0; i < deck_list.size(); i++) {
comb_deck += deck_list.get(i);
}
combinations.add(comb_deck + hand_combination);
combinations.add(hand_combination);
System.out.println("AT LEAST " + hand_combination.toUpperCase() + " out of a " + servant_deck.toUpperCase() + " deck: ");
System.out.println(hypergeometricCalculation(combinations, deck_array, cards_pool) * 100 + "%");
}
public static long factorial(int n) {
long fact = 1;
for (int i = 2; i <= n; i++) {
fact = fact * i;
}
return fact;
}
public static char[] removeCards(char arr[]) {
Arrays.sort(arr);
char[] temp = new char[arr.length];
int j = 0;
for (int i = 0; i < arr.length - 1; i++)
if (arr[i] != arr[i + 1])
temp[j++] = arr[i];
temp[j++] = arr[arr.length - 1];
return temp;
}
public static float hypergeometricCalculation(HashSet<String> set, char[] deck_array, int cards_pool) {
int buster_deck;
int arts_deck;
int quick_deck;
int buster_hand;
int arts_hand;
int quick_hand;
float total = 0;
List<String> combinations = new ArrayList<>();
combinations.addAll(set);
for (int i = 0; i < combinations.size(); i++) {
buster_deck = 0;
arts_deck = 0;
quick_deck = 0;
buster_hand = 0;
arts_hand = 0;
quick_hand = 0;
int cards_remaining = Math.max(cards_pool, 5);
for (int j = 0; j < deck_array.length; j++) {
switch (deck_array[j]) {
case 'b':
buster_deck++;
break;
case 'a':
arts_deck++;
break;
case 'q':
quick_deck++;
break;
}
}
char[] hand_combination_array = combinations.get(i).toLowerCase().toCharArray();
Arrays.sort(hand_combination_array);
for (int j = 0; j < hand_combination_array.length; j++) {
switch (hand_combination_array[j]) {
case 'b':
buster_hand++;
break;
case 'a':
arts_hand++;
break;
case 'q':
quick_hand++;
break;
}
}
for (char j : removeCards(hand_combination_array)) {
switch (j) {
case 'b':
cards_remaining -= buster_deck;
break;
case 'a':
cards_remaining -= arts_deck;
break;
case 'q':
cards_remaining -= quick_deck;
break;
}
}
int hand = hand_combination_array.length;
float max_combinations = factorial(cards_pool) / (factorial(cards_pool - 5) * factorial(5));
float buster_combinations = factorial(buster_deck) / (factorial(buster_deck - buster_hand) * factorial(buster_hand));
float arts_combinations = factorial(arts_deck) / (factorial(arts_deck - arts_hand) * factorial(arts_hand));
float quick_combinations = factorial(quick_deck) / (factorial(quick_deck - quick_hand) * factorial(quick_hand));
float draw_combinations = (buster_combinations * arts_combinations * quick_combinations * (float) (factorial(cards_remaining) / (factorial(cards_remaining - 5 + hand) * factorial(5 - hand))) / max_combinations);
total = total + draw_combinations;
}
return total;
}
}