## 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.

## 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

## About Problem 587 – Project Euler

I started looking again at some problems on the Project Euler site. It’s not often that I manage to solve a recent problem. Below are a few hints about the math needed to provide an answer to problem 587.

I’ll not repeat the statement of the problem here, so please read it by following the above link. The idea is to find the ratio of the areas of some triangular shapes made of two segments and one circle arc. The breakdown of the problem is the following:

- Note that the size of the square does not matter, since we need the result as a ratio, so we can consider that the square has side equal to 1. First note that the L-shape in the corner of the triangle has area equal to . We’ll need this in the end, to compute the ratio.
- Secondly, the shape whose area we need to compute can be decomposed into a right-angled triangle and a complement of a part of the circle. In order to have precise information about these shapes we compute the intersection of the line y=x/n and the circle (x-0.5)^2+(y-0.5)^2=0.25. It is possible to find the value explicitly.
- Once we have the coordinates of the point of intersection we can compute the area of the triangle. The area of the rounded part which remains is the difference between a rectangle and the circle portion PQON. In order to do find this difference it suffices to find the angle PSQ.
- Once the mathematical part is done, the programming job is not that tough, since the numbers involved are not that high. I managed to write a Matlab solution in no time.

## Identifying edges and boundary points – 2D Mesh – Matlab

A triangulation algorithm often gives as output a list of points, and a list of triangle. Each triangle is represented by the indexes of the points which form it. Sometimes we need extra information on the structure of the triangulation, like the list of edges, or the list of boundary points. I will present below two fast algorithms for doing this.

Finding the list of edges is not hard. The idea is to go through each triangle, and extract all edges. The algorithm proposed below creates the adjacency matrix in the following way: for each triangle we set the elements (and their symmetric correspondents) to be equal to .

In order to find the points on the boundary (in two dimensions), it is enough to look for the edges which are sides to only one triangle. We can do this using the adjacency matrix. Note that if is the adjacency matrix, then stores the number of paths of length (two sides) between two points of the triangulation. Note that any edge which is not on the boundary will contain the starting and ending point of two paths of length . If is a triangle such that points are on the boundary, then (there is one path of length going through . We also have . Conversely, if and then are connected, and there is a unique path of length going from to . Thus, is an edge on the boundary. Therefore, we just need to identify the indexes such that there exists with .

Below are two short Matlab codes doing these two algorithms. I guess they are close to being optimal, since only sparse and vectorized operations are used.

%p is the list of points %T is the list of triangles, ap is the number of points %this computes the adjacency matrix A = min(sparse(T(:,1),T(:,2),1,ap,ap)+sparse(T(:,2),T(:,3),1,ap,ap)+sparse(T(:,3),T(:,1),1,ap,ap),1); A = min(A+A',1); % this finds the boundary points, whose indexes are stored in Ibord B = A^2.*A==1; Ibord = find(sum(B,2)>0);