Ну, первая часть вашего вопроса о алгоритмах, которые являются действительными. Если вы определяете столько функций, сколько вам необходимо для обеспечения полноты по Тьюрингу (например, +, -, *, /, X, Y, Retval, loop, if), то вы удовлетворяете первую часть. Я рекомендую использовать функции более высокого уровня, потому что есть определенные структуры, которые будут развиваться снова и снова, и вы ускорите эволюцию, если просто включите ее в список функций для начала. Например, цикл можно разложить на if и goto, но с помощью цикла вы сэкономите ценную энергию эволюции, а также обеспечите валидность.
Однако ваша вторая часть посвящена алгоритмам, которые в конечном итоге останавливаются. Это, как известно, не имеет решения . Одна альтернатива - установить ограничение на количество инструкций, которые может выполнить программа, и прервать программу, если она нарушит это ограничение, что приведет к высоким штрафам. Или, если у вас есть терминал, который программа должна загрузить с ответом (например, Retval), вы можете просто остановить программу и проверить этот терминал.