Wolfram Computation Meets Knowledge

Happy 10*9*8+7+6-5+4*321 !

I was amazed to see this tweet from our friends at the Museum of Mathematics:

A quick check with Mathematica verified that, yes indeed, 10*9*8+7+6-5+4*321 = 2012. Wow! How in the world did anyone discover that rare factoid? And how long will it be until another year arrives that can be similarly expressed?

That’s the sort of question that’s so easy to answer with Mathematica that I couldn’t not have a look. It turns out that what seemed to me like a rare jewel is as common as dirt. In fact, there is only one year in the next 100 that can’t be expressed by interspersing +, -, *, /, or nothing between the numbers in order from 10 to 1! In subsequent correspondence with George Hart, the museum’s Chief of Content, he told me that he learned the idea from Hans Havermann, who wrote about it in a blog post last year. I’ve discovered what he had up his sleeve: abundant computing.

Let’s call an expression like the one above, with the numbers 10, 9, …, 1 interspersed with operators, a 10-expression. To check what years could be formulated as 10-expressions, I strung together the component characters into character strings and then told Mathematica to interpret those as mathematical expressions. Since there are 5 different operators and 9 operator positions between the 10 numbers, there are 59 = 1953125 different calculations to make. With brutish force, I generated every one of them and had a look at the result.

This is how it works. Here are the numbers:

numbers = {"10", "9", "8", "7", "6", "5", "4", "3", "2", "1"} ;

And the operators:

ops = {"", "+", "-", "*", "/"};

The set of all 1953125 possible combinations of the 5 operators in 9 positions is given by:

opTuples = Tuples[ops, 9];

opTuples is a list, each element of which is a list of 9 operators. For example:

opTuples[[1426451]]

{"*", "*", "+", "+", "-", "+", "*", "", ""}

I interspersed each such tuple among the 10 numbers using Mathematica‘s Riffle function, which effectively shuffles two lists together, and applied StringJoin to concatenate that into a single string that expresses an arithmetic calculation:

expressionString = StringJoin @@ Riffle[numbers, opTuples[[1426451]]]

"10*9*8+7+6-5+4*321"

Applying ToExpression to that string evaluates the corresponding mathematical expression and returns the value it represents:

ToExpression[expressionString]

2012

I encapsulated those operations in the function ShowNExpressions that calculates all the possibilities, selects those in a given range of dates, and nicely formats the result. Imagine my surprise when I applied it to the next 100 years, and it appeared that every one of them was expressible as a 10-expression, and most of them in more than one way (on closer examination I saw that one year, 2102, was missing). Here’s the beginning of that list:

ShowNExpressions[numbers, ops, {2012, 2016}]

{  {2012, "10*9*8+7+6-5+4*321"}, {2012, "10+9*87-65+4*321"}, {2012, "109-8*7+654*3-2-1"}, {2013, "10*9*8*7/6/5*4*3-2-1"}, {2013, "10*98/7*6/5*4*3-2-1"}, {2013, "109-8*7+654*3-2*1"}, {2013, "109-8*7+654*3-2/1"}, {2014, "10*9*8*7/6/5*4*3-2*1"}, {2014, "10*9*8*7/6/5*4*3-2/1"}, {2014, "10*9*8+7+6*5*43-2-1"}, {2014, "10*98/7*6/5*4*3-2*1"}, {2014, "10*98/7*6/5*4*3-2/1"}, {2014, "109-8*7+654*3-2+1"}, {"", ""}, {2015, "10*9*8*7/6/5*4*3-2+1"}, {2015, "10*9*8+7+6*5*43-2*1"}, {2015, "10*9*8+7+6*5*43-2/1"}, {2015, "10*98/7*6/5*4*3-2+1"}, {2015, "10*98/7/6/5*432-1"}, {"", ""},  {2016, "10+9+8*7*6*5-4+321"}, {2016, "10*9*8+7+6*5*43-2+1"}, {2016, "10-9+8*7+654*3-2-1"}, {2016, "10*9-8-7+654*3-21"}, {2016, "10+9*8-7+654*3-21"},  {2016, "10+9+8*7+654*3-21"}, {2016, "10*98/7/6/5*432*1"}, {2016, "10*98/7/6/5*432/1"}, {2016, "109-8*7+654*3+2-1"}, {2016, "109+87+65*4/3*21"} }

It turns out that if you have enough numbers in the sequence, you can express any year with some combination of operators. Ten numbers is just about the sweet spot. With 9-expressions, you get only 79% of the next 100 years. With 10-expressions you get 99%. 11-expressions go way overboard, giving an average of 51 different ways to express each year.

There’s nothing special about the sequence 10, 9, …, 1. The sequence 1, 2, …, 9 works, too (in 6 different ways):

