Simple way to calculate number of chess material combinations - algorithm

In chess, one player can have different material combinations, for example:
"1 queen, 2 rooks, 2 knights, 2 bishops, 8 pawns + the king" is one combination
if the player loses one bishop:
"1 queen, 2 rooks, 2 knights, 1 bishop, 8 pawns + the king" is another combination
..afterwards, if a pawn is promoted to a knight, then:
"1 queen, 2 rooks, 3 knights, 1 bishop, 7 pawns + the king" is another combination
OK, the following combination is not valid:
"5 queens, 5 rooks, 5 knights, 5 bishops, 2 pawns + the king"
since you lack of pawns to promote. (5 queens = 4 pawns needed) (5 rooks = 3 pawns needed) , etc. so 4 + 3 + 3 + 3 = 13 pawns needed. Since 2 pawns on the board, then at most 6 pawns could be promoted. Not valid.
How many valid material combinations are there?
I computed 8694 combinations using the following C code. The question is:
Do you find simpler/efficient algorithm to calculate it? (less cycles, less calculations, clearer code, etc.) ... or even a math formulae??
total = 0;
for (queens=0;queens<=9;queens++)
for (rooks=0;rooks<=10;rooks++)
for (bishops=0;bishops<=10;bishops++)
for (knights=0;knights<=10;knights++)
for (pawns=0;pawns<=8;pawns++)
{
pawnsRequested = 0;
if (queens>1) pawnsRequested += queens - 1;
if (rooks>2) pawnsRequested += rooks - 2;
if (bishops>2) pawnsRequested += bishops - 2;
if (knights>2) pawnsRequested += knights - 2;
if (8-pawns < pawnsRequested) continue;
total++;
}
printf("%i\n",total);

If the piece types were independent, then we could just multiply: 10 possibilities for the queens times 11 possibilities for the rooks times etc. We need to track pawn usage, however. There's a mathematical trick called generating functions where we can encode the possibilities for, e.g., rooks as
3 + x + x^2 + x^3 + x^4 + x^5 + x^6 + x^7 + x^8,
where the power of x denotes the number of pawns used, and the coefficient denotes the number of possibilities. Here, there are three possibilities that require no promoted pawns (0, 1, 2), one that requires one promoted pawn (3), one that requires two promoted pawns (4), etc. Now we can multiply each of the factors together (respectively, queens, rooks, bishops, knights, pawns).
(2 + x + x^2 + x^3 + x^4 + x^5 + x^6 + x^7 + x^8)
* (3 + x + x^2 + x^3 + x^4 + x^5 + x^6 + x^7 + x^8)
* (3 + x + x^2 + x^3 + x^4 + x^5 + x^6 + x^7 + x^8)
* (3 + x + x^2 + x^3 + x^4 + x^5 + x^6 + x^7 + x^8)
* (1 + x + x^2 + x^3 + x^4 + x^5 + x^6 + x^7 + x^8)
Here it is from Wolfram Alpha.
The coefficients of 1 through x^8, which are the number of possibilities for 0 to 8 pawns required, are 54, 135, 261, 443, 693, 1024, 1450, 1986, 2648, summing to 8694.

Related

Set values of a matrix on positions inside a triangle

I have a N x N matrix will all values equal to zero, then I need to get the coordinates of a triangle and set the values inside this triangle to one (1).
How can I determine the position of each element in the matrix that forms the triangle faces?
Like this 10x10 matrix, I have a triangle set at (9,1),(5,5) and (9,5):
0000000000
0000000000
0000000000
0000000000
0000000000
0000010000
0000110000
0001010000
0010010000
0111110000
I don't need the code made for me, I want to check if there is a proper way (maybe using math) to get the "coordinates".
When you have two points x1,y1 and x2,y2, you can use these to create a formula for the line using "point-slope form"
Calculate slope with m = (y1 - y2) / (x1 - x2)
Then you have a formula of y - y1 = m(x - x1)
This further goes to y = m(x - x1) + y1
So in your example of (9,1),(5,5) you calculate the m = (1 - 5) / (9 - 5) = (-4) / (4) = -1
Then your formula becomes, for that line, y = (-1)(x - 9) + 1
Then iterate between 5 and 9.
f(5) = -(5-9) + 1 = -(-4) + 1 = 4 + 1 = 5
f(6) = -(6-9) + 1 = -(-3) + 1 = 3 + 1 = 4
f(7) = -(7-9) + 1 = -(-2) + 1 = 2 + 1 = 3
f(8) = -(8-9) + 1 = -(-1) + 1 = 1 + 1 = 2
f(9) = -(9-9) + 1 = -(0)) + 1 = 0 + 1 = 1
Triangles have nice properties allowing a very simple algorithm to suffice.
Find Ymax, the topmost Y coordinate set in the triangle. Then for Ymax, find Xmin and Xmax, of the left and rightmost pixels set in that row. Now there are 2 cases. If Xmin == Xmax, then one vertex is (Xmin,Ymax), otherwise two of the coordinates are (Xmin, Ymax) and (Xmax, Ymax).
With this you've found the topmost coordinate or coordinates.
It's pretty simple to continue this reasoning to find the other ones. I'll let you puzzle it out for the fun...
You can combine the min and max-finding in the algorithm above with the algorithm that does the filling as required in the second part of the problem.

