Ramanujan's Taxi Cab Numbers : A Solution

Here's one solution to the Taxi Cab function:

      ∇R←TaxiCab N;⎕IO;vals;sumCubes;cubes
[1]   ⎕IO←1
[2]   vals←⍳N
[3]   sumCubes←(vals∘.<vals)×cubes∘.+cubes←vals*3
[4]   R←(R=1⌽R)/R←R[⍋R←(,sumCubes)~0]
[5]   R←⍉R,[0.5](,¨(R⍷¨⊂sumCubes)×⊂vals∘.,vals)~¨⊂⊂0 0

For example:

      TaxiCab 30
  1729  1 12  9 10
  4104  2 16  9 15
 13832  2 24  18 20
 20683  10 27  19 24

The output shows the taxi cab number followed by the pairs of terms. For example 1729 = 13 + 123 = 93 + 103

An explanation of the APL code

Let's explore the solution line by line. Lines [1] and [2] are easy enough : vals is assigned a vector of numbers, e.g.

      vals←⍳13
      vals
1 2 3 4 5 6 7 8 9 10 11 12 13

Now we want to compute the cubes of those values:

      cubes←vals*3
      cubes
1 8 27 64 125 216 343 512 729 1000 1331 1728 2197

The next step is to compute the sums of all the possible pairs of cubes:

      cubes∘.+cubes←vals*3
   2    9   28   65  126  217  344  513  730 1001 1332 1729 2198
   9   16   35   72  133  224  351  520  737 1008 1339 1736 2205
  28   35   54   91  152  243  370  539  756 1027 1358 1755 2224
  65   72   91  128  189  280  407  576  793 1064 1395 1792 2261
 126  133  152  189  250  341  468  637  854 1125 1456 1853 2322
 217  224  243  280  341  432  559  728  945 1216 1547 1944 2413
 344  351  370  407  468  559  686  855 1072 1343 1674 2071 2540
 513  520  539  576  637  728  855 1024 1241 1512 1843 2240 2709
 730  737  756  793  854  945 1072 1241 1458 1729 2060 2457 2926
1001 1008 1027 1064 1125 1216 1343 1512 1729 2000 2331 2728 3197
1332 1339 1358 1395 1456 1547 1674 1843 2060 2331 2662 3059 3528
1729 1736 1755 1792 1853 1944 2071 2240 2457 2728 3059 3456 3925
2198 2205 2224 2261 2322 2413 2540 2709 2926 3197 3528 3925 4394

However, we're only interested in pairs of cubes where the two numbers are different, and we don't want to consider both '3 and 4' and '4 and 3'. The expression vals∘.<vals gives an array in which there is a '1' in every position where the column number is greater than the row number:

      vals∘.<vals
0 1 1 1 1 1 1 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1 1 1 1 1
0 0 0 1 1 1 1 1 1 1 1 1 1
0 0 0 0 1 1 1 1 1 1 1 1 1
0 0 0 0 0 1 1 1 1 1 1 1 1
0 0 0 0 0 0 1 1 1 1 1 1 1
0 0 0 0 0 0 0 1 1 1 1 1 1
0 0 0 0 0 0 0 0 1 1 1 1 1
0 0 0 0 0 0 0 0 0 1 1 1 1
0 0 0 0 0 0 0 0 0 0 1 1 1
0 0 0 0 0 0 0 0 0 0 0 1 1
0 0 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0

So Line [3] find the sums of pairs of cubes as follows:

      sumCubes←(vals∘.<vals)×cubes∘.+cubes←vals*3
      sumCubes
0 9 28 65 126 217 344 513  730 1001 1332 1729 2198
0 0 35 72 133 224 351 520  737 1008 1339 1736 2205
0 0  0 91 152 243 370 539  756 1027 1358 1755 2224
0 0  0  0 189 280 407 576  793 1064 1395 1792 2261
0 0  0  0   0 341 468 637  854 1125 1456 1853 2322
0 0  0  0   0   0 559 728  945 1216 1547 1944 2413
0 0  0  0   0   0   0 855 1072 1343 1674 2071 2540
0 0  0  0   0   0   0   0 1241 1512 1843 2240 2709
0 0  0  0   0   0   0   0    0 1729 2060 2457 2926
0 0  0  0   0   0   0   0    0    0 2331 2728 3197
0 0  0  0   0   0   0   0    0    0    0 3059 3528
0 0  0  0   0   0   0   0    0    0    0    0 3925
0 0  0  0   0   0   0   0    0    0    0    0    0

Line [4] is concerned with finding the taxi cab numbers themselves. First we convert the array of sums of cubes into a simple list and remove any 0s:

      R←(,sumCubes)~0
      R
9 28 65 126 217 344 513 730 1001 1332 1729 2198 35 72 ...etc

Now we sort the list into ascending order:

      R←R[⍋R←(,sumCubes)~0]
      R
