Minimal example of fail-soft alpha-beta game tree including a fail-low - minimax

While studying the fail-soft alpha-beta algorithm I'm struggling to come up with a minimal game tree which, when solved with fail-soft alpha-beta produces a fail-low which is different to the minimax value.
For example. Let the initial alpha and beta values be 2 and 4, respectively. Also let's say that the true minimax value of the root node is -2. Furthermore, let's suppose that the fail-soft alpha beta produces 0 for the root node.
Formally:
true_minimax(root_node) = -2
fail_soft(root_node, 2, 4) = 0

true_minimax(root) = 3
fail_soft(root, 6, 8) = 5
enter image description here

Related

Game theory problem involving bitwise XOR [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I participated in a DIV 2 contest on codeforces but was unable to solve this problem.
I understand what the most significant bit means, but the way in which it has been used in the solution confuses me. I just need help with the logic behind the solution.
Any help would be appreciated.
So first, let's understand what actually wins the game.
Since at the end, they are comparing the score, and the one with higher score wins, so the only thing that matter is the most significant bit of each ones' score.
Since the way to gain score is by taking numbers from the given array, so the only thing that matters is the most significant bit of each numbers from the array. Only both player will get the same score from the most significant bit, you would need to test the next bit.
Let x be the number of ones and y be the numbers of zeros in the most significant bit of the numbers:
if x is even, whatever decision players take, both will end with the same score in that bit, so go to the next bit (if it doesn't exist the game ends in a draw). Indeed, the parity of the result of both players will be the same, since x is even.
To make the question simple, I will assume all the numbers contained in the array are either 1 or 0. Imagine you have 4 numbers in the array, [1, 1, 1, 1]. If the both player would have to xor 1 twice. So both of them get (0 xor 1) xor 1 = 0.
In fact, as long the numbers of 1 are even, they would always tie, because both of them will xor same amount of 1. On the other hand, xor 0 doesn't change their score.
So we can get: x mod 2 = 0 gives tie
Now let's think about how player 1 would win or lose. The most simple case, if there's [1, (0)...], or only one 1's, and whatever numbers of 0, player 1 win.
Here we can get if x = 1, p1 wins
Then how can you make player 1 lose? As long there's a 1 in the array, player 1 can take it. So to make him lose, player 1 has to take another 1, and player 2 also need to take a 1. Which means, you would require at least three 1's to make player 1 lose.
Here we can get if x = 3, p1 may lose
But how do you ensure that player 1 will take that extra 1? We have to make sure player 1 is the last player to pick, so he has no choice but to pick it. To do that, we will have even numbers of 0. By doing that, p2 can always copy what p1 has done, except taking that extra 1.
Let's say we had [1, 1, 1, 0, 0]. Then they would be doing:
P1: 1, 0, 1
P2: 1, 0,
 or:
P1: 0, 1, 1
P2: 0, 1,
Now we can get if x = 3, y mod 2 = 0, p1 lose
Now lets see if we can generalize this part, let's say we have x = 5. Now, no matter whay p2 does, p1 can always ensure odd numbers of 1, so he will always win.
Similarly, if we have x = 7, we would have a case just the same as x = 3. If we have even numbers of 0, p2 can always make p1 get even number's of 1.
Now we get:
if x mod 2 = 0, they tie
if x mod 4 = 1, p1 wins and
if x mod 4 = 3, y mod 2 = 1, p1 wins and
if x mod 4 = 3, y mod 2 = 0, p1 lose, which is basically what they had for the solution.

How to find the largest sum with the smallest possible path in a tetrahedron of integers?

First here is the question,
Say that an integer can be represented as a perfect sphere, in which the value of the sphere is equal to the integer it contains. The spheres are organized into a tetrahedral pyramid in which N = the length of the side, N being between 1 and 15. Pick (a possibly empty) subset of sphere's such that their sum of values is maximized. Note that the sphere can hold a negative value so it is not necessarily desirable to pick up every sphere. We do not want to disorganize the pyramid so we cannot take any one sphere without first taking the ones above it.
Input Format:
Line 1: integer N
Line 2: N(N+1)/2+1
Output Format:
Line 1: One integer, the maximum sum of values achievable
Sample Input:
3
5
-2 -7
-3
1 0 8
0 3
2
Sample Output:
8
Here is a sample solution given to my understanding so far:
The best solution is shown as bold in the diagram bellow. It is not smart to take 1 because that would require taking -2, decreasing the total. There for 8, 3, and 2 should be taken because they outweigh -3 and -7.
My question is,
How do I store the input so that I can retain the proper order? Or do i even need to? I am trying to use a queue but my program gets very lengthly because I have to find the sum for each possible path and then compare each sum to find the max. I am also having a lot of difficulty breaking the data up into the right pattern so I don't recount a number or take one out of sequence. Is there a more efficient way to do this? Can Dijkstra's algorithm be of any use in this case? If so, then how? Any help is greatly appreciated!!
I would use a 3-dimensional array. To use your example:
A[0][0][0] = 5
A[1][0][0] = -2
A[1][1][0] = -3
A[1][0][1] = -7
A[2][0][0] = 1
A[2][1][0] = 0
A[2][2][0] = 2
A[2][0][0] = 0
A[2][1][0] = 3
A[2][0][0] = 8
The "above" relationship is simply a matter of index arithmetic: [ia, ja, ka] is above [ia+1, ja, ka], [ia+1, ja+1, ka] and [ia+1, ja, ka+1].

How the double recursion works in C/C++ - for example depth of a binary tree?

Recursion doesn't strike naturally to me. A few programs, which I could understand was Factorial, where factorial of n is n * factorial(n-1). Similarly, fibonacci series - Fn = Fn-1 + Fn-2. Also, a bst- insert, search. All these recursion functions have one thing common - a condition to return the concrete value. Otherwise, it will call itself with a different parameter. Once the concrete value is returned, all the calls are unfolded. However, I am not able to understand the programs where the recursion is one after the other. What happens over there. How can I think on those lines naturally? For example - here is the program -
What is the significance of the following lines?
/* compute the depth of each subtree */
int lDepth = maxDepth(node->left);
int rDepth = maxDepth(node->right);
int maxDepth(struct node* node)
{
if (node==NULL)
return 0;
else
{
/* compute the depth of each subtree */
int lDepth = maxDepth(node->left);
int rDepth = maxDepth(node->right);
/* use the larger one */
if (lDepth > rDepth)
return(lDepth+1);
else return(rDepth+1);
}
}
While searching the tree, the condition that returns a concrete value is if (node==NULL) and the concrete value returned is 0, which is a tree of depth 0. Consider the following tree (from wikipedia)
Starting at node 8, the code will recurse to node 3, and then to node 1. When it tries to recurse to the left child of node 1, it will find NULL and return 0. Then it will try the right child of node 1, which will also return 0. At this point node 1 comes to the if statement
if (lDepth > rDepth)
return(lDepth+1);
else return(rDepth+1);
Since both lDepth and rDepth are 0, node 1 returns 1 to node 3. Then node 3 recurses to node 6, and so on.
Each call to maxDepth(node->left) will result in an immediate call to maxDepth(node->left), until there it nothing left (no pun intended) on the left most side of the tree. Then the last call returns and there will be a call to maxDepth(node->right).
This is a so-called 'depth-first' traversal, in that we go as far up the tree as possible and then visit the leaves on each branch until we're done on the branch and then we back-up to the fork.
Perhaps the best way to understand this code is to draw a picture of a small binary tree, and step through the code to see what will happen.
Mentally, it may help to separate the logic into two parts. If you have a pointer possibly to a node in a singly-linked list, and define the depth of a NULL pointer as being 0, then you can say the depth of any other node is one more than the depth of the node to which it links.
{node3 p_next_->}---->{node2 p_next_->}---->{node1 p_next_=nullptr}
So, the code for this would be:
int depth(Node* p)
{
if (p == NULL) return 0;
return depth(p->p_next_) + 1;
}
Then, your question is about a binary tree... the logic is similar but each time you work out the depth of a node, you're saying "well, this node may have a right and/or a left hierarchy of nodes under it... my depth is one more than the greater of their depths".
Alternatively, it might help to think of a family, say fred has two children sue and max, and so on....
fred
/ \
sue max
/ \
sally charlie
/
june
Here, working out the depth of say sue is a bit like asking "is she a child (depth 1), a parent (depth 2), a grandparent (depth 3), a great-grandparent (depth 4)?"
We can see she's sally's mother (depth 2 on that side), but she's june's grandmother (depth 3) on that side.
We can work out that answer of 3 systematically by saying sue's depth is one more than the deepest of sally and charlie's, and sally's got no kids (their imaginary depth is 0) so she's depth 1 so sue'2 at least 2, but charlie's one more than june who's one more than her imaginarykids (depth 0) i.e. june's 1 so charlie's 2 so sue's actually 3, being more than the count from sally's side.

Finding PostOrder traversal from LevelOrder traversal without constructing the tree

Given a binary tree where value of each internal node is 1 and leaf node is 0. Every internal
node has exactly two children. Now given level order traversal of this tree return postorder
traversal of the same tree.
This question can be easily solved if I construct a tree and then do its postorder traversal. Although it is O(n) time. But is it possible to print postOrder traversal without building up the tree.
It's definitely possible.
Considering it's a Full Binary Tree, once the number of nodes is determined, theoretically, the shape of tree is unique.
Deem the level order traversal as an array, for example, 1 2 3 4 5 6 7.
It represents such tree:
1
2 3
4 5 6 7
What you want to get is the post order traversal: 4 5 2 6 7 3 1.
The first step is calculate how deep the tree was:
depth = ceil(log(2, LevelOrderArray.length)) // =3 for this example
after that, set up a counter = 0, and extract nodes from the bottom level of the original array, one by one:
for(i=0, i<LevelOrderArray.length, i++){
postOrderArray[i] = LevelOrderArray[ 2 ^ (depth-1) +i ] //4,5,....
counter++; //1,2,.....
}
But notice that once the counter can be divided by 2, that means you need to retrieve another node from upper level:
if(counter mod 2^1 == 0)
postOrderArray[i] = LevelOrderArray[ 2 ^ (depth -2) + (++i) ] // =2 here,
//which is the node you need after 4 and 5, and get 3 after 6 and 7 at the 2nd round
Don't ++ the counter here, because the counter represents how many nodes you retrieved from the bottom level.
Every time 2^2 = 4 nodes was pop out, retrieve another node from 3rd level (counting from bottom)
if(counter mod 2^2 == 0)
postOrderArray[i] = LevelOrderArray[ 2 ^ (depth -3) + (++i) ] // =1
Every time 2^3 = 8 nodes was pop out, again, retrieve another node from 4th level
.... until the loop is finished.
It's not strict C++ code, only the concept. If you fully understand the algorithm, the value of tree nodes doesn't matter at all, even though there are all 0 and 1. The point is although you didn't build up the tree in program, but build it up in your mind instead, and convert it into algorithm.

Finding the location of a parent node in a binary tree

So I need help coming up with an expression that will always give me the location of a child's parent node in a binary tree. Here is an example of a problem my teacher will put on our exam:
"Consider a complete binary tree with exactly 10,000 nodes, implemented with an array starting at index 0 . The array is populated in order by extracting elements from the tree one level at a time from left to right. Suppose that a node has its value stored in location 4999. Where is the value stored for this node’s parent?"
My teacher did not tell us how to solve a problem like this. She just said "Draw a binary tree and find a pattern." I did just that but i could not come up with anything! please help. thanks.
The following is entirely using integer division. I.e. fractional remainders are dropped. For any given node index N, the children of that node will always be in locations 2N+1 and 2(N+1) in the same array.
Therefore, The parent of any node N > 0 in such an array will always be at index (N-1)/2.
Parent to Child Examples:
Parent 0: children 1,2
Parent 1: children 3,4
Parent 2: children 5,6
Parent 3: children 7,8
etc...
Child to Parent Examples:
Child 8 : Parent = (8-1)/2 = 7/2 = 3
Child 7 : Parent = (7-1)/2 = 6/2 = 3
Child 6 : Parent = (6-1)/2 = 5/2 = 2
Child 5 : Parent = (5-1)/2 = 4/2 = 2
So for your problem:
(4999-1)/2 = 4998/2 = 2499
Note: remember this, since you'll be using it extensively when you start coding array-based heap-sort algorithms.
Thanks for all your help guys. And I found the answer to my question!
The general algorithm for finding the location of the parent node is:
[i + (root - 1)] / 2 where i is the location of the given node and root is the location of the root. So in the given problem above the root starts at position 0. so the equation to find the parent node of any node is [i + (0 - 1)] / 2 = (i - 1) / 2
Now let's say the root started at position 3, then the equation would be [i + (3 - 1)] / 2
= (i + 2) / 2!!!! This is the algorithm I needed. Most of you helped me solve the one problem i provided but i actually needed the general solution for a binary tree whose root can start at any postions; not just at zero
It seems this is how the array elements map back to tree based on array indices
0
1 2
3 4 5 6
If so, then the parent of index n is at floor( (n - 1) / 2 ) (for n != 0)
If you do the log2 of the number requested (4999) and take the integer part it will give you the closest power of two to the number (12). It is 2^12 = 4096.
The parent of the nodes between 4096 and 2^13 - 1, are the ones between 2^11 and 2^12 - 1. And for each pair of nodes in the first range you have its parent in the second. So you can map them taking the integer part of the half of the difference (4999 - 4096) and adding it to the parent range start (2048).
So you will have floor of 903 / 2, and add it to 2048, getting 2499.
Note that I didn't make a precise calculation, take the strategy of the answer not the results.
You can put this algorithm in a mathematical expression, with a little work.
Hope it helps!
The parent node is at n/2 if n is even.
It is at (n-1)/2 if n is odd.
So you can remember it as math.ceil((n-1)/2)