A Naive Shedding Card Game
Given a simple version of a shedding type card game (which is actually a naive version of Dou Di Zhu(https://en.wikipedia.org/wiki/Dou_dizhu), the most popular game in china), how can we determine the winner (each player can have up to 20 cards) (is there exists a linear algorithm to solve the problem)?
The object of the game is to get rid of all cards on hand before the opponent. The players are called A and B. The card ranks are:
3 < 4 < 5 < 6 < 7 < 8 < 9 < T < J < Q < k < A < 2 < r < R (where T is 10, r, R is small and big joker)
Definition1: Player who can discard any card compile with the Give-Out-Rule is called FirstDiscard player, while player who can only discard a card that has a higher rank then previous discarded card is called BeatDiscard player.
A is the first player to discard a card, so A is always a FirstDiscard player at the beginning. If one choose not to discard a card (because he chooses not to discard or he can not find a valid card to discard), then another become FirstDiscard player.
Give out Rule1: Each player can discard a single card at most, Even if you have multiple cards that is the same rank, you can only discard only one of them.
Example1: B winner 4,4,5 < B: 3,4,4,8,T
Explain: B is always the winner, because for any strategy A can possible choose to
play, B can always find a strategy to discard card that leads to winning of B.
Example2: A winner 4,4,5,R > B: 3,4,4,8,T
Explain: A is always the winner, because there exists a strategy A can choose to use that leads to winning of A regardless of strategies B choose to react.
The red and blue indicate the state(the cards left in hand) of A and
B.
The polygon and box shape indicate the player is at FirstDiscard
player state and BeatDiscard player state.
A Relative Graph of tow card sets(A: 4,4,5,R > B: 3,4,4,8,T)
The Bp value of each card indicates how may opponent's card that this card can be used to beat.
Cards with the same Bp value form a block.
The research progress
For now, I can only use the game search tree methods to determine the winner, but the methods takes too long time to process. Give out Rule1 is Actually the first step of my research, the following research give out rule is:
Definition2: solo-card is defined as card with a specific rank whose count is one. while pair-card, trio-card, four-card are defined as card with a specific rank whose count is two, three, four.
Definition3: solo-card, pair-card, trio-card, four-card are also called independent-card
Give out Rule2: Each player can only discard a kind of independent-card each time, if player is at BeatDiscard player state, he can only discard the same kind of independent-card of previous discarded cards with a higher rank.
SplitCard is not allowed. (if you have a trio-card 555, you can not split the card to be a solo-card 5 and a pair-card 55)
Give out Rule3: The same as Give out Rule2 except SplitCard is allowed.
Definition4: trio-card with a solo-card is called trio-solo-kicker-card, the rank is the same of trio-card.
Definition5: trio-card with a pair-card is called trio-pair-kicker-card, the rank is the same of trio-card.
Definition6: four-card with two solo-card is called four-2-solo-kicker-card, the rank is the same of four-card.
Definition7: four-card with two pair-card is called four-2-pair-kicker-card, the rank is the same of four-card.
Give out Rule4: The same as Give out Rule3 and four additional card types (from Def4 ~ Def7) are allowed to discard.
Definition8: four-card is also called bomb-card, it can be used to beat all other card type and four-card with a lower rank (6666 can beat 33, 5555, 3331, 8888KJ)
Definition9: rocket-card is a combination of r and R, it can beat all other card type.
Give out Rule5: The same as Give out Rule4 and tow additional card types (from Def8 ~ Def9) are allowed to discard.
Give out Rule6: Player C is added as a teammate of B, he will discard card following B, either B or C discards all hand cards first will be winner of B and C.
I believe there exists an linear algorithm for Give out Rule1 ~ Rule3, someone can provide such a method and related informations, or prove that the problem is exponential.
Related
I have a task where I need to guess the number in range. For example, lets say n is in range of 1 … 10^8, what is the most efficient algorithm to guess the number?
Let's look at the guessing game as an example to use the Divide and Conquer Algorithm by halfing our possible number of guesses. To play the guessing, a person (player A) will choose a random numer from n to m, another person (player B) will have to guess player A's number in "x" turns. Player A will assist player B by telling player B if the number they guessed is higher than or lower than player A's randomly chosen number. The Divide and Conquer Algoritm will tell you if it is possible to guess player A's number in the given amount of turns x, and will tell the maximum amount of tries or guesses you will need in order to guess there number correctly.
using Divide and Conquer Algorithm:
Let's look at the guessing game example from before, but this time we will use the Divide and Conquer Algorithm to solve it
Player A: I am thinking of a number from 1 to 100, can you guess my number within 6 turns ?
Player B: Sure and in 6 turns or less, is your number 100/2 = 50 ?
Player A: Nope guess a higher number.
Player B: Okay, is your number (100 + 50) / 2 = 75 ?
Player A: Nope, guess a higher number.
Player B: Okay is your number round up (100 +75)/2 = 88?
Player A: Yes, congratulations you guessed my number in 3 turns you
win!
So I am doing a program on Hackerrank.
The problem is
You have been asked to help study the population of birds migrating across the continent. Each type of bird you are interested in will be identified by an integer value. Each time a particular kind of bird is spotted, its id number will be added to your array of sightings. You would like to be able to find out which type of bird is most common given a list of sightings. Your task is to print the type number of that bird and if two or more types of birds are equally common, choose the type with the smallest ID number.
For example, assume your bird sightings are of types . There are two each of types and , and one sighting of type . Pick the lower of the two types seen twice: type .
Function Description
Complete the migratoryBirds function in the editor below. It should return the lowest type number of the most frequently sighted bird.
migratoryBirds has the following parameter(s):
arr: an array of integers representing types of birds sighted
Input Format
The first line contains an integer denoting , the number of birds sighted and reported in the array .
The second line describes as space-separated integers representing the type numbers of each bird sighted.
Constraints
It is guaranteed that each type is , , , , or .
Output Format
Print the type number of the most common bird; if two or more types of birds are equally common, choose the type with the smallest ID number.
This is my code. It is passing all but one of the test cases. Can you help?
x = []
for i in range (0,len(arr)):
x.append(arr.count(arr[i]))
for i in range(0,len(x)):
if x[i] == max(x):
out = i
return out
I don't see that your code passes any test cases, even with the indentation fixed. Your input size can be as large as 105, so that pretty much eliminates any O(n2) solutions that require traversing the entire list, which is unnecessary. The culprit here is arr.count(), which traverses the entire list for every element. You probably meant to traverse the list for every bird type, which results in 5 traversals of the input list:
x = []
for i in range(1, 6):
x.append(arr.count(i))
out = 0
best = x[0]
for i in range(len(x)):
if x[i] > best:
best = x[i]
out = i
return out + 1
The important restriction to note in this problem is that there are only 5 bird types (numbered 1-5), so we can initialize a counts array of length 6 with a dummy element at position 0 so indices map to counts neatly. Then, we can iterate through our input bird type list in one pass, updating our counter array. Lastly, take the max index of the counter array. The "smallest id for ties" restriction is automatically handled by the way max() works--it'll take the smallest index automatically. Here's the code:
counts = [-1, 0, 0, 0, 0, 0]
for bird in arr:
counts[bird] += 1
return counts.index(max(counts))
Note that the variable names are descriptive. This helps ensure that the purpose of each variable is clear and reduces bugs and erroneous assumptions about the program state.
I recently came through an interesting coding problem, which is as follows:
There are n boxes, let us assume this is an array of n boxes.
For each index i of this array, three values are given -
1.) Weight(i)
2.) Left(i)
3.) Right(i)
left(i) means - if weight[i] is chosen, we are not allowed to choose left[i] elements from the left of this ith element.
Similarly, right[i] means if arr[i] is chosen, we are not allowed to choose right[i] elements from the right of it.
Example :
Weight[2] = 5
Left[2] = 1
Right[2] = 3
Then, if I pick element at position 2, I get weight of 5 units. But, I cannot pick elements at position {1} (due to left constraint). And cannot pick elements at position {3,4,5} (due to right constraint).
Objective - We need to calculate the maximum sum of the weights we can pick.
Sample Test Case :-
**Input: **
5
2 0 3
4 0 0
3 2 0
7 2 1
9 2 0
**Output: **
13
Note - First column is weights, Second column is left constraints, Third column is right constraints
I used Dynamic Programming approach(similar to Longest Increasing Subsequence) to reach a O(n^2) solution. But, not able to think of a O(n*logn) solution. (n can be up to 10^5.)
I also tried to use priority queue, in which elements with lower value of (right[i] + i) are given higher priority(assigned higher priority to element with lower value of "i", in case primary key value is equal). But, it is also giving timeout error.
Any other approach for this? or any optimization in priority queue method? I can post both of my codes if needed.
Thanks.
One approach is to use a binary indexed tree to create a data structure that makes it easy to do two operations in O(logn) time each:
Insert number into an array
Find maximum in a given range
We will use this data structure to hold the maximum weight that can be achieved by selecting box i along with an optimal selection of boxes to the left.
The key is that we will only insert values into this data structure when we reach a point where the right constraint has been met.
To find the best value for box i, we need to find the maximum value in the data structure for all points up to location i-left[i], which can be done in O(logn).
The final algorithm is to loop over i=0..n-1 and for each i:
Compute result for box i by finding maximum in range 0..(i-left[i])
Schedule the result to be added when we reach location i+right[i]
Add any previously scheduled results into our data structure
The final result is the maximum value in the whole data structure.
Overall, the complexity is o(nlogn) because each value of i results in one lookup and one update operation.
I was wondering if anyone could help me go through this question. I looked up the Min Max theory, but I still don't know how to apply this concept to this question below.
The following tree represents possible moves in a competitive game, showing that player X currently has a choice between move A and move B.
Following the move of player X, player Y is allowed to select a move, and then player X is allowed to select the last move of the game.
The leaf nodes of the tree are labeled W, L, or T, depending on whether that ending represents a win, loss, or tie for player X.
Use the min-max search to determine if player X should move A or B to obtain the best result X can expect.
To review min-max search, see http://www.nada.kth.se/kurser/kth/2D1350/progp02/lecture2.pdf
Player X should move A.
Player X should move B.
I added numbers for the nodes, and highlighted the "max" rows. The non-highlighted rows are "min" rows (i.e., the player wants to minimize the result). Obviously an L is the lowest value, and a W is the highest value. We usually assign a 1 to a win, a -1 to a loss, and a 0 to a tie. Player Y wants to make the number as low as possible (they win if the player X gets an L). Player X wants to make the number as high as possible (he wants a W).
If the game plays out to node 4, you know that player X will win no matter what. Therefore, 4 is marked W (or 1). If the game plays out to node 5, you know that he loses, so it's marked L. Same happens for 6 (which gets a W).
To assign to node 2, we note that 2 is on a "min" row (it's player Y's turn). 4, 5, 6, have W, L, W, respectively. Player Y can minimize this by choosing node 5, therefore winning. Therefore, Player X knows that if Player Y is intelligent, Player X will lose if he chooses A.
We can do the same thing on the other side to show that if Player X chooses B, he will tie. Therefore, Player X should choose B.
When code is written for minimax, the code does a post-order tree traversal and assigns values to the nodes as it goes by looking at the descendants.
I recently read this question regarding information gain and entropy. I think I have a semi-decent grasp on the main idea, but I'm curious as what to do with situations such as follows:
If we have a bag of 7 coins, 1 of which is heavier than the others, and 1 of which is lighter than the others, and we know the heavier coin + the lighter coin is the same as 2 normal coins, what is the information gain associated with picking two random coins and weighing them against each other?
Our goal here is to identify the two odd coins. I've been thinking this problem over for a while, and can't frame it correctly in a decision tree, or any other way for that matter. Any help?
EDIT: I understand the formula for entropy and the formula for information gain. What I don't understand is how to frame this problem in a decision tree format.
EDIT 2: Here is where I'm at so far:
Assuming we pick two coins and they both end up weighing the same, we can assume our new chances of picking H+L come out to 1/5 * 1/4 = 1/20 , easy enough.
Assuming we pick two coins and the left side is heavier. There are three different cases where this can occur:
HM: Which gives us 1/2 chance of picking H and a 1/4 chance of picking L: 1/8
HL: 1/2 chance of picking high, 1/1 chance of picking low: 1/1
ML: 1/2 chance of picking low, 1/4 chance of picking high: 1/8
However, the odds of us picking HM are 1/7 * 5/6 which is 5/42
The odds of us picking HL are 1/7 * 1/6 which is 1/42
And the odds of us picking ML are 1/7 * 5/6 which is 5/42
If we weight the overall probabilities with these odds, we are given:
(1/8) * (5/42) + (1/1) * (1/42) + (1/8) * (5/42) = 3/56.
The same holds true for option B.
option A = 3/56
option B = 3/56
option C = 1/20
However, option C should be weighted heavier because there is a 5/7 * 4/6 chance to pick two mediums. So I'm assuming from here I weight THOSE odds.
I am pretty sure I've messed up somewhere along the way, but I think I'm on the right path!
EDIT 3: More stuff.
Assuming the scale is unbalanced, the odds are (10/11) that only one of the coins is the H or L coin, and (1/11) that both coins are H/L
Therefore we can conclude:
(10 / 11) * (1/2 * 1/5) and
(1 / 11) * (1/2)
EDIT 4: Going to go ahead and say that it is a total 4/42 increase.
You can construct a decision tree from information-gain considerations, but that's not the question you posted, which is only the compute the information gain (presumably the expected information gain;-) from one "information extraction move" -- picking two random coins and weighing them against each other. To construct the decision tree, you need to know what moves are affordable from the initial state (presumably the general rule is: you can pick two sets of N coins, N < 4, and weigh them against each other -- and that's the only kind of move, parametric over N), the expected information gain from each, and that gives you the first leg of the decision tree (the move with highest expected information gain); then you do the same process for each of the possible results of that move, and so on down.
So do you need help to compute that expected information gain for each of the three allowable values of N, only for N==1, or can you try doing it yourself? If the third possibility obtains, then that would maximize the amount of learning you get from the exercise -- which after all IS the key purpose of homework. So why don't you try, edit your answer to show you how you proceeded and what you got, and we'll be happy to confirm you got it right, or try and help correct any misunderstanding your procedure might reveal!
Edit: trying to give some hints rather than serving the OP the ready-cooked solution on a platter;-). Call the coins H (for heavy), L (for light), and M (for medium -- five of those). When you pick 2 coins at random you can get (out of 7 * 6 == 42 possibilities including order) HL, LH (one each), HM, MH, LM, ML (5 each), MM (5 * 4 == 20 cases) -- 2 plus 20 plus 20 is 42, check. In the weighting you get 3 possible results, call them A (left heavier), B (right heavier), C (equal weight). HL, HM, and ML, 11 cases, will be A; LH, MH, and LM, 11 cases, will be B; MM, 20 cases, will be C. So A and B aren't really distinguishable (which one is left, which one is right, is basically arbitrary!), so we have 22 cases where the weight will be different, 20 where they will be equal -- it's a good sign that the cases giving each results are in pretty close numbers!
So now consider how many (equiprobable) possibilities existed a priori, how many a posteriori, for each of the experiment's results. You're tasked to pick the H and L choice. If you did it at random before the experiment, what would be you chances? 1 in 7 for the random pick of the H; given that succeeds 1 in 6 for the pick of the L -- overall 1 in 42.
After the experiment, how are you doing? If C, you can rule out those two coins and you're left with a mystery H, a mystery L, and three Ms -- so if you picked at random you'd have 1 in 5 to pick H, if successful 1 in 4 to pick L, overall 1 in 20 -- your success chances have slightly more than doubled. It's trickier to see "what next" for the A (and equivalently B) cases because they're several, as listed above (and, less obviously, not equiprobable...), but obviously you won't pick the known-lighter coin for H (and viceversa) and if you pick one of the 5 unweighed coins for H (or L) only one of the weighed coins is a candidate for the other role (L or H respectively). Ignoring for simplicity the "non equiprobable" issue (which is really kind of tricky) can you compute what your chances of guessing (with a random pick not inconsistent with the experiment's result) would be...?