views:

68

answers:

3

what I am struggling with is testing predefined conditions which takes user provided parameters like in example below:

cond = "if ( 1 is yes and 2 is no ) or ( 1 is yes and 2 is no )"  
cond2 = "if (3 is no or 1 is no )"  
vars = []  

lst = cond.split()  
lst += cond2.split()  

for l in lst:  
   if l.isdigit():  
      if l not in vars:  
         vars.append(l)  
# ... sort 
# ... read user answers => x = no, y = no, y = yes 
# ... replace numbers with input (yes or no)

# ... finally I have 

cond = "if ( no is yes and no is no ) or ( no is yes and no is no )"
cond2 = "if (yes is no or no is no )" 

First of all, is this the right approach?
Secondly, how do I validate above conditions if True or False ?

Thank You in advance.

+1  A: 
Ignacio Vazquez-Abrams
I was looking at it, but still can't get thru. would you please give some code example ?
m1k3y02
A: 

so, after some reading based on Ignacio's tip, I think I have it after some string modifications. However, still not quite sure if this is the right approach.
So, my condition variable is defined as below

cond = """if ( 'no' is 'yes' and 'no' is 'no' ):
   result.append[1]
else:
   result.append[0]
"""

Additionally I create variable to store condition result to evaluate it later

result = []

I run exec on my string

exec(cond)

Finally, I can evaluate result.

if result[0] == 1
   print "Condition was met"
else: 
   print "Condition wasn't met"

Any thoughts or comments highly appreciated.

m1k3y02
If all you need to do is evaluate a single expression, boolean or otherwise, you can use `eval()` -- say something like `result = eval(cond)` where `cond` contains only the expression to be evaluated, such as `cond = "'no' is 'yes' and 'no' is 'no'"`. You could also use `result.append[eval(cond)]` to store several at a time.
martineau
A: 

All a user's answers taken together can be used to form a unique binary number (one composed of only zeros and ones). You could make a table (list) for each condition indexed by the each of the possible combinations of answer in each position store the value a given condition -- expressed as a lambda function -- would have for that set.

Once these tables are set up, you could determine whether any condition is true by looking up the value in the corresponding table indexed by a given combination of answers. Below is an example of how this might be set up.

NUM_ANSWERS = 4
NUM_COMBOS = 2**NUM_ANSWERS
NO,YES = 'no','yes'

def index(answers):
    """ Convert a list of yes/no answers into binary number. """
    binstr = ''.join([('1' if a is 'yes' else '0') for a in answers])
    return int(binstr, 2)

def answers(index):
    """ Convert binary value of number into list of yes/no answers. """
    masks = [2**p for p in range(NUM_ANSWERS-1, -1, -1)]
    bits = [((index & m) / m) for m in masks]
    return [[NO,YES][b] for b in bits]

# condition expressions
cond_expr1 = lambda a1,a2,a3,a4: a1 is YES and a2 is NO  # a3,a4 ignored
cond_expr2 = lambda a1,a2,a3,a4: (
                ( a1 is YES and a2 is NO ) or ( a3 is YES and a4 is NO )
             )
# build tables for each condition
cond1 = []
cond2 = []
for i in range(NUM_COMBOS):
    ans_combo = answers(i)
    cond1.append( cond_expr1(*ans_combo) )
    cond2.append( cond_expr2(*ans_combo) )

# once tables are built, you can lookup the corresponding conditional
print cond1[ index(['yes', 'no', 'no', 'yes']) ]  # True
print cond2[ index(['yes', 'no', 'yes', 'no']) ]  # True
martineau