Project Euler Problem #15

20 03 2009

Starting in the top left corner of a 2×2 grid, there are 6 routes (without backtracking) to the bottom right corner.

p_015

How many routes are there through a 20×20 grid?

First off, let me say I’ve never taken a combinatorics course, and before this problem had never seen the words “n choose k”. If you’ve taken a combinatorics course, you’ll probably figure out this problem in about 3 seconds, realizing it’s simply 40 choose 20 (which Google calculator will gladly output). Due to my lack of combinatorics, I was forced to take a very long route to get to the answer, but challenged myself a lot more in the process.

First off, I thought to myself, there must be some function f(n) for an n x n grid that will give me the result, and I just need to find it. In order to simplify things, I changed the grid to a set of equally spaced points in a plane. For a 2×2 grid, there would be 9 points (2+1)(2+1). Then I traced through the grid again, looking for some simple pattern. I quickly noticed that once you hit the bottom or right edge, you must go straight to the end point using a single path (along the edge). Otherwise, you have two choices (down or right). In my diagram below, I drew arrows on the points that I had a choice, and simply put a line through the points on the edges that had no choice. I also took note that for an n x n grid, there would be n movements in the right direction, n movements in the down direction, and 2n movements total.

paths2I was also on the bus at the time, so no access to a computer, which explains the badly scribbled diagrams.

The only pattern I could deduce from this, is that because there is 2n number of moves, all of which n must be down and n must be right, I could do something like this.

Down = 0

Right = 1

Paths to end in my 2×2 grid (from left to right, top to bottom in the diagram): 1100, 1001, 1010, 0011, 0101, 0110.

Nifty, but how do I make an algorithm to actually create these numbers? I could simply check using a brute force method, generating all the binary numbers from 0 to 15, and then checking if they meet the requirements. To solve the problem though, I would need to generate all the numbers from 0 to 2^(40). That’s a lot of numbers to check. 1,099,511,627,776 of them to be exact. I found the result of the 3×3 grid by hand, through painful searching. There’s 20 of them, so I don’t bother to show the result. If anyone finds an easy algorithm to use this method, I’d be interested in seeing it.

As things were, I hadn’t gotten far, and decided to take another approach. After staring at 1’s and 0’s for so long, I was ready to stare at something more graphical, and decided to represent the 3×3 grid paths as a binary tree, in the back of my mind thinking I could use a linked list in C to actually make such a structure and maybe get somewhere. First off, I put all the points into an array (in my head anyway) so I could easily keep track of them. P11, P12, P13, P21, etc for labels. Then, for a down branch, go left on the tree, and for a right branch, go right.

pathtreeThen I spent quite some time trying to make out patterns. First off, I began noting the paths from a point down to the bottom, which you can see in the small numbers on the lines and under the points. Then I noticed the tree diagrams for a 1×1 (red) and 2×2 (blue) grid were actually inside the 3×3 (green) grid. Nifty! Closer I thought I was, to finding a simple recursive function to find the answer I seek. Unfortunately, I couldn’t devise a simple function to generate the number of paths from the next tree diagram. Then, it came to me, looking at the path lengths.

1

1 1

1 2 1

1 3 3 1

1 4 6 4 1

1 5 10 10 5 1

20

Eureka! It’s Pascal’s  triangle up-side-down! The result I seek for a n x n grid is the middle number of the 2*n’th row of pascal’s triangle. Not only that, but this is also the sum of the terms squared of the n’th row (one of many odd patterns in the triangle). Finally all I had to do was write a program to calculate the first 20 lines of Pascal’s triangle, and then square the terms of that last row and add them together.

to calculate the triangle,

#include 

#define ROWS 21
#define COLS 21

int main() {
        int triangle[ROWS][COLS];
        int i, j;

        for (i = 0; i < ROWS; i++) {
                for (j = 0; j <= i; j++) {
                        triangle[i][j] = 0;
                        if (i == j || j == 0) {
                                triangle[i][j] = 1;
                        } else {
                                triangle[i][j] = triangle[i-1][j-1] + triangle[i-1][j];
                        }
                        printf("%d ", triangle[i][j]);
                }
                printf("\n");
        }
}

Resulting in,

1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
1 10 45 120 210 252 210 120 45 10 1
1 11 55 165 330 462 462 330 165 55 11 1
1 12 66 220 495 792 924 792 495 220 66 12 1
1 13 78 286 715 1287 1716 1716 1287 715 286 78 13 1
1 14 91 364 1001 2002 3003 3432 3003 2002 1001 364 91 14 1
1 15 105 455 1365 3003 5005 6435 6435 5005 3003 1365 455 105 15 1
1 16 120 560 1820 4368 8008 11440 12870 11440 8008 4368 1820 560 120 16 1
1 17 136 680 2380 6188 12376 19448 24310 24310 19448 12376 6188 2380 680 136 17 1
1 18 153 816 3060 8568 18564 31824 43758 48620 43758 31824 18564 8568 3060 816 153 18 1
1 19 171 969 3876 11628 27132 50388 75582 92378 92378 75582 50388 27132 11628 3876 969 171 19 1
1 20 190 1140 4845 15504 38760 77520 125970 167960 184756 167960 125970 77520 38760 15504 4845 1140 190 20 1

Taking all the elements of the last row, squaring them, and adding them,

1^2 + 20^2 + 190^2…. = 137,846,528,820 paths to the end in a 20×20 grid. That’s a lot of paths, I’m glad I didn’t have to resort to a pure brute force approach, it would have taken quite a long time.

Advertisements




A Programmer’s Quest for Primes: Part 4 – Special Primes

10 03 2009

