What is the first triangle number to have more than 500 divisors?

Ok, this one kicked me in the pants, and it kicked my little Mac in the pants as well. I had to relearn how to get divisors quickly and efficiently, which meant seeking the wisdom of others on the Internet. But eventually I got a working program that didn't take all night to run.

function euler12

nn = 3;
while 1

  if mod(nn,2) == 0
    ndivisors = get_divisors(nn/2)*get_divisors(nn+1);
  else
    ndivisors = get_divisors((nn+1)/2)*get_divisors(nn);
  end

  if ndivisors > 500
    break;
  end

  nn = nn+1;

end
nn
triangle_num = nn/2*(nn+1)
ndivisors


function ndivisors = get_divisors(nn)

ndivisors = 2; % 1 and nn

% Get the prime factors
vv = factor(nn);
nvv = length(vv);
ndivisors = ndivisors + length(unique(vv));

% Now get all the combinations of the prime factors
for ii = 2:(nvv-1)
  aa = nchoosek(vv, ii);
  bb = unique(aa, 'rows');
  [mm, nn] = size(bb);
  ndivisors = ndivisors + mm;
end
with no comments
Filed under:

For those of you out there doing e-commerce, check out 7 Billion People. They specialize in a more personalized e-commerce experience, and they have a hard-working, experienced team behind them. Take a look at their marketing videos:

http://www.youtube.com/watch?v=-5xahNGE-lU
http://www.youtube.com/watch?v=724s9rmfk0g
http://www.youtube.com/watch?v=Z5ZVwf9YXsQ

A customer asked me to write a very small application that performs some operations on 2D parametric curves. While their code base for their primary software is C++ Win32, I thought this would be a great opportunity to show off C#.Net to them, but that meant coming up with a basic graphics library that would allow me to display (x,y) data as a spline curve or polyline, toggle control points display, and perhaps do some zooming and panning. While the customer is willing to pay for a 3rd party library if the price and feature set are right, I thought I'd look into open source libraries to see what's out there. That's how I discovered ZedGraph.

ZedGraph is billed as a charting library (it can do X-Y, bar and pie charts), but it's X-Y graphing functionality is solid enough to make it appropriate for a basic 2D graphics app. One of my big concerns was the ability to exert control over the scaling along the X and Y axes. I want to be able to force a 1:1 aspect ratio between the X and Y scaling so that the curves that I'm plotting aren't distorted. ZedGraph allows me to set the minimum and maximum values along an axis, but then it takes care of the rest. If I'm showing the axes and a grid behind my curves, ZedGraph automatically figures out where to put tick marks and major and/or minor grid lines.

Naturally I want to be able to control the color and style of the plotted curves, the type of symbol used to represent curve control points, the axes titles, the chart title,  the gridline color, etc. This is very intuitive in ZedGraph, because the architecture of the library and the names of the properties and methods make sense.

Zooming and panning functionality is available by default in the .Net UserControl that comes along with the library. Best of all, the functionality mimics that of many well-known graphics software apps (like ANSYS and Unigraphics).

Finally, the documentation and examples available at the ZedGraph website are decent enough to get the novice beyond setting up a basic graph. I was able to follow the examples to get the look, feel, and functionality my customer required in place within a few hours.

I haven't played around with the library long enough to discover its limitations - I'm sure they're there! But for a very basic 2D graphics app, this libary is an excellent choice.

with no comments
Filed under:

In this problem we are searching for the largest product of four consecutive numbers in any row, column, or diagonal of a given 20 by 20 matrix. This is a nice sort of problem to do in Matlab because it is so well-suited for working with matrices. I wrote a separate function for scooting along a vector looking for the greatest product. Matlab has a built-in diag function that gives you a matrix diagonal as a vector. The 0th diagonal is the central one, the negative indices give you the lower triangle, and positive indices give you the upper triangle. Without further ado...

function euler11

global nn;
global mm;
global max_product;

grid = [08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08;
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00;
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65;
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91;
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80;
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50;
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70;
67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21;
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72;
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95;
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92;
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57;
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58;
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40;
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66;
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69;
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36;
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16;
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54;
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48];

nn = 20;
mm = 4;
max_product = 0;

% Go through rows
for ii = 1:nn
  get_product(grid(ii,:));
end

% Go through columns
for ii = 1:nn
  get_product(grid(:,ii));
end

% Go through upper left lower right diagonals
for ii = (-nn+mm):(nn-mm)
  clear vv;
  vv = diag(grid, ii);
  get_product(vv);
end

% Go through lower left upper right diagonals
grid = flipud(grid);
for ii = (-nn+mm-1):(nn-mm+1)
  clear vv;
  vv = diag(grid, ii);
  get_product(vv);
end

max_product

function get_product(vv)

global mm;
global max_product;

for ii = 1:(length(vv)-mm+1)
  product = vv(ii);
  for jj = 1:mm-1
   product = product * vv(ii+jj);
  end
  if product > max_product
   max_product = product;
  end
