2014-01-15 22:18:55 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# encoding: utf-8
|
|
|
|
|
|
|
|
from random import randint
|
|
|
|
import re
|
2014-11-23 09:45:13 +00:00
|
|
|
import pyparsing
|
|
|
|
from .generic import flatten_list
|
2014-01-15 22:18:55 +00:00
|
|
|
|
2014-02-28 12:17:12 +00:00
|
|
|
from .arithmetic import gcd
|
|
|
|
|
2014-12-27 15:32:44 +00:00
|
|
|
def random_str(form, conditions = [], val_min = -10, val_max = 10):
|
|
|
|
""" Create a random string using RdExpression class """
|
|
|
|
random_str_generator = RdExpression(form, conditions)
|
|
|
|
return random_str_generator(val_min, val_max)
|
|
|
|
|
2014-01-15 22:18:55 +00:00
|
|
|
class RdExpression(object):
|
2014-08-29 14:35:38 +00:00
|
|
|
"""
|
|
|
|
|
2014-12-19 15:45:22 +00:00
|
|
|
A generator of random expression builder
|
2014-08-29 14:35:38 +00:00
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self, form, conditions = []):
|
2014-01-15 22:18:55 +00:00
|
|
|
"""Initiate the generator
|
|
|
|
|
|
|
|
:param form: the form of the expression (/!\ variables need to be in brackets {})
|
|
|
|
:param conditions: condition on variables (/!\ variables need to be in brackets {})
|
|
|
|
|
|
|
|
"""
|
|
|
|
self._form = form
|
|
|
|
self._conditions = conditions
|
2014-08-29 14:35:38 +00:00
|
|
|
|
2014-01-15 22:18:55 +00:00
|
|
|
self._letters = self.get_letters()
|
|
|
|
self._gene_varia = {}
|
2014-12-19 16:17:25 +00:00
|
|
|
self._gene_2replaced = {}
|
2014-01-17 11:28:59 +00:00
|
|
|
|
|
|
|
def get_2replaced(self):
|
|
|
|
"""Get elements of self._form which will have to be replaced
|
|
|
|
:returns: set for elements which have to be replaced
|
|
|
|
|
|
|
|
"""
|
2014-11-23 09:45:13 +00:00
|
|
|
#pattern = "\{(.*?)\}" #select inside {} non greedy way
|
|
|
|
#varia_form = re.findall(pattern, self._form)
|
2014-01-17 11:28:59 +00:00
|
|
|
|
2014-11-23 09:45:13 +00:00
|
|
|
# TODO: Bug with varia with spaces |dim. nov. 23 10:44:34 CET 2014
|
|
|
|
varia_form = flatten_list([eval(str(i[0])) for i in pyparsing.nestedExpr('{','}').searchString(self._form)])
|
2014-02-28 12:17:12 +00:00
|
|
|
varia_form = set(varia_form)
|
|
|
|
|
|
|
|
varia_cond = set()
|
|
|
|
for c in self._conditions:
|
2014-11-23 09:45:13 +00:00
|
|
|
c_varia_cond = flatten_list([eval(str(i[0])) for i in pyparsing.nestedExpr('{','}').searchString(c)])
|
|
|
|
varia_cond = varia_cond | set(c_varia_cond)
|
2014-02-28 12:17:12 +00:00
|
|
|
|
|
|
|
self._2replaced = varia_cond | varia_form
|
|
|
|
|
|
|
|
return self._2replaced
|
2014-01-15 22:18:55 +00:00
|
|
|
|
|
|
|
def get_letters(self):
|
|
|
|
"""Find letters in the form
|
|
|
|
:returns: list of letters
|
|
|
|
|
|
|
|
"""
|
2014-01-17 11:28:59 +00:00
|
|
|
v2replaced = self.get_2replaced()
|
|
|
|
varia = set()
|
|
|
|
|
|
|
|
pattern = "([a-zA-Z]+)"
|
|
|
|
for v in v2replaced:
|
|
|
|
lvar = set(re.findall(pattern, v))
|
|
|
|
varia = varia | lvar
|
|
|
|
|
|
|
|
return varia
|
|
|
|
|
2014-01-15 22:18:55 +00:00
|
|
|
|
2014-08-29 14:35:38 +00:00
|
|
|
def __call__(self, val_min = -10, val_max = 10):
|
2014-01-15 22:18:55 +00:00
|
|
|
"""RdExpression once it is initiate act like a function which create random expressions.
|
|
|
|
|
|
|
|
:param val_min: minimum value random generation
|
|
|
|
:param val_max: maximum value random generation
|
2014-01-19 20:39:35 +00:00
|
|
|
:returns: an formated random expression
|
2014-01-18 18:25:10 +00:00
|
|
|
|
|
|
|
"""
|
2014-12-19 15:45:22 +00:00
|
|
|
return self.raw_str(val_min, val_max)
|
2014-01-18 18:25:10 +00:00
|
|
|
|
2014-01-30 08:26:48 +00:00
|
|
|
def raw_str(self, val_min = -10, val_max = 10):
|
|
|
|
"""Return raw string (don't use Expression for rendering or parsing)
|
2014-01-18 18:25:10 +00:00
|
|
|
|
|
|
|
:param val_min: minimum value random generation
|
|
|
|
:param val_max: maximum value random generation
|
|
|
|
:returns: an random Expression object
|
2014-01-15 22:18:55 +00:00
|
|
|
|
|
|
|
"""
|
|
|
|
self.gene_varia(val_min, val_max)
|
|
|
|
|
|
|
|
while not(self.val_conditions()):
|
|
|
|
self.gene_varia(val_min, val_max)
|
|
|
|
|
2014-01-18 18:25:10 +00:00
|
|
|
exp = self._form.format(**self._gene_2replaced)
|
|
|
|
|
2014-01-30 08:26:48 +00:00
|
|
|
return exp
|
|
|
|
|
2014-01-15 22:18:55 +00:00
|
|
|
def gene_varia(self, val_min = -10, val_max = 10):
|
2014-02-28 12:17:12 +00:00
|
|
|
"""Randomly generates variables/letters
|
|
|
|
|
|
|
|
Varia can't be equal to 0
|
2014-01-15 22:18:55 +00:00
|
|
|
|
|
|
|
"""
|
|
|
|
for l in self._letters:
|
|
|
|
self._gene_varia[l] = randint(val_min, val_max)
|
2014-01-28 22:21:37 +00:00
|
|
|
while self._gene_varia[l] == 0:
|
|
|
|
self._gene_varia[l] = randint(val_min, val_max)
|
2014-01-15 22:18:55 +00:00
|
|
|
|
2014-02-28 12:17:12 +00:00
|
|
|
|
2014-01-17 11:28:59 +00:00
|
|
|
for e in self._2replaced:
|
|
|
|
self._gene_2replaced[e] = eval(e, globals(), self._gene_varia)
|
|
|
|
|
2014-01-15 22:18:55 +00:00
|
|
|
def val_conditions(self):
|
|
|
|
"""Tells whether or not conditions are validates
|
|
|
|
:returns: boolean
|
|
|
|
|
|
|
|
"""
|
2014-01-17 10:19:28 +00:00
|
|
|
if self._conditions != []:
|
2014-02-28 12:17:12 +00:00
|
|
|
return eval(" and ".join(self._conditions).format(**self._gene_2replaced))
|
2014-01-17 10:19:28 +00:00
|
|
|
else:
|
|
|
|
return True
|
2014-01-15 22:18:55 +00:00
|
|
|
|
2014-01-17 11:28:59 +00:00
|
|
|
def desc_rdExp(rdExp):
|
|
|
|
print("--------------------")
|
|
|
|
print("form: ",rdExp._form)
|
|
|
|
print("Conditions: ",rdExp._conditions)
|
|
|
|
print("Letters: ", rdExp._letters)
|
|
|
|
print("2replaced: ", rdExp._2replaced)
|
2014-08-29 14:35:38 +00:00
|
|
|
print("Call : ", rdExp())
|
2014-11-21 16:21:12 +00:00
|
|
|
print("type: ",type(rdExp()))
|
2014-01-17 11:28:59 +00:00
|
|
|
print("Gene varia: ", rdExp._gene_varia)
|
|
|
|
print("Gene 2replaced: ", rdExp._gene_2replaced)
|
|
|
|
print('')
|
|
|
|
|
2014-01-15 22:18:55 +00:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2014-12-27 15:32:44 +00:00
|
|
|
form = "({a};{b})"
|
|
|
|
cond = []
|
|
|
|
print(random_str(form, cond))
|
2014-02-28 12:17:12 +00:00
|
|
|
|
|
|
|
form = "{a+a*10}*4 + {a} + 2*{b}"
|
|
|
|
cond = ["{a} + {b} in [1, 2, 3, 4, 5]", "abs({a}) not in [1]", "{b} not in [1]", "gcd({a},{b}) == 1"]
|
2014-12-27 15:32:44 +00:00
|
|
|
print(random_str(form, cond))
|
2014-02-28 12:17:12 +00:00
|
|
|
|
2014-12-03 14:52:08 +00:00
|
|
|
form = "{a+a*10}*4 + {a} + 2*{b}"
|
2014-02-28 12:17:12 +00:00
|
|
|
cond = ["{a-b} + {b} in list(range(20))", "abs({a}) not in [1]", "{b} not in [1]", "gcd({a},{b}) == 1"]
|
2014-12-27 15:32:44 +00:00
|
|
|
print(random_str(form, cond))
|
2014-01-15 22:18:55 +00:00
|
|
|
|
2014-12-03 14:52:08 +00:00
|
|
|
import doctest
|
|
|
|
doctest.testmod()
|
2014-01-15 22:18:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# -----------------------------
|
|
|
|
# Reglages pour 'vim'
|
|
|
|
# vim:set autoindent expandtab tabstop=4 shiftwidth=4:
|
|
|
|
# cursor: 16 del
|