4

Problem:

The numbers from 1 to 10 are given. Put the equal sign(somewhere between them) and any arithmetic operator {+ - * /} so that a perfect integer equality is obtained(both the final result and the partial results must be integer)

Example:

1*2*3*4*5/6+7=8+9+10

1*2*3*4*5/6+7-8=9+10

My first idea to resolve this was using backtracking:

  1. Generate all possibilities of putting operators between the numbers
  2. For one such possibility replace all the operators, one by one, with the equal sign and check if we have two equal results

But this solution takes a lot of time.

So, my question is: Is there a faster solution, maybe something that uses the operator properties or some other cool math trick ?

Zoltan Ersek
  • 755
  • 9
  • 28
  • 7
    This smells like homework, but is very interesting nonetheless. – erip Mar 02 '15 at 07:32
  • you can reduce constant factors by taking into account the symmetries of operators (e. g. `+` is associative and commutative), but that won't help the asymptotical complexity of the algorithm. Eventually, this **will** blow up combinatorially. – The Paramagnetic Croissant Mar 02 '15 at 07:35
  • 1
    Do "/" and "*" have precedence in order of operations? And do you need to find all possibilities? – Andrei Nikolaenko Mar 02 '15 at 07:44
  • 4
    The equal sign can go 9 different places, and the other 8 places have four possibilities each. That's a total of `9 * 4^8 = 589824` possible equations. That's not a lot for a modern computer. – user3386109 Mar 02 '15 at 07:49
  • @AndreiNikolaenko Yes / and * have precedence, and yes I need to find all possibilities – Zoltan Ersek Mar 02 '15 at 08:04
  • 3
    Actually brute-forcing some problems is faster today then using elaborate algorithms. You can put the work onto a GPU and do it really fast and fancy. – Jonathan Mar 02 '15 at 08:06
  • 2
    A tree could be built starting from node 1. Node depth is the current number in sequence, node value is current result, node has a list of "+", "-", "*", "/" links to the next node, if some of operations is illegal, the link is absent. Search would be done starting from the root node and finding all paths that lead to the result in the current node. But that works fine only when operation precedence is equal. I think this can be tuned somehow and the initial sequence must first be restructured or preprocessed so the operation order would be strictrly sequential. – Andrei Nikolaenko Mar 02 '15 at 08:12

1 Answers1

4

I'd start with the equals sign. Pick a possible location for that, and split your sequence there. For left and right side independently, find all possible results you could get for each, and store them in a dict. Then match them up later on.

Finding all 226 solutions took my Python program, based on this approach, less than 0.15 seconds. So there certainly is no need to optimize further, is there? Along the way, I computed a total of 20683 subexpressions for a single side of one equation. They are fairly well balenced: 10327 expressions for left hand sides and 10356 expressions for right hand sides.

If you want to be a bit more clever, you can try reduce the places where you even attempt division. In order to allov for division without remainder, the prime factors of the divisor must be contained in those of the dividend. So the dividend must be some product and that product must contain the factors of number by which you divide. 2, 3, 5 and 7 are prime numbers, so they can never be such divisors. 4 will never have two even numbers before it. So the only possible ways are 2*3*4*5/6, 4*5*6*7/8 and 3*4*5*6*7*8/9. But I'd say it's far easier to check whether a given division is possible as you go, without any need for cleverness.

MvG
  • 57,380
  • 22
  • 148
  • 276
  • Thanks for your answer. I'm not sure I've completely understood the dictionary part. Are the sequences results the keys and the expressions the values ? – Zoltan Ersek Mar 02 '15 at 14:08
  • @user2219209: The expression values are the keys, the actual expressions the values. E.g. the number `19` might get mapped to the string `"9+10"`. Actually it's a multimap, since you can have multiple values for each key, multiple expressions with the same value over the same sequence, like `1+2-3+4+5*6-7-8` and `1*2+3-4*5+6*7-8` are two of the many ways to combine 1…8 to form 19. I implemented this as a map from value to list of expressions, appending to that list. – MvG Mar 02 '15 at 14:28