9 28 35 65 72 91 126 133 152 189 217 224 243 ...etc 

Now we want to find duplicates in the list. These are the taxi cab numbers, since they can be expressed as the sum of two cubes in two different ways. The expression R=1⌽R produces a boolean vector with a '1' for every item in the list which is repeated, and we can use it with / to get the actual item values:

      R←(R=1⌽R)/R←R[⍋R←(,sumCubes)~0]
      R
1729

Line [5] is concerned with finding which pairs of values produced each taxi cab number. First we find each taxi cab number in the sum-of-cubes array. Let's consider the simple case first, where we found only one taxi cab number:

      R
1729
      R⍷sumCubes
0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0

You can see that it was found at row 1, column 12 and also at row 9, column 10. In other words, 1729 = 13 + 123 = 93 + 103.

How do we find out the row/column numbers of the two '1's ? The following expression gives all the pairs of row and column values:

     vals∘.,vals
 1 1   1 2   1 3   1 4   1 5   1 6   1 7   1 8   1 9   1 10   1 11   1 12   1 13
 2 1   2 2   2 3   2 4   2 5   2 6   2 7   2 8   2 9   2 10   2 11   2 12   2 13
 3 1   3 2   3 3   3 4   3 5   3 6   3 7   3 8   3 9   3 10   3 11   3 12   3 13
 4 1   4 2   4 3   4 4   4 5   4 6   4 7   4 8   4 9   4 10   4 11   4 12   4 13
 5 1   5 2   5 3   5 4   5 5   5 6   5 7   5 8   5 9   5 10   5 11   5 12   5 13
 6 1   6 2   6 3   6 4   6 5   6 6   6 7   6 8   6 9   6 10   6 11   6 12   6 13
 7 1   7 2   7 3   7 4   7 5   7 6   7 7   7 8   7 9   7 10   7 11   7 12   7 13
 8 1   8 2   8 3   8 4   8 5   8 6   8 7   8 8   8 9   8 10   8 11   8 12   8 13
 9 1   9 2   9 3   9 4   9 5   9 6   9 7   9 8   9 9   9 10   9 11   9 12   9 13
 10 1  10 2  10 3  10 4  10 5  10 6  10 7  10 8  10 9  10 10  10 11  10 12  10 13
 11 1  11 2  11 3  11 4  11 5  11 6  11 7  11 8  11 9  11 10  11 11  11 12  11 13
 12 1  12 2  12 3  12 4  12 5  12 6  12 7  12 8  12 9  12 10  12 11  12 12  12 13
 13 1  13 2  13 3  13 4  13 5  13 6  13 7  13 8  13 9  13 10  13 11  13 12  13 13

So we can find the answer as follows:

     (R⍷sumCubes)×vals∘.,vals
 0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0   0 0  1 12  0 0
 0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0   0 0  0 0   0 0
 0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0   0 0  0 0   0 0
 0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0   0 0  0 0   0 0
 0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0   0 0  0 0   0 0
 0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0   0 0  0 0   0 0
 0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0   0 0  0 0   0 0
 0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0   0 0  0 0   0 0
 0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  9 10  0 0  0 0   0 0
 0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0   0 0  0 0   0 0
 0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0   0 0  0 0   0 0
 0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0   0 0  0 0   0 0
 0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0  0 0   0 0  0 0   0 0
      (,(R⍷sumCubes)×vals∘.,vals)~⊂0 0
 1 12  9 10

We now need to take care of the fact that there might be more than one taxi-cab number, so the expression becomes:

      (,¨(R⍷¨⊂sumCubes)×⊂vals∘.,vals)~¨⊂⊂0 0
  1 12  9 10

Finally, we create an array with the first row containing the taxi cab numbers and the second row containing the terms, flip it using to make the result more readable, and we're done.

Other investigations concerning 1729

We can define a handy function to break a number up into its digits:

      ∇R←base Digits val
[1]  ⍝ Returns individual digits of 'val' when expressed in base 'base',
[2]  ⍝ e.g. 10 Digits 1729 gives 1 7 2 9
[3]   R←((1+⌊base⍟val+0=val)⍴base)⊤val

(a) Now to find out which numbers are evenly divisible by the sum of their digits. Here's a test of the range 1720-1770

      (0=(+/¨10 Digits¨ X)|X)/X←1719+⍳50 
1725 1728 1729 1740 1744 1746 1764 1770

(b) Now we investigate which of the first 100000 numbers behave in the same way as 1729, i.e.

      (vals=sums×10⊥¨⌽¨10 Digits¨sums←+/¨10 Digits¨ vals)/vals←⍳100000
1 81 1458 1729

In fact these are the only four natural numbers which have this property.

<< The task

   

Author: SimonMarsden

TaxiCabNumbers/Solution (last edited 2009-02-08 21:52:34 by SimonMarsden)