а временные затраты окупятся? или это так и останется Proof of concept.
Реализуй подобное в своём project - тогда и узнаешь.а временные затраты окупятся? или это так и останется Proof of concept.
для начала нужно дорасти до 100сообщений чтоб посмотреть предложения товарища Left4DeadРеализуй подобное в своём project - тогда и узнаешь.
Будут вопросы - обращайся, чем смогу - помогу.
post-order traversal?Мне кажется нерационально генерировать случайные деревья и проверять потом, а не подходит ли это дерево под нашу задачу, в частности подстановка и проверка ожидаемого выхода, медленно достаточно
Мне кажется лучше генерировать случайное дерево, делать рассчет получая Y из входного X, затем просто строить обратное дерево преобразований, отзеркаливающих действия, по итогу получаем дерево, которому на вход подается Y, а на выход получаем X
Так гораздо быстрее, и не нарушается оригинальная концепция, просто вместо функции проверки формулы на валидность для нашего случая надо написать генератор дерева функции-инверсии
import secrets
TREE_NODE_OPERAND = 0
TREE_NODE_UNARY = 1
TREE_NODE_BINARY = 2
TREE_MAX_DEPTH = 8
unary_array = []
binary_array = []
def calculate_unary(a, opcode):
if opcode == 0x00:
return a
elif opcode == 0x01:
return ~a & 0xFF
elif opcode == 0x02:
return (a + 1) & 0xFF
elif opcode == 0x03:
return (a - 1) & 0xFF
elif opcode == 0x04:
return a >> 1
elif opcode == 0x05:
return a >> 2
elif opcode == 0x06:
return a >> 3
elif opcode == 0x07:
return a >> 4
elif opcode == 0x08:
return (a << 1) & 0xFF
elif opcode == 0x09:
return (a << 2) & 0xFF
elif opcode == 0x0A:
return (a << 3) & 0xFF
elif opcode == 0x0B:
return (a << 4) & 0xFF
def unary_to_string(operand, opcode):
if opcode == 0x00:
return f"(unsigned char)( {operand} )"
elif opcode == 0x01:
return f"(unsigned char)( ~( (unsigned char){operand} ) )"
elif opcode == 0x02:
return f"(unsigned char)( (unsigned char){operand} + 1 )"
elif opcode == 0x03:
return f"(unsigned char)( (unsigned char){operand} - 1 )"
elif opcode == 0x04:
return f"(unsigned char)( (unsigned char){operand} >> 1 )"
elif opcode == 0x05:
return f"(unsigned char)( (unsigned char){operand} >> 2 )"
elif opcode == 0x06:
return f"(unsigned char)( (unsigned char){operand} >> 3 )"
elif opcode == 0x07:
return f"(unsigned char)( (unsigned char){operand} >> 4 )"
elif opcode == 0x08:
return f"(unsigned char)( (unsigned char){operand} << 1 )"
elif opcode == 0x09:
return f"(unsigned char)( (unsigned char){operand} << 2 )"
elif opcode == 0x0A:
return f"(unsigned char)( (unsigned char){operand} << 3 )"
elif opcode == 0x0B:
return f"(unsigned char)( (unsigned char){operand} << 4 )"
def calculate_binary(a, b, opcode):
if opcode == 0x00:
return a & b
elif opcode == 0x01:
return a ^ b
elif opcode == 0x02:
return a | b
elif opcode == 0x03:
return (a + b) & 0xFF
elif opcode == 0x04:
return (a - b) & 0xFF
elif opcode == 0x05:
return (a * b) & 0xFF
def binary_to_string(operand_left, operand_right, opcode):
if opcode == 0x00:
return f"( {operand_left} & {operand_right} )"
elif opcode == 0x01:
return f"( {operand_left} ^ {operand_right} )"
elif opcode == 0x02:
return f"( {operand_left} | {operand_right} )"
elif opcode == 0x03:
return f"( {operand_left} + {operand_right} )"
elif opcode == 0x04:
return f"( {operand_left} - {operand_right} )"
elif opcode == 0x05:
return f"( {operand_left} * {operand_right} )"
def precalculate_unary_array():
global unary_array
sz = (0xFF + 1) * (0x0B + 1)
unary_array = [calculate_unary(a, opcode) for a in range(0x00, 0x100) for opcode in range(0x00, 0x0C)]
def precalculate_binary_array():
global binary_array
sz = (0xFF + 1) * (0xFF + 1) * (0x05 + 1)
binary_array = [calculate_binary(a, b, opcode) for a in range(0x00, 0x100) for b in range(0x00, 0x100) for opcode in
range(0x00, 0x06)]
class Tree:
def __init__(self, t, opcode=None, child_left=None, child_right=None):
self.type = t
self.opcode = opcode
self.child_left = child_left
self.child_right = child_right
def create_random_tree(depth):
if depth <= 1:
return Tree(TREE_NODE_OPERAND)
else:
t = secrets.randbelow(3)
if t == TREE_NODE_UNARY:
opcode = secrets.randbelow(0x0C)
return Tree(TREE_NODE_UNARY, opcode=opcode, child_left=create_random_tree(depth - 1))
elif t == TREE_NODE_BINARY:
opcode = secrets.randbelow(0x06)
return Tree(TREE_NODE_BINARY, opcode=opcode, child_left=create_random_tree(depth - 1),
child_right=create_random_tree(depth - 1))
else:
return Tree(TREE_NODE_OPERAND)
def delete_tree(t):
if t is not None:
if t.child_left is not None:
delete_tree(t.child_left)
if t.child_right is not None:
delete_tree(t.child_right)
t = None
def count_tree(t, operand_value):
if t.type == TREE_NODE_OPERAND:
return operand_value
elif t.type == TREE_NODE_UNARY:
return unary_array[count_tree(t.child_left, operand_value) * (0x0B + 1) + t.opcode]
elif t.type == TREE_NODE_BINARY:
return binary_array[
count_tree(t.child_left, operand_value) * (0xFF + 1) * (0x05 + 1) + count_tree(t.child_right,
operand_value) * (
0x05 + 1) + t.opcode]
def tree_to_string(t, operand):
if t.type == TREE_NODE_OPERAND:
return operand
elif t.type == TREE_NODE_UNARY:
return unary_to_string(tree_to_string(t.child_left, operand), t.opcode)
elif t.type == TREE_NODE_BINARY:
return binary_to_string(tree_to_string(t.child_left, operand), tree_to_string(t.child_right, operand), t.opcode)
def generate_tree(x, y):
while True:
t = create_random_tree(TREE_MAX_DEPTH)
if count_tree(t, x) == y:
return t
delete_tree(t)
if __name__ == '__main__':
precalculate_unary_array()
precalculate_binary_array()
with open("genka.c", "w") as f:
f.write("#include <stdio.h>\nvoid main(){\n unsigned char x, y, c;\n")
for i in range(10):
while True:
x = secrets.randbelow(256)
t = create_random_tree(3 + secrets.randbelow(5))
st = tree_to_string(t, "x")
y = count_tree(t, x)
delete_tree(t)
if x != y:
break
print(f"x = {x}, y = {y}\n{st}\n")
f.write(f" x = {x};\n")
f.write(f" y = {y};\n")
f.write(f" c = {st};\n")
f.write(f" if (c != y)\n")
f.write(f' printf("x = %d, y = %d, c = %d\\t%s\\n", x, y, c, {st});\n')
f.write("}\n")
Короче делал твою версию, бред какой-то выходит. Операции то многие не обратимыМне кажется нерационально генерировать случайные деревья и проверять потом, а не подходит ли это дерево под нашу задачу, в частности подстановка и проверка ожидаемого выхода, медленно достаточно
Мне кажется лучше генерировать случайное дерево, делать рассчет получая Y из входного X, затем просто строить обратное дерево преобразований, отзеркаливающих действия, по итогу получаем дерево, которому на вход подается Y, а на выход получаем X
Так гораздо быстрее, и не нарушается оригинальная концепция, просто вместо функции проверки формулы на валидность для нашего случая надо написать генератор дерева функции-инверсии