Finding number representation in different bases

I was recently solving a problem when I encountered this one: APAC Round E Q2
Basically the question asks to find the smallest base (>1) in which if the number (input) is written then the number would only consist of 1s. Like 3 if represented in base 2 would become 1 (consisting of only 1s).
Now, I tried to solve this the brute force way trying out all bases from 2 till the number to find such a base. But the constraints required a more efficient one.
Can anyone provide some help on how to approach this?
Here is one suggestion: A number x that can be represented as all 1s in a base b can be written as x = b^n + b^(n-1) + b^(n-2) + ... + b^1 + 1
If you subtract 1 from this number you end up with a number divisble by b:
b^n + b^(n-1) + b^(n-2) + ... + b^1 which has the representation 111...110. Dividing by b means shifting it right once so the resulting number is now b^(n-1) + b^(n-2) + ... + b^1 or 111...111 with one digit less than before. Now you can repeat the process until you reach 0.
For example 13 which is 111 in base 3:
13 - 1 = 12 --> 110
12 / 3 = 4 --> 11
4 - 1 = 3 --> 10
3 / 3 = 1 --> 1
1 - 1 = 0 --> 0
Done => 13 can be represented as all 1s in base 3
So in order to check if a given number can be written with all 1s in a base b you can check if that number is divisble by b after subtracting 1. If not you can immediately start with the next base.
This is also pretty brute-forcey but it doesn't do any base conversions, only one subtraction, one divisions and one mod operation per iteration.
We can solve this in O( (log2 n)^2 ) complexity by recognizing that the highest power attainable in the sequence would correspond with the smallest base, 2, and using the formula for geometric sum:
1 + r + r^2 + r^3 ... + r^(n-1) = (1 - r^n) / (1 - r)
Renaming the variables, we get:
n = (1 - base^power) / (1 - base)
Now we only need to check power's from (floor(log2 n) + 1) down to 2, and for each given power, use a binary search for the base. For example:
n = 13:
p = floor(log2 13) + 1 = 4:
Binary search for base:
(1 - 13^4) / (1 - 13) = 2380
...
No match for power = 4.
Try power = 3:
(1 - 13^3) / (1 - 13) = 183
(1 - 6^3) / (1 - 6) = 43
(1 - 3^3) / (1 - 3) = 13 # match
For n around 10^18 we may need up to (floor(log2 (10^18)) + 1)^2 = 3600 iterations.

How to compute the remainder of a very large number (string with 1 mi digits) in the division by 1500

I'm wondering if there is a trick with number theory to compute this remainder without need to implement a BigInt division algorithm.
Haha, it's easy!
I can iterate over all digits, adding each parcel...
Using the properties:
1) (a+b) mod c = (a mod c + b mod c) mod c
2) (a*b) mod c = (a mod c * b mod c) mod c
The power of ten can be increased mod 1500 each step.
Its simple, just check these three things:
Divisibility by 1500
it has to be divisible by 100 (last two digits must be 00)
it has to be divisible by 5 (third digit from right has to be 0 or 5)
it has to be divisible by 3 (iterate over all digits, sum them, and the result has to be divisible by 3)
And if you want to know the remainder, its again simple:
Check for divisible by 5 and get remainder
get remainder from last 4 digits after division by 500, it will be from 0 to 499.
Check for divisible by 3 and get remainder
iterate over all digits, sum them, and get remainder from that after division by 3, it will be from 0 to 2.
and depending from this remainder increase the remainder from 1st step by this remainder multiplied by 500.
Example 1
1234567890 % 1500 = 390
7890 % 500 = 390
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 0 = 45 and 45 % 3 = 0, so nothing has to be added to 390 and the result is then 390.
Example 2
12345678901 % 1500 = 901
8901 % 500 = 401
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 0 + 1 = 46 and 46 % 3 = 1, so we have to add 1 * 500 to the result from 1st step, so 401 + 1 * 500 = 901.
Example 3
1357913579 % 1500 = 1079
3579 % 500 = 79
1 + 3 + 5 + 7 + 9 + 1 + 3 + 5 + 7 + 9 = 50 and 50 % 3 = 2, so we have to add 2 * 500 to the result from 1st step, so 79 + 2 * 500 = 1079.
Hope this helps you.

