Project Euler 12

I was recently going through some old Project Euler solutions, and noticed that my solution to problem 12 was never optimized. The problems asks:

The sequence of triangle numbers is generated by adding the natural numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first ten terms would be:

1, 3, 6, 10, 15, 21, 28, 36, 45, 55, …

Let us list the factors of the first seven triangle numbers:

1: 1
3: 1,3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28

We can see that 28 is the first triangle number to have over five divisors.

What is the value of the first triangle number to have over five hundred divisors?

The way I originally solved this problem was a brute-force approach following this basic logic:

  1. Calculate next triangle number
  2. Try dividing number by every integer smaller than the number
  3. Count the number of integers that divide evenly
  4. Go to step 1 and repeat until divisors are greater than 500

This process yielded the results, but it is far from elegant or optimized. it took 14 minutes to calculate the answer! I knew that dividing by each number was a waste; there had to be a better way.

Although I didn’t know it, I felt fairly certain that there was a relationship between prime factors and the number of divisors. It turns out I was right. There is a trick to calculate the number of divisors if you know the prime factors.

Using the number 28 as an example, we can find that the prime factors are 2, 2, and 7, which can be written as 22 × 71. Interestingly, if we take the exponents, add 1 to each, and then multiply them together, we can calculate the number of divisors. For this example, this becomes (2+1) × (1+1), which is 2 × 3, which equals 6. (This is also mentioned in the Wikipedia article for divisor briefly in the section titled ‘Further notions and facts’).

Equipped with this knowledge, I was able to devise a more efficient method to solve this problem:

  1. Pre-calculate primes up to x amount (to save effort recomputing each time)
  2. Calculate next triangle number that is divisible by 3 or 5 (I found a pattern that the most divisible triangle numbers were divisible by 3 or 5)
  3. Go through primes and divide number by primes until number equals 1
  4. Convert the prime factors to divisors
  5. Go to step 1 and repeat until divisors are greater than 500

While this method is more complex, it yielded great results. Once I was done refining this method, I got the compute time down to .086 seconds. That is a very substantial improvement!

The interesting part of the code is the findDivisors function, seen below.

int findDivisors(int input, int *primes, int primesToFind)
{
    int i, count=1;
    int primeCount[primesToFind];
    for (i=0; i<primesToFind; i++)
    primeCount[i] = 0;

    // Prime factorization
    while (input != 1)
        for (i=0; i<primesToFind; i++)
            if (input % primes[i] == 0)
            {
                input = input / primes[i];
                primeCount[i]++;
            }

    // Convert prime factorization to divisors
    for (i=0; i<primesToFind; i++)
        if (primeCount[i] > 0)
            count *= (primeCount[i]+1);

    return count;
}

In this function, the inputs are:

  • The triangle number (input)
  • The array of pre-calculated prime numbers (primes)
  • The number of primes in the array (primesToFind)

As the division of primes occurs, I keep track in a separate array (primeCount) how many times a given prime index is used to divide. This keeps track of the prime factorization I talked about earlier so we can finally compute the number of divisors. Once computed, we pass back the count, and the program moves on to the next triangle number.

So there you have it. My entire solution is available on my GitHub page.

Emacs on Mac OS X

carbon-emacs-iconAt work I use a Linux work station a lot, and one of the things I really enjoy is that when I use Emacs from the command line, it opens up the graphical user interface. This, of course, is not the behavior on OS X. Additionally, the version that ships with Mac OS X is woefully out of date (version 22.1.1 at the time of writing).

I decided to do something about it, and grabbed an up-to-date build of Emacs from emacsformacosx.com. By default, it gets installed in /Applications, which will work just fine. It provides a graphical version of Emacs with support for normal Mac OS X short cuts, like command-c, etc.

But, Michael, how does this solve the problem of the Emacs from the command line being out of date? Well, Inside the application bundle is the Emacs executable that can be run from the command line, sans GUI. All you have to do is create an alias with this code (in my case, I made a bash script that resides in my ~/.bin named ’emacs’) with the following code:

#!/bin/sh
if
    [ -z "$SSH_CONNECTION" ]
then
    /Applications/Emacs.app/Contents/MacOS/Emacs "$@"
else
    /Applications/Emacs.app/Contents/MacOS/Emacs -nw "$@"
fi

This makes it so that if the terminal detects that you are running over an SSH (non-graphical) connection, it will run the non-windowed version of Emacs, otherwise it will launch the graphical version. It works just like it does in most Linux distros, and is a real pleasure to use!

Shipping Containers

Shipping-Container-Width

The other day I was stuck in some traffic while out on a trip with my brother and dad. The freeway was moving at about 5 MPH due to an accident, and we were behind a semi-truck towing a shipping container. Naturally, with nothing better to do, we looked up shipping container information online to find out how much they cost, size, weight, etc. and ran across the ISO 6346 specification for the serial numbers found on shipping containers.

The serial number found on shipping containers follow a strict format. The first 3 characters are the owner code, and are only letters. The 4th digit is the category identifier, which at this moment the only category is “U” for freight container. The remaining 6 characters are the serial number which will only be comprised of digits. After the 10 character serial number, there is a check digit, usually shown as a number in a box to the right.

Containernumber

The check digit is calculated by taking each character of the serial number, and assigning a value to the character and multiplying that value by 2 to the power of its location. Digits retain their face value, 0-9, while letters are given an incrementing value starting at 10, with the exception of multiples of 11 which are skipped (a=10, b=12, c=13, d=14… z=38). All of these values are then added together, divided by 11, truncated to an integer, multiplied by 11, and then subtracted from the original total. This is basically a fancy way of saying take the modulus 11 of the total.

We passed the remainder of our time in the traffic by verifying by hand that all the shipping container check numbers were calculated correctly. When I got home, I wrote this Python program to calculate it for me the next time I may ever need to generate or check a shipping container check digit. It asks for input, then uses a regular expression to validate the format. It then calculates and returns the check digit.

#!/usr/bin/python
import re
 
ShippingNumber = raw_input("Enter Container Code (eg. PSSU210948): ")
 
if not re.compile('\D{4}\d{6}').match(ShippingNumber):
    print "Invalid, please ensure code follows ISO 6346 specifications."
    quit()
 
Total=0
for i in range(len(ShippingNumber)):
    Value=ShippingNumber[i]
    if not Value.isdigit():
        Value=ord(Value.lower())-ord('a')+10
        Value+=Value/11
Total+=int(Value)*2**i
 
print "Check Digit:", str(Total%11%10)

© 2007-2015 Michael Caldwell