Sunday 23 June 2019

Project Euler 154 - Exploring Pascal's pyramid

A triangular pyramid is constructed using spherical balls so that each ball rests on exactly three balls of the next lower level.
Then, we calculate the number of paths leading from the apex to each position:
A path starts at the apex and progresses downwards to any of the three spheres directly below the current position.
Consequently, the number of paths to reach a certain position is the sum of the numbers immediately above it (depending on the position, there are up to three numbers above it).
The result is Pascal's pyramid and the numbers at each level n are the coefficients of the trinomial expansion (x + y + z)n.
How many coefficients in the expansion of (x + y + z)200000 are multiples of 1012?

Solution

I have spent a week to solve this problem.

First step is observe the pattern



Now we can see the for any given level l, any row m (starting 0), any column n (starting 0), the value is Clm * Cmn

Due to the symmetry, there is no need to go through the entire a triangle. Only going through the red ones is sufficient.


To illustrate the idea, considering peeling an onion, we take off the outermost layer of the triangle, what is left is:


Then again take off the outermost layer, what is left is:


The complexity of the algorithm is O(n^2), which runs 19 minutes on my iMac. I struggle to make it run any faster. 

Thursday 6 June 2019

Project Euler 152 - Writing 1/2 as a sum of inverse squares

There are several ways to write the number 1/2 as a sum of inverse squares using distinct integers.
For instance, the numbers {2,3,4,5,7,12,15,20,28,35} can be used:


In fact, only using integers between 2 and 45 inclusive, there are exactly three ways to do it, the remaining two being: {2,3,4,6,7,9,10,20,28,35,36,45} and {2,3,4,6,7,9,12,15,28,30,35,36,45}.
How many ways are there to write the number 1/2 as a sum of inverse squares using distinct integers between 2 and 80 inclusive?


Solution

Wow, this one is tough. I spent more than 6 hours to solve it.

Upon observing the outcome of a very naive (and hence very slow) algorithm, it can be found that only a portion of numbers in the range of [2, 80] can be candidates that form the solution, namely

CANDIDATES = [2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 18, 20, 21, 24, 28, 30, 35, 36, 39, 40, 42, 45, 52, 56, 60, 63, 70, 72]

I don't know how to prove it, so I just hope it's the correct set of candidates.

My algorithm is very intuitive and requires no advanced mathematics knowledge.

First define S([a1, a2, a3, ..., ak]) = sum(1 / a1 ^ 2 + 1 / a2 ^ 2 + 1 / a ^ 3 + .... + 1 / ak ^ 2)

We start with the candidate array [2], search for the next smallest candidate (sc) so that S([2]) + S([sc]) <= 0.5. Obviously, in this case, the next smallest candidate is 3, so we append 3 to the candidate array and the array becomes [2, 3].

The candidate array keeps expanding until such smallest candidate cannot be found, then we update the last element of the candidate array to its 'next greater element' (we will refer to it as 'sibling' in the rest of the article) in the CANDIDATES list.

For example, the candidates array is [2, 3, 4, 5, 6, 12, 28, 52], so no such smallest candidate can be found so that S([2, 3, 4, 5, 6, 12, 28, 52]) + S([sc]) <= 0.5. Therefore the last element 52 is updated to its 'sibling ' 56, the candidate array becomes [2, 3, 4, 5, 6, 12, 28, 56].

if S(candidate_array) + S([sc]) happens to be 0.5, a solution is found.

The algorithm so far will find all the solutions although it's still quite slow. Consider this scenario:

candidate_array = [2, 4], the next smallest candidate that meets the criteria is 5, but even if we 'add up' the rest of all candidates, i.e. S([5, 6, 7, ...., 72]), the sum of S([2, 4]) and S([5, 6, 7, ...., 72]) is less than 0.5. We can see there is no solution for candidate array starting with [2, 4]. Similarly, there won't be a solution when it starts with [2, 5] and so on so forth. So we simply take off the last item off the list, and update the second last item (now it has become the last one) to its 'sibling' 3. When candidate_array = [3], there is also no solution. We take it off the list and end up with an empty array. And this is the terminating condition in the while loop.

It is worth mentioning that there is another condition that needs to be met to trigger the above scenario. That is, the next smallest candidate must equate the last element's 'sibling' in the CANDIDATES list, because the greatest candidate 72, happens to always meet this criteria, and therefore this particular case must be excluded. In the example above, 5 is 4's 'sibling', so the condition is met. On the other hand, the next smallest candidate for [2, 3, 4, 5, 9, 10, 13, 18, 24, 30, 35, 45, 52, 56] is 72, which is not 56's 'sibling'. Therefore the condition is not met and the scenario is not applied. 

The algorithm runs 4 seconds. I consider it not a half bad result.


 

Monday 3 June 2019

Project Euler 151 - Paper sheets of standard sizes: an expected-value problem

A printing shop runs 16 batches (jobs) every week and each batch requires a sheet of special colour-proofing paper of size A5.

Every Monday morning, the foreman opens a new envelope, containing a large sheet of the special paper with size A1.

He proceeds to cut it in half, thus getting two sheets of size A2. Then he cuts one of them in half to get two sheets of size A3 and so on until he obtains the A5-size sheet needed for the first batch of the week.

All the unused sheets are placed back in the envelope.

At the beginning of each subsequent batch, he takes from the envelope one sheet of paper at random.
If it is of size A5, he uses it. If it is larger, he repeats the 'cut-in-half' procedure until he has what he needs and any remaining sheets are always placed back in the envelope.

Excluding the first and last batch of the week, find the expected number of times (during each week) that the foreman finds a single sheet of paper in the envelope.

Give your answer rounded to six decimal places using the format x.xxxxxx .

Solution 

After round 1, we have
(A2, A3, A4, A5), 1. 1 denotes the probability of this combination.

After round 2, we have
(A2, A3, A4), 1/4
(2*A3, 2*A4, 2*A5), 1/4
(A2, 2*A4, 2*A5), 1/4
(A2, A3, 2*A5), 1/4

After round 3, we have
(2*A3, 2*A4, A5), 1/12
(A2, 2*A4, A5), 1/12
(A2, A3, A5), 1/12
(A3, 3*A4, 3*A5), 1/12
(2*A3, A4, 3*A5), 1/12
(2*A3, 2*A4, A5), 1/12
(A3, 3*A4, 3*A5), 1/20
(A2, A4, 3*A5), 1/10
(A2, 2*A4, A5), 1/10
(2*A3, A4, 3*A5), 1/16
(A2, A4, 3*A5), 1/16
(A2, A3, A5), 1/8

Then we add the probability for the same combination

(2*A3, 2*A4, A5), 1/12 + 1/12
(A2, 2*A4, A5), 1/12 + 1/10
(A2, A3, A5), 1/12 + 1/8
(A3, 3*A4, 3*A5), 1/12 + 1/20
(2*A3, A4, 3*A5), 1/12 + 1/16
(A2, A4, 3*A5), 1/10 + 1/16

Repeat the process for 14 rounds, then look for the combination that has one sheet of paper.