How many bombs can your landlord take?

Keywords: Attribute P4 less

Recently, I'm bored. I want to know how likely I can get a bomb if I play with the landlord (four cards of the same number or a king of the same size). But I was not good at probability, so I thought of using statistics to try. I wrote a program to simulate the licensing process of the landlord.

Object-Oriented Card

Firstly, according to OOP, I regard cards as an object. Points and colors are its attributes. In order to deal with King and King, Type attributes are added.

public class Card {
    Suit suit;
    Size size;
    Type type;

    Card(Suit suit, Size size) {
        this.suit = suit;
        this.size = size;
        this.type = Type.Ordinary;
    }

    Card(Type type) {
        if (type.equals(Type.Ordinary)) {
            throw new RuntimeException("illegal parameter");
        }
        this.type = type;
    }
}

I use enumeration classes to represent all three attributes, purely because it's object-oriented, so it's pure.

public enum Size {
    P3(0), P4(1), P5(2), P6(3), P7(4), P8(5), P9(6),
    P10(7), J(8), Q(9), K(10), A(11), P2(12);

    int sequence;

    Size(int sequence) {
        this.sequence =  sequence;
    }
}

Size represents the size of points, sorted from small to large. The purpose of adding sequence attribute is to facilitate processing in statistics.

public enum Suit {
    Spade(4), Heart(3), Club(2), Diamond(1);

    // weight
    int weight;

    Suit(int weight) {
        this.weight = weight;
    }
}

Suit colors, adding weight attribute as the size weight, the landlord colors regardless of size, but some cards will distinguish, so add it casually.

public enum Type {
    Ordinary(0), LITTLE_JOKER(1), BIG_JOKER(2);

    int weight;

    Type(int weight) {
        this.weight = weight;
    }
}

Type card type, mainly for special treatment of Wang Xiaowang, according to the weight value, Wang Xiaowang is smaller than Wang Dawang.~

Computation process

First, I abstract several steps of playing cards. The first step is to take out a deck of cards; the second step is to shuffle cards (randomly disturbed); the third step is to deal cards; the fourth step is to calculate whether there are bombs or not; I simplify the method of dealing cards and put it into the main program. The other steps are as follows.

/**
     * Generate an ordered array of cards
     */
    static Card[] newCards() {
        // Arrays of cards are represented by arrays
        Card[] cards = new Card[54];
        // Cursor i
        int i = 0;
        // 13 sizes* 4 colors = 52
        for (Size point : Size.values()) {
            for (Suit suit : Suit.values()) {
                cards[i++] = new Card(suit, point);
            }
        }
        // Insert King and King
        cards[52] = new Card(Type.LITTLE_JOKER);
        cards[53] = new Card(Type.BIG_JOKER);
        return cards;
    }

    /**
     * Shuffle the cards
     * @param cards Disrupted decks
     */
    static Card[] shuffle(Card[] cards) {
        Random random = new Random();
        int len = cards.length;
        // Complex O(n)
        // Traverse a deck of cards, each cycle randomly take a card behind the current card (including the current card) and exchange with the current card
        // In a completely random situation, the probability of each card in each position should be the same, there are n!
        for (int i = 0;i < len; i++) {
            int r = random.nextInt(len - i);
            change(i, r + i, cards);
        }
        return cards;
    }

    // Simple Interactive Location Method
    static void change(int a, int b, Card[] cards) {
        Card temp = cards[a];
        cards[a] = cards[b];
        cards[b] = temp;
    }
    
    static final int DOUBLE_JOKER = 3;
    static final int FULL_SUIT = 10;
    /**
     * Judge whether there is a bomb or not
     * @param cards Card group
     * @return true Bomb-free false
     */
    static boolean hasBoom(Card[] cards) {
        // Construct an array equal in length to the number of Size whose initial value is 0
        int[] counter = new int[Size.values().length]; //Initialization is 0
        // Special Processing King and King
        int weightOfJoker = 0;
        for (Card card: cards) {
            // Special Processing King and King
            if (!card.type.equals(Type.Ordinary)) {
                weightOfJoker += card.type.weight;
                // The sum of the weights of the king and the king is 3:00, that is Wang Bo.
                if (weightOfJoker == DOUBLE_JOKER) {
                    return true;
                }
                continue;
            }
            // Four cards are made up by using the sequence value of points as subscripts, plus the weight value, and the sum of points as 10.
            counter[card.size.sequence] += card.suit.weight;
            if (counter[card.size.sequence] == FULL_SUIT) {
                return true;
            }
        }
        return false;
    }

How many probabilities do the landlords and farmers have?

public static void main(String[] args) {
        long gameStart = System.currentTimeMillis();
        int gameTime = 100000;
        // Farmer's 17 Card Counter
        int nongHasBoom = 0;
        // Landlord 20 Card Counter
        int diHasBoom = 0;
        // Running games
        for (int i = 0;i < gameTime; i++) {
            // Get a new deck of cards
            Card[] poker = newCards();
            // Shuffle the cards
            poker = shuffle(poker);
            // Licensing in random circumstances, continuous distribution and development theory does not affect the probability of your card, simplification
            Card[] nong = Arrays.copyOf(poker, 17);
            Card[] di = Arrays.copyOfRange(poker, 17, 17 + 20);
            nongHasBoom += hasBoom(nong)? 1 : 0;
            diHasBoom += hasBoom(di)? 1 : 0;
        }
        long gameEnd = System.currentTimeMillis();
        System.out.println(String.format("Landlord Bomb Probability %f , Farmer Bomb Probability %f", diHasBoom * 1.0 / gameTime, nongHasBoom * 0.1 / gameTime));
        System.out.println(String.format("Runtime %f s", (gameEnd - gameStart)/1000.0));
    }

Running a program, found that the speed is still very fast, anyway, 100,000 times less than half a second, running only to find that the landlord three cards on the probability of carrying bombs is so great, can increase the probability of nearly double. Of course, I write the program casually, there may be inaccurate data errors, if found, please correct. Secondly, I stole some laziness in enumeration writing rules, not all capitals.~

The landlord bomb probability is 0.302310 and the peasant bomb probability is 0.186460.
Runtime 0.217000s

Posted by teejayuu on Sat, 18 May 2019 10:27:41 -0700