Continuing my playing with primes, I’m now up to having 1 billion of them sitting on my hard drive. That’s 11GB in a text file. It’s actually spread out between 10 files in 100 million prime blocks to load in an out of RAM easier. They were generated in only 30 minutes using the Sieve of Eratosthenes and a modified version of the prime program found here, http://www.troubleshooters.com/codecorn/primenumbers/primenumbers.htm.

In this post I went through my files finding some statistics on special primes. The graphs below have groups of 1 million primes on the x-axis, and the number of special primes found within that 1 million on the y-axis.

Twin primes: prime numbers that differ by two. For example, 17 and 19. There are theories that there are an infinite number of twin primes, but looking at it as a limit as the function approaches infinity, it certainly looks like it goes to 0, if very slowly. In the first 1 billion primes, there are 58,047,180 twin primes (according to my program’s results at least), or about 5.8% of the total.

twinprimesCousin primes: prime numbers that differ by four. Interestingly, according to some number theory equations called the Hardy–Littlewood conjecture, they are supposed to have about the same distribution as twin primes. My results show it’s quite close, 58,040,262 of them in the first billion primes. The graph is about the same.

cousinprimesSexy primes: no, I didn’t come up with the name, the Latin word for 6 is sex, and the math people love to name things in Latin and use Greek symbols. Primes that differ by 6. There are 105,002,853 of them in the first billion, quite a bit more than twin or cousin primes.

sexyprimesAnswer primes: pairs of primes that differ by 42. Okay, I did make this one up. Any scifi fans out there will see the reference. There are 22,729,810 of them in the first billion primes. The graph is at least more interesting than the others due to the fact it’s a larger number. The distance between primes increases as the primes gets bigger.

answerprimesSome random facts of interest (to weird people like me anyway).

The longest distance between two primes out of the first billion (consecutive composite integers): 394. There are no prime numbers between 22367084959 and 22367085353. If you split the 1 billion primes into blocks of 1 hundred million, and then find the longest runs of composite integers in each block,

292 between 1453168141 and 1453168433
336 between 3842610773 and 3842611109
354 between 4302407359 and 4302407713
340 between 8605261447 and 8605261787
382 between 10726904659 and 10726905041
354 between 11705477863 and 11705478217
346 between 14066075347 and 14066075693
376 between 16161669787 and 16161670163
372 between 20404137779 and 20404138151
394 between 22367084959 and 22367085353

Since the distance on average between primes increases as you get bigger, you’d think the max distance would increase more clearly. Such is one of the mysteries of the primes.





A Programmer’s Quest for Primes: Part 3 – Prime Distribution

9 03 2009

While playing around with primes and C some more, I put together some plots with Mathematica dealing with the distance between primes. The prime numbers are plotted, with the n’th prime on the x-axis and the difference between it and the last prime on the y-axis. After all, I’ve got gigabytes of primes sitting around.. got to figure out something to do with them other than test my RAM while generating them.

The first 1,000 primes,

prime_distro_1k1Of course, primes can’t be odd numbers apart, because that would make them even. That explains the pattern a bit. Still, for something that has baffled mathematicians for centuries, it certainly does seem like there’s a pattern to it. If you draw lines between the points,

primes_1k_dist_linedCertainly not as pretty.

The first 10,000 primes,

prime_distro_100kThe scale makes this one a bit less interesting. Too much overlap, but Mathematica really doesn’t like big listplots like this. I even crashed it a few times when I tried to do a listplot of 100,000 data plots. 10,000 was pushing it.

A random sampling of 1,000 primes (between the 90 millionth and 90 million 1 thousandth prime),

primes_distri_90mil1More interesting patterns in primes, the Ulam spiral. Starting at 1 and spiraling outwords from the orgin, you create a graph like so (http://en.wikipedia.org/wiki/Ulam_spiral),

ulam-spirale1And then remove all but the primes (http://en.wikipedia.org/wiki/File:Ulam-Spirale2.png),

ulam-spirale21And you find an intersting pattern, that the prime numbers tend to lay along some diagnols more oftan than others. Expanding this to 150,000 primes,

spiral





A Programmer’s Quest for Primes: Part 2 – Sieve of Eratosthenes

6 03 2009

This is part 2 of my quest to calculate prime numbers using small and efficient programs written in C. In the first part I wrote a program to brute force find primes by testing sequential numbers to see if they were divisible by any other prime numbers found before, and making the process a bit faster by only checking odd numbers and stopping when I reach a prime greater than the square root of the number in question.

For my second prime calculating program I make use of an algorithm developed 2,200 years ago by the Greek mathematician Eratosthenes. A friend once told me all the great computer science ideas were developed 20 years ago. I often tend to think it was further back than that. Division and modulus commands are very costly in terms of CPU cycles. Multiplication and addition are much faster. Rather than checking to see if a number is prime by dividing it by all prime numbers found before it, it’s much faster to multiply the prime numbers to find all the composites, and then mark anything remaining as prime.

animation_sieve_of_eratosth-2

A bit array would be the ideal data structure for this algorithm, but because C doesn’t have a bit array structure built in. The only other option is use the bool datatype (C99) or an unsigned char (ANSI), but either way you’re wasting 7 bits of memory for each element (you only need one bit). While searching for bit arrays in C I found another programmer’s quest for calculating prime numbers here, http://www.troubleshooters.com/codecorn/primenumbers/primenumbers.htm.

Rather than reinventing the wheel I just finished up my much simpler version using char arrays to find the first 100 million primes. The code can be found here, http://pherricoxide.jumbofx.com/code/eratosthenesprimecalc.c. After this point it starts running out of RAM though, so to find more primes you’ll have to use a paging or cluster method as coded in the last link.

Using the brute force program it took over 2 hours to compute the first 100 million primes.

Using this method, it took less than 7 minutes. Quite a difference to say the least. The only downside is that this algorithm uses much more RAM.