In Mathematica, how can I cut off the high-order terms in a polynomial?

For example, I have a polynomial y=a_0+a_1 x + ..... + a_50 x^50. Since I know that the high-order terms are imposing negligible effects on the evaluation of y, I want to cut off them and have something like y=a_0+a_1 x + ..... + a_10 x^10, the first eleven terms. How can I realize this?
I thank you all in advance.
In[1]:= y = a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4;
y /. x^b_ /; b >= 3 -> 0
Out[2]= a0 + a1 x + a2 x^2
The mathematically proper approach..
Series[ a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4, {x, 0, 2}] // Normal
-> a0 + a1 x + a2 x^2
If your polynomial is actually as simple as shown, with a term for every power of x and none others, you can simply use Take or Part to extract only those terms that you want because of the automatic ordering (in Plus) that Mathematica uses. For example:
exp1 = Expand[(1 + x)^9]
Take[exp1, 5]
1 + 9 x + 36 x^2 + 84 x^3 + 126 x^4 + 126 x^5 + 84 x^6 + 36 x^7 + 9 x^8 + x^9
1 + 9 x + 36 x^2 + 84 x^3 + 126 x^4
If it is not you will need something else. Bill's replacement rule is one concise and efficient method. For more complex manipulations you may wish to decompose the polynomial using CoefficientArrays, CoefficientRules, or CoefficientList.
There is a shortcut to the previous answers which is even more symbolic. You write, say,
y[x_] = a0 + a1 x + a2 x^2 + a3 x^3 + a4 x^4 + a5 x^5;
y[x] + O[x]^3
which gives you,
a0 + a1 x + a2 x^2 + O[x]^3

number of ways of distribution

if we have n different things and we need to distribute them among m different people then how many ways can we do it such that for each of the m persons there is conditions that:
person 1 can have at least a things and at most b things
person 2 can have at least c things and at most d things
.. and so on ?
e.g if n = 5 and m =3 and the conditions are:
person 1 can receive at least 0 and at most 1 gift
person 2 can receive at least 1 and at most 3 gift
person 3 can receive at least 1 and at most 4 gift
then the number of ways of distributing these 5 gifts is 6((0 1 4), (0 2 3), (0 3 2), (1 1 3), (1 2 2), (1 3 1)).
One way i believe is to iterate through all possible combinations for each range and see which ones sum upto n , but can't think of an efficient algorithm.
Thanks
You probably want to use a generating function approach. Represent the number of objects that person i gets by the exponents of x. This means that if person i can have at least 3 and at most 7 things, this corresponds to the term
x^3 + x^4 + x^5 + x^6 + x^7
Remember to think of + as OR and * as AND. If we want to impose conditions and person 1 and person 2, then multiply their functions together. For example, with person 1 having between 3 and 7 things, and say person 2 has at least 5 things, and add a third person with at most 10 things. Then we get:
(x^3 + x^4 + x^5 + x^6 + x^7) * (x^5 + x^6 + ... ) * (1 + x + x^2 + ... + x^10)
which can also be written as
(x^3 + x^4 + x^5 + x^6 + x^7) * ( x^5/(1+x) ) * (1 + x + x^2 + ... + x^10)
The way to get information back from this is the following. The coefficient of x^M in the expansion of these terms gives the number of ways to distribute a total of M things among all the people subject to the given constraints.
You can work this out from the formulas, or write a program to extract the coefficient, but the idea is to use generating functions as a convenient and efficient way to encode the constraints along with the answer.

Resources