## Project Euler tips

A few years back I started working on Project Euler problems mainly because it was fun from a mathematical point of view, but also to improve my programming skills. After solving about 120 problems I seem to have hit a wall, because the numbers involved in some of the problems were just too big for my simple brute-force algorithms.

Recently, I decided to try and see if I can do some more of these problems. I cannot say that I’ve acquired some new techniques between 2012-2016 concerning the mathematics involved in these problems. My research topics are usually quite different and my day to day programming routines are more about constructing new stuff which works fast enough than optimizing actual code. Nevertheless, I have some experience coding in Matlab, and I realized that nested loops are to be avoided. Vectorizing the code can speed up things 100 fold.

So the point of Project Euler tasks is making things go well for large numbers. Normally all problems are tested and should run within a minute on a regular machine. This brings us to choosing the right algorithms, the right simplifications and finding the complexity of the algorithms involved.

## Project Euler Problem 285

Another quite nice problem from Project Euler is number 285. The result of the problem depends on the computation of a certain probability, which in turn is related to the computation of a certain area. Below is an illustration of the computation for k equal to 10.

To save you some time, here’s a picture of the case k=1 which I ignored and spent quite a lot of time debugging… Plus, it only affects the last three digits or so after the decimal point…

Here’s a Matlab code which can construct the pictures above and can compute the result for low cases. To solve the problem, you should compute explicitly all these areas.

function problem285(k) N = 100000; a = rand(1,N); b = rand(1,N); ind = find(abs(sqrt((k*a+1).^2+(k*b+1).^2)-k)<0.5); plot(a(ind),b(ind),'.'); axis equal M = k; pl = 1; for k=1:M if mod(k,100)==0 k end r1 = (k+0.5)/k; r2 = (k-0.5)/k; f1 = @(x) (x<=(-1/k+r1)).*(x>=(-1/k-r1)).*(sqrt(r1^2-(x+1/k).^2)-1/k).*(x>=0).*(x<=1); f1 = @(x) f1(x).*(f1(x)>=0); f2 = @(x) (x<=(-1/k+r2)).*(x>=(-1/k-r2)).*(sqrt(r2^2-(x+1/k).^2)-1/k).*(x>=0).*(x<=1); f2 = @(x) f2(x).*(f2(x)>=0); if k == pl thetas = linspace(0,pi/2,200); hold on plot(-1/k+r1*cos(thetas),-1/k+r1*sin(thetas),'r','LineWidth',2); plot(-1/k+r2*cos(thetas),-1/k+r2*sin(thetas),'r','LineWidth',2); plot([0 1 1 0 0],[0 0 1 1 0],'k','LineWidth',3); hold off axis off end A(k) = integral(@(x) f1(x)-f2(x),0,1); end xs = xlim; ys = ylim; w = 0.01; axis([xs(1)-w xs(2)+w ys(1)-w ys(2)+w]); sum((1:k).*A)

## Fireworks – Project Euler 317

You can read the text of the problem here. The idea is that we have an explosion at a given height in a uniform gravitational field (no friction/wind). Supposing that all particles go outwards from the explosion point with a constant initial speed, what is the shape of the body formed by these particles? A hint is given in the picture below with a nice Matlab simulation.

Now what happens if we add a little bit of wind? Here’s the perturbation obtained when adding a 10m/s uniform wind speed vs the initial configuration. Something like this would be a lot more challenging 🙂

## Project Euler Problem 144 – Laser light escaping an ellipse

Project Euler – problem 144 – visualization of the solution in Matlab

## Linear programming #1 – Project Euler 185

I was recently faced with a very nice challenge from Project Euler – Problem 185. The idea is to find a number with a fixed number of digits by making guesses. Each time you are told how many digits you got right. By got right, I mean guessing the right digit on the right position. If you find a digit which is in the number, but on a different position, you don’t know…

There is a test case with 5 digits:

90342 ;2 correct

70794 ;0 correct

39458 ;2 correct

34109 ;1 correct

51545 ;2 correct

12531 ;1 correct

with unique solution 39542 and the difficult case with 16 digits

5616185650518293 ;2 correct

3847439647293047 ;1 correct

5855462940810587 ;3 correct

9742855507068353 ;3 correct

4296849643607543 ;3 correct

3174248439465858 ;1 correct

4513559094146117 ;2 correct

7890971548908067 ;3 correct

8157356344118483 ;1 correct

2615250744386899 ;2 correct

8690095851526254 ;3 correct

6375711915077050 ;1 correct

6913859173121360 ;1 correct

6442889055042768 ;2 correct

2321386104303845 ;0 correct

2326509471271448 ;2 correct

5251583379644322 ;2 correct

1748270476758276 ;3 correct

4895722652190306 ;1 correct

3041631117224635 ;3 correct

1841236454324589 ;3 correct

2659862637316867 ;2 correct

While the small case could be tackled using a pure brute force approach (only ) cases to check, the second case becomes intractable. Looping through all cases would take ages. One could try genetic algorithms or other algorithms based on randomness. Recursive approaches are also possible.

There is however a way to express this problem which makes it solvable right away using a linear programming solver: that is an algorithm which finds valid solutions given some constraints. How do we find these constraints? There are essentially two types of constraints in our case:

- each of the positions of the result contains one digit from 0 to 9
- in each of the guesses given above we have a fixed number of correct digits