### Archive

Archive for the ‘Programming’ Category

## 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 $10^5$) cases to check, the second case becomes intractable. Looping through all $10^16$ 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 $1/8-\pi/32$. 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

April 21, 2015 1 comment

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 ${[i,j,k]}$ we set the elements ${a_{ij},a_{jk},a_{ik}}$ (and their symmetric correspondents) to be equal to ${1}$.

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 ${A}$ is the adjacency matrix, then ${A^2=(b_{ik})}$ stores the number of paths of length ${2}$ (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 ${2}$. If ${[i,j,k]}$ is a triangle such that points ${i,j}$ are on the boundary, then ${b_{i,j}=1}$ (there is one path of length ${2}$ going through ${i,k,j}$. We also have ${a_{i,j} = 1}$. Conversely, if ${a_{i,j} = 1}$ and ${b_{i,j} = 1}$ then ${i,j}$ are connected, and there is a unique path of length ${2}$ going from ${i}$ to ${j}$. Thus, ${i,j}$ is an edge on the boundary. Therefore, we just need to identify the indexes ${i}$ such that there exists ${j}$ with ${a_{i,j} b_{i,j} = 1}$.

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);