Как и говорил, хочу подробнее рассказать о том, как реализована программа на данный момент, чтобы можно было оценить насколько удачно я придумал сам алгоритм. Постараюсь максимально подробно, с картинками, чтобы было наглядно.
Ну чтож, поехали!
1| Все начинается с загрузки файла, содержащего параметры артефактов. Эту условную “БД” я поместил в json файл, поскольку понятная структура, объектов не так много, удобно хранить и обрабатывать. Ниже пример структуры:

Как можно понять, взял я точку отсчета артефакты с редкостью “обычные”, качеством 100% и потенциалом 0, думаю в этом моменте вопросов возникнуть не должно. Данные из этого файлика будут подгружаться в основную программу.
2| Далее происходит инициализация входных данных в виде контейнера (его вместительности и защиты) и желаемых баффов в понятной форме: “Название баффа”: “Значение”. Этих баффов может быть сколько угодно, хоть все сразу.
Важный момент : желаемое значение конкретного баффа может быть любым путем использования знака “*”, что говорит программе о том, что данный бафф просто должен присутствовать в итоговой сборке, но его значение не имеет границ.

Буду предоставлять выдержки из окна среды разработки для лучшей наглядности.
3| После входим в основной цикл в котором первым делом мы формируем список артов, которые содержат нужные нам баффы. Лучше для начала показать на примере: возьмем входные параметры из скрина сверху и посмотрим какой список подходящих артефактов программа нам предлагает.

Красный - сам артефакт
Зеленый - показывает, что у арта 2 баффа из вводимых пользователем
Желтый - 1 бафф из вводимых пользователем.
Таким образом на этом этапе подбираются подходящие арты и сортируются сначала по кол-ву желаемых баффов, а затем по их величине. Все это нужно, что передать на следующий этап - перебора.
4| Перебор комбинаций осуществляется следующим образом:
- сначала определяем на сколько слотов мы подбираем сборку. Я задал следующее условие: если защита конта ниже 85, то ищем сборку на n-1 артефактов, где n - количество слотов в контейнере. Такое решение принято в связи с тем, что в берлоге крайне тяжело подобрать адекватную сборку на 6 слотов без контрартефакта, а также в целях оптимизации, поскольку перебор на 6 слотов займет гораздо больше времени чем на 5.
- на вход возможных артефактов подается ранее отобранный и отсортированный список, поэтому сам процесс перебора начинается с наиболее подходящих под требования пользователя артефактов. В ходе этого подбора осуществляется выбор комбинации артефактов, а затем перебор их параметров. На скрине более наглядно.

Как можно заметить, то параметры подбираются таким образом: сначала повышается качество всех артов до 106%, затем все арты повышаются до +15 потенциала, а после идут на повышение качества вплоть до 150%. Хочу объяснить почему сделал так: на мой взгляд нет смысла перебирать артефакты ниже 100%, поскольку это действительно рофло сборки и они не смогут дать более менее внятных баффов (поправьте, если не прав). Повышение сначала до 106% обусловлено тем, что вряд ли кто-то захочет использовать артефакты данной редкости на меньшем качестве, чаще всего их просто перероливают. Последующее повышение потенциала обусловлено тем, что даже необычные сборки точат до +15 и это нормально. Все эти условия были взяты сугубо из моего опыта игры и действительно могут быть не оптимальны, но я посчитал, что так лучше.
Еще одно очень важное замечание: для оптимизации времени перебора использовал функцию combinations_with_replacement из библиотеки itertools, которая создает сочетания с учетом повторений объектов, но без повторения самих комбинаций, т.е. если была проверена комбинация 1-2-3, то комбинация 3-2-1 откинется. Вспоминаем формулу
. Понимаю, что это очевидно, потому что все понимают, что порядок артов в сборке не играет роли, но решил уточнить.
каждая такая комбинация проверяется на соответствие заданным параметрам в рамках погрешности -3%…+3%.., поскольку точное значение нам не нужно и получить его крайне малая вероятность.
Перебрав и проверив все комбинации составляется список валидных сборок, которые ВНИМАНИЕ сортируются по суммарному среднему качеству таким образом, что в начале оказываются сборки с наименьшим суммарным качеством. Именно это решение и определяет, что в начале списка будут самые бюджетные из возможных комбинаций, которые дают нужны баффы. Далее все комбинации ждет следующий этап - проверка на допустимость их дебаффов.
если дебаффа сборки с учетом защиты контейнера не превышают лимитов, то сборка заносится в список допустимых. Если нет, то для нее ищется контрартефакт и подбираются параметры по уже знакомой нам схеме - он должен погасить дебаффы так, чтобы войти в лимиты организма персонажа. Если контрартефакт найден, то он добавляется в контейнер и сборка считается допустимой, иначе - недопустима.

тут изображены итерации поиска контрартов для найденых комбинаций.
если сборка не проходит по допустимым дебаффам и не имеет свободных слотов, то осуществляется перебор уже для N-1 артефактов так, чтобы свободное место для контрартефакта появилось.
по итогу прохождения всех кругом ада итераций на выход подается список допустимым комбинаций с подобранными контрартами (или допустимым дебаффами), из которых выбирается 5 уникальных сборок (то есть комбинации артов не будут повторяться) с наименьшим суммарным качеством:

часть вывода
Вроде все рассказал. С радостью поясню какие-то моменты, учту предложения, поскольку действительно мог чего-то не учесть.