ShowNExpressions[ToString /@ Range[9], ops, {2012, 2012}]

{{2012, "1-2-3+4*567*8/9"}, {2012, "1+2/3*45*67-8+9"}, {2012, "1+2345*6/7-8+9"}, {2012, "12+34*56+7+89"}, {2012, "123+45*6*7+8-9"}, {2012, "1234-5-6+789"}}

My colleague Ed Pegg explored this variation when he was playing with a draft of this post. He sent the last of those expressions to National Public Radio Puzzlemaster Will Shortz, who used it as the January 29 Sunday Puzzle (sorry, the deadline for solutions has passed!).

Other number sequences work as well. You can express 2012 using the first 9 digits of π (2 ways):

{ {2012, "3*141*5-9*2*6+5"}, {2012, "3*141*5-92-6-5"} }

And the first 9 Fibonacci numbers (3 ways):

{ {2012, "1-1-23+5-8*13+2134"}, {2012, "1-123-5-8+13+2134"}, {2012, "1-123+5+8-13+2134"} }

My telephone number works, and it’s likely that yours does, too, if it doesn’t contain too many zeros.

I found another pleasant surprise in the operator patterns of different expressions for the same year. Take, for example, 2040.

{ {2040, "10*9-8-7+654*3+2+1"}, {2040, "10+9*8-7+654*3+2+1"}, {2040, "10+9+8*7+654*3+2+1"}, {2040, "10-9+8*7+654*3+21"}, {2040, "10*98*7*6/5/4+3-21"} }

The first three expressions for that year have the same “+654*3+2+1” suffix, which means that their prefixes all express the same number. But there’s a curious pattern there, where multiplication marches right, gobbling up minuses and depositing pluses in its wake. Is it a fluke, or is there something general going on?

I calculated that pattern for 10-expressions and saw that regardless of the position of the multiplication, you do indeed get the same number:

Grid[MakeNExpression[numbers, #] & /@  Table[Join[Table["+", {i - 1}], {"*"}, Table["-", {9 - i}]], {i, 1, 9}]]

{ {54, "10*9-8-7-6-5-4-3-2-1"}, {54, "10+9*8-7-6-5-4-3-2-1"}, {54, "10+9+8*7-6-5-4-3-2-1"}, {54, "10+9+8+7*6-5-4-3-2-1"}, {54, "10+9+8+7+6*5-4-3-2-1"}, {54, "10+9+8+7+6+5*4-3-2-1"}, {54, "10+9+8+7+6+5+4*3-2-1"}, {54, "10+9+8+7+6+5+4+3*2-1"}, {54, "10+9+8+7+6+5+4+3+2*1"} }

That, of course, doesn’t show that it always works that way, but we can ask Mathematica to prove the general case. This expression gives the value expressed by the sequential integers m to n with multiplication in position p. The simplified result does not contain p, which shows that the value does not depend on the position of the multiplication, regardless of the number sequence.

Expression giving the value expressed by the sequential integers m to n with multiplication in position p

1/2 (-2 - m + m^2 + n + n^2)

In an age when natural resources are growing ever more scarce, computing resources are growing ever more abundant. The extravagantly wasteful computation above—calculating nearly two million numbers in order to filter out the few hundred I was interested in—took 48 seconds on my laptop. It would have taken many weeks on the university mainframe computer when I was an undergraduate. The very fact that I could be extravagant—and didn’t have to spend any time trying to be clever or efficient—meant that I could explore and discover new things. Hans Havermann knew this already: it’s abundant computing that makes these rare jewels as common as dirt.

Download this post as a Mathematica notebook.

Comments

Join the discussion

!Please enter your comment (at least 5 characters).

!Please enter your name.

!Please enter a valid email address.

6 comments

  1. A simistic but cool example. Nothing fancy, but really cool post.
    This blog need more posts like this.
    But I still hope for more technical posts.

    :) Many thanks

    Reply
  2. A good example how to use a brutal force to solve a simple problem :-) Just try to reverse list of numbers to realize there are eight possibilities how to express the year 2102 (for example “12+345*6-7+8+9+10”). Anyway it shows the strengths of Mathematica.

    Reply
  3. I was confused for a bit there… I was being quite literal and I thought that the “!” was a factorial at first…

    Reply
  4. At first, I would like to thank you for this good article. But, what happens if we use braces? I think the odds will increase the possibilities? Please explain how to enter braces in the code.

    Reply
  5. verry good… (i’am Indonesian)

    Reply
  6. Just wonderful. I loved how you implemented bit-by-bit using Wolfram’s huge laboratory of purely developed functions. But I’m a little sad because I saw this post today in 2021.

    Reply