end
with 2 comment(s)
Filed under:

Sum the primes below 2,000,000.

This is the sort of problem that Matlab handles very well. The code looks pretty, and I got an answer right quick. Now if I type fast, I'll get my code posted before my battery drains and Baseball Tonight ends.

function euler10
sum(primes(2000000),2)

Now I'm really challenging myself - can I get a solution to a problem without the fan kicking on? This one took a few tries, but I finally found a good algorithm.

We're asked to find the pythagorean triplet (a, b, c) that sums to 1000. I made an educated guess as to a good range for c, to limit the search space.

function euler9

% a < b < c

for cc = 500:-1:300
  aa_bb = 1000-cc;
  for bb = aa_bb-1:-1:1
   aa = aa_bb - bb;
   if (aa*aa + bb*bb) == cc*cc
    disp([num2str(aa), ", ", num2str(bb), ", ", num2str(cc)]);
    aa*bb*cc
    return;
   end
  end
end

This problem reminded me of Professor Rida Farouki, who teaches his students the value of conserving computations in CAD systems, and who has written several papers on Pythagorean hodograph curves.

This problem asks us to find the greatest product of five consecutive digits in a given 1000 digit number. First the 1000 digit number has to be stored as a string. I wanted to make sure that each digit of the number was converted from a string to an int only once, which complicates the code a bit. Second, it occurred to me that if I'm looking for the greatest product, I'm also looking for the greatest sum. This allows me to save some further compute time.

function euler8

big_num = "73167176531330624919225119674426574742355349194934...
96983520312774506326239578318016984801869478851843...
85861560789112949495459501737958331952853208805511...
12540698747158523863050715693290963295227443043557...
66896648950445244523161731856403098711121722383113...
62229893423380308135336276614282806444486645238749...
30358907296290491560440772390713810515859307960866...
70172427121883998797908792274921901699720888093776...
65727333001053367881220235421809751254540594752243...
52584907711670556013604839586446706324415722155397...
53697817977846174064955149290862569321978468622482...
83972241375657056057490261407972968652414535100474...
82166370484403199890008895243450658541227588666881...
16427171479924442928230863465674813919123162824586...
17866458359124566529476545682848912883142607690042...
24219022671055626321111109370544217506941658960408...
07198403850962455444362981230987879927244284909188...
84580156166097919133875499200524063689912560717606...
05886116467109405077541002256983155200055935729725...
71636269561882670428252483600823257530420752963450";

sum = 0;
product = 1;
for ii = 1:5
  digit(ii) = str2num(big_num(ii));
  sum = sum + digit(ii);
  product = product*digit(ii);
end
biggest_product = product;
biggest_sum = sum;

for ii = 2:996
  sum = sum - digit(1);
  for jj = 1:4
   digit(jj) = digit(jj+1);
  end
  digit(5) = str2num(big_num(ii+4));
  sum = sum + digit(5);

  if sum > biggest_sum
   biggest_sum = sum;
   biggest_product = digit(1)*digit(2)*digit(3)*digit(4)*digit(5);
  end
end
biggest_product
with no comments
Filed under:

Is it cheating to use the Matlab built in isprime function? It saves me from going to Google to find a prime number algorithm.

Here's my code:

function euler7

ii = 0;
jj = 2;
while 1
  if isprime(jj)
   ii=ii+1;
   if ii == 10001
    break;
   end
  end
  jj=jj+1;
end
jj

This completed in a reasonable amount of time on my slow Mac, but later I read about only testing odd numbers, and I wish I had thought of that.

with no comments
Filed under:

I'm skipping around a bit, but this one shows off Matlab a little better.

function euler6

nat_nums = 1:1:100
sum(nat_nums,2)^2 - sum(nat_nums .* nat_nums, 2)

 

.* is the array multiplcation operator (element-wise)

Arrays in Matlab are really 1xn matrices, so in the sum functions, the second argument indicates that I should sum across columns.

Matlab rocks. 

 

I thought I'd join the Euler problem bandwagon. In true mechanical engineering fashion, I'm using Matlab to solve them. Actually, just for an added twist, I'm using Octave, an open source math interpreter that is mostly compatible with Matlab, on my dog-slow Mac notebook, forcing me to not use brute-force approaches if they can be avoided.

I had already seen solutions to problems 1-3, so I started with 4.  So here goes:

function euler4

max_result = 0;
for ii = 999:-1:100
  for jj = 999:-1:100

    % Don't bother to check if this number is smaller than the max found
    result = ii*jj;
    if (result < max_result)
      continue;
    end
     
    % Check for palindrome
    result_string = int2str(result);
    success = 1;
    rlength = length(result_string);
    for kk = 1:rlength/2
      if result_string(kk) ~= result_string(rlength-kk+1)
        success = 0;
        break;
      end
    end
    if success && result > max_result
      max_result = result;
    end
   
  end
end

max_result

Not pretty, but it gets the job done.

 

with no comments
Filed under: