Reputation: 1670
I am attempting to write a simple math expression generator. The problem I am having is achieving an expression with random numbers selected from within a range, and inserting a random operator between each number.
Here's what I have so far:
from random import randint
from random import choice
lower = int(raw_input("Enter a lower integer constraint: "))
higher = int(raw_input("Enter a higher integer constraint: "))
def gen_randoms(lower, higher):
integers = list()
for x in xrange(4):
rand_int = randint(lower, higher)
integers.append(rand_int)
return integers
def gen_equations(integers):
nums = map(str, integers)
print nums
operators = ['*', '+', '-']
equation = 'num op num op num op num'
equation = equation.replace('op', choice(operators))
equation = equation.replace('num', choice(nums))
print equation
nums = gen_randoms(lower, higher)
gen_equations(nums)
The problem here is the output will repeat the operator choice and random integer selection, so it gives 5 + 5 + 5 + 5
or 1 - 1 - 1 - 1
instead of something like 1 + 2 - 6 * 2
. How do I instruct choice
to generate different selections?
Upvotes: 0
Views: 292
Reputation: 142136
I'd go for using a replacements dict
and using that to replace each "word":
import random
replacements = {
'op': ['*', '+', '-'],
'num': map(str, range(1, 6))
}
equation = 'num op num op num op num op num'
res = ' '.join(random.choice(replacements[word]) for word in equation.split())
# 1 + 3 * 5 * 2 + 2
You could then generalise this so that each word performs a different action, so to pick a random operator, but keep the numbers in sequence...:
replacements = {
'op': lambda: random.choice(['*', '+', '-']),
'num': lambda n=iter(map(str, range(1, 6))): next(n)
}
equation = 'num op num op num op num op num'
res = ' '.join(replacements[word]() for word in equation.split())
# 1 + 2 + 3 - 4 * 5
Note, this will throw an error if there are more num
's present in the string, then there are in the replacements...
Upvotes: 4
Reputation: 1121744
str.replace()
replaces all occurrences of the first operand with the second operand. It does not treat the second argument as an expression, however.
Replace one occurrence at a time; the str.replace()
method takes a third argument that limits how many replacements are made:
while 'op' in equation:
equation = equation.replace('op', choice(operators), 1)
while 'num' in equation:
equation = equation.replace('num', choice(nums), 1)
Now the choice()
is called for each iteration through the loop.
Demo:
>>> from random import choice
>>> operators = ['*', '+', '-']
>>> nums = map(str, range(1, 6))
>>> equation = 'num op num op num op num op num'
>>> while 'op' in equation:
... equation = equation.replace('op', choice(operators), 1)
...
>>> while 'num' in equation:
... equation = equation.replace('num', choice(nums), 1)
...
>>> equation
'5 - 1 * 2 * 4 - 1'
Upvotes: 5
Reputation: 49826
This line calls choice
only once:
equation = equation.replace('num', choice(nums))
It replaces every instance of 'num'
with the one value you pass as the second argument.
This is as expected.
The correct way to replace values in a string is to use format
or the %
operator. See: http://docs.python.org/2/library/string.html
Alternatively, you could iteratively build up the string.
Upvotes: 0