def generate_nop(params, never_be_here=False): option = random.randint(0, 2 if never_be_here else 1) if option == 0: return "%s = %d\n" % (generate_id(), random.randint(-1000, -1000)) elif option == 1 and len(params) > 0: name, value = random.choice(list(params.items())) random_value = generate_random_string_literal() return 'if strcmp(%s, "%s") == 0 then\n%send\n' % ( "$" + name, random_value, textwrap.indent(generate_nop(params, True), INDENT)) else: return random.choice(list(DIRECTION_TO_FUNCTION.values())) + "()\n"
def generate_loop(operation, length): loop_variable = generate_id() shift = random.randint(0, 10) if random.randint(0, 5) == 0: return "for %s = %d .. %d do begin\n%s\nend\n" % ( loop_variable, 1 + shift, length + shift, textwrap.indent(operation, INDENT)) else: variable = generate_id() expression = generate_variable_value(variable, length + shift) return expression + "for %s = %d .. %s do begin\n%s\nend\n" % ( loop_variable, 1 + shift, variable, textwrap.indent(operation, INDENT))
def get_random_multiplicators(value): """ Returns tuple (x, y) such that x * y == value """ if value == 0: return random.randint(-100, 100), 0 dividers = [] x = 1 while x * x <= abs(value): if value % x == 0: dividers.append(x) x += 1 mult1 = random.choice(dividers) mult2 = value // mult1 if random.randint(0, 1) == 0: mult1 = -mult1 mult2 = -mult2 return mult1, mult2
def split_to_parts(moves): if len(moves) <= 3: return [moves] parts_count = random.randint(1, len(moves) // 3) sample = random.sample(range(len(moves) + parts_count), parts_count) sample = [0] + sorted(sample) + [len(moves) + parts_count] result = [] prev = 0 for idx in range(len(sample) - 1): result.append(moves[prev:prev + sample[idx + 1] - sample[idx]]) prev += sample[idx + 1] - sample[idx] return list(filter(bool, result))
def generate_variable_value(variable, value): option = random.randint(0, 4) if option == 0: # Just an assignment return "%s = %d\n" % (variable, value) result = "" if option == 1: # Assign a sum of two terms term1 = random.randint(-100, 100) term2 = value - term1 operation = "+" elif option == 2: # value = term1 - term2 term1 = random.randint(-100, 100) term2 = term1 - value operation = "-" elif option == 3: term1, term2 = get_random_multiplicators(value) operation = "*" else: term2 = random.randint(1, 100) term1 = term2 * value operation = "/" if random.randint(0, 1) == 0: v = generate_id() result += generate_variable_value(v, term1) term1 = v if random.randint(0, 1) == 0: v = generate_id() result += generate_variable_value(v, term2) term2 = v result += "%s = %s %s %s\n" % (variable, term1, operation, term2) return result
def generate_function(name, moves, params, flag=None): function = Function(name, {}, "", "") if name != "main": return_type_option = random.randint(0, 2) if return_type_option == 0: function.return_type = "int" elif return_type_option == 1: function.return_type = "str" functions = [] parts = split_to_parts(moves) already_printed_flag = flag is None for part in parts: if random.randint( 0, 2) <= 1 and len(part) >= 3: # generate a function and call it extracted_function_name = generate_id() flag_for_function = None if not already_printed_flag and random.choice(parts) == part: flag_for_function = flag already_printed_flag = True extracted_functions = generate_function(extracted_function_name, part, params, flag_for_function) extracted_function = extracted_functions[-1] functions.extend(extracted_functions) function.body += extracted_function_name + "()\n" else: # generate a sequence of moves (calls of goX() methods), maybe with loops if not already_printed_flag and random.choice(parts) == part: function.body += "write(\"%s\")\n" % flag already_printed_flag = True move_idx = 0 while move_idx < len(part): if move_idx + 2 < len(part) and part[move_idx] == part[ move_idx + 1] == part[move_idx + 2] and random.randint( 0, 2) <= 1: count = 0 while move_idx + count < len(part) and part[ move_idx + count] == part[move_idx]: count += 1 loop_length = random.randint(count // 2, count) loop = generate_loop( DIRECTION_TO_FUNCTION[part[move_idx]] + "()", loop_length) function.body += loop move_idx += loop_length else: move = part[move_idx] function.body += DIRECTION_TO_FUNCTION[move] + "()\n" move_idx += 1 if random.randint(0, 4) == 0: function.body += generate_nop(params) if not already_printed_flag: function.body += "write(\"%s\")\n" % flag if function.return_type == "str": function.body += 'return "%s"\n' % generate_random_string_literal() elif function.return_type == "int": function.body += 'return %d\n' % random.randint(-1000, 1000) return functions + [function]
def generate_params(): params_count = random.randint(1, 10) result = {} for _ in range(params_count): result[generate_id()] = generate_random_string_literal() return result