I "cheated" and wrote a Python script that used the Johnson-Trotter algorithm to permute the order of the numbers that are plugged into the equation.
My script spits out 6 possible solutions:
3 + 6 - 4 x 5 ÷ 1 x 2
6 + 3 - 4 x 5 ÷ 1 x 2
6 + 3 - 4 x 2 ÷ 1 x 5
3 + 6 - 4 x 2 ÷ 1 x 5
4 + 2 - 1 x 6 ÷ 3 x 5
2 + 4 - 1 x 6 ÷ 3 x 5
Though, given the extra conditions of the puzzle (no ÷1 and never dealing with decimals/fractions), you're left with 2 solutions because addition is commutative.
4 + 2 - 1 x 6 ÷ 3 x 5
2 + 4 - 1 x 6 ÷ 3 x 5
I'm sure the pen-and-paper method accomplished above is probably more satisfying to perform, though!
Python Source
Play with the code here.
This is just a Johnson-Trotter permutation class I wrote. It uses a step
function to go to the next permutation. I thought about making an iterator version, but was too lazy =/. It may be a little lengthy, but it can be used to permute any list of objects. I'm sure it could be improved and condensed; I just threw this together for this puzzle =P
jtpermute.py
class JohnsonTrotterPermute(object):
objlist = [] # contains the objects given to the class
nodelist = [] # contains the JTNode objects that wrap around each given object
numnodes = 0 # the current number of nodes added (for numbering)
steps = 1 # the number of iterations generated (number of steps)
def __init__(self, objlist):
self.objlist = objlist
for obj in self.objlist:
self.nodelist.append(JTNode(self.numnodes, obj))
self.numnodes += 1
# returns True if there exists at least one mobile JTNode
def has_mobile(self):
for i in range(len(self.nodelist)):
if self.check_mobility(i):
return True
return False
# returns True if the JTNode at the given index is mobile
def check_mobility(self, index):
if index < 0 or index >= len(self.nodelist):
return False
if self.nodelist[index].direction == -1: # pointing left
if index == 0: # on the left edge of list
return False
if self.nodelist[index].num > self.nodelist[index - 1].num:
return True
if self.nodelist[index].direction == 1: # pointing right
if index == len(self.nodelist) - 1: # on the right edge of list
return False
if self.nodelist[index].num > self.nodelist[index + 1].num:
return True
return False
# iterates through the nodes and flips the direction of any node
# whose .num is larger than the given number
def flip_larger_than_num(self, num):
for node in self.nodelist:
if (node.num > num):
node.flip()
# returns the index of the JTNode that has the largest .num value
# and is mobile
def get_largest_mobile_index(self):
index = -1
largest = -1
for i in range(len(self.nodelist)):
if self.nodelist[i].num > largest and self.check_mobility(i):
largest = self.nodelist[i].num
index = i
return index
# swaps the node at the given index with the node that it's pointing
# at. Returns True if the swap is successful, False if the swap fails
# (e.g. the node is pointing left, but it's the left-most node)
def move_node(self, index):
node = self.nodelist[index]
tempnode = None
if node.direction == -1: # pointed left
if index == 0: # on left edge of list
return False
tempnode = self.nodelist[index]
self.nodelist[index] = self.nodelist[index - 1]
self.nodelist[index - 1] = tempnode
self.flip_larger_than_num(tempnode.num)
if node.direction == 1: # pointed right
if index == len(self.nodelist) - 1: # on right edge of list
return False
tempnode = self.nodelist[index]
self.nodelist[index] = self.nodelist[index + 1]
self.nodelist[index + 1] = tempnode
self.flip_larger_than_num(tempnode.num)
return True
# steps the list order to its next iteration
def step(self):
if self.has_mobile():
largest_mobile = self.get_largest_mobile_index()
self.move_node(largest_mobile)
self.steps += 1
return True
return False
# returns the list of items that the user initially provided in the
# order of the current iteration
def get_items(self):
returnlist = []
for node in self.nodelist:
returnlist.append(node.obj)
return returnlist
# a wrapper class for the list items the user will provide
class JTNode(object):
obj = None # the actual user-provided list item
num = -1 # the number of the node
direction = -1 # pointing direction (-1 -> left, 1 -> right)
def __init__(self, num, obj):
self.obj = obj
self.num = num
# flip the direction the node is pointing
def flip(self):
self.direction *= -1
puzzle.py
from jtpermute import *
# computes the puzzle equation on the given list of integers
def do_maths(intlist):
if len(intlist) < 6:
return 0
num = intlist[0]
num += intlist[1]
num -= intlist[2]
num *= intlist[3]
num /= intlist[4]
num *= intlist[5]
return num
# prints the puzzle's function with the numbers plugged in
def print_maths(intlist):
if len(intlist) < 6:
return 0
# a string builder of sorts
strlist = []
strlist.append(str(intlist[0]))
strlist.append(" + ")
strlist.append(str(intlist[1]))
strlist.append(" - ")
strlist.append(str(intlist[2]))
strlist.append(" * ")
strlist.append(str(intlist[3]))
strlist.append(" / ")
strlist.append(str(intlist[4]))
strlist.append(" * ")
strlist.append(str(intlist[5]))
strlist.append(" = ")
strlist.append(str(do_maths(intlist)))
print "".join(strlist)
jtp = JohnsonTrotterPermute([1, 2, 3, 4, 5, 6])
# the equivalent of a do-while loop in Python. I wanted to put the
# step function in the loop conditional, but it had to be evaluated
# before the first .step call. When the step function returns False,
# it has reached the end of the permutations
while True:
if do_maths(jtp.get_items()) == 50:
print_maths(jtp.get_items())
if jtp.step() == False:
break
print "Number of permutations: %d" % jtp.steps
Output of puzzle.py
3 + 6 - 4 * 5 / 1 * 2 = 50
6 + 3 - 4 * 5 / 1 * 2 = 50
6 + 3 - 4 * 2 / 1 * 5 = 50
3 + 6 - 4 * 2 / 1 * 5 = 50
4 + 2 - 1 * 6 / 3 * 5 = 50
2 + 4 - 1 * 6 / 3 * 5 = 50
Number of permutations: 720