Даны цифры от 1 до 13 задача расположить их в таком порядке, чтобы следующее число делилось на сумму предыдущих и были использованы все числа и вывести все возможные варианты, пример: 8,4,2,7,1,11,3,9,5,10,12,6,13 , 4 делится на 8 , а 2 на сумму 4 и 8 и так далее. Наверное будет полезно знать, что сумма всех чисел составляет 91. Есть собственный код , но он очень громоздкий
-
1а вопрос в чем? – ZxNuClear Dec 30 '23 at 18:19
-
34 делится на 8 , а 2 на сумму 4 и 8 Вот блин.. а мужики-то не знают... – Akina Dec 30 '23 at 18:20
-
Bывести все возможные варианты – Григорий Dec 30 '23 at 18:37
-
1Это ваше задание. А вопрос-то какой? – Эникейщик Dec 30 '23 at 19:49
-
1https://ru.stackoverflow.com/q/453059/178988 – Qwertiy Dec 30 '23 at 21:41
2 Answers
Для того, чтобы перебирать разумное количество вариантов, и не перебирать все 6 миллиардов перестановок, хорошо бы сразу отсекать заведомо непроходные. Для этого идём с конца - в конце может стоять только число, которое является делителем оставшейся суммы (суммы ещё не построенного начала списка, а так же суммы, включая данное число).
Например, для начальной суммы 91 это 1,7,13. Если использовали в качестве последнего числа 1, то остаётся сумма 90 и подходят 2,3,5,6,9,10 и так далее.
Рекурсивно обрабатываем набор и сумму без выбранного числа.
Работает для данного количества мгновенно, оптимизировать дальше не стал (потенциал - формирование списка-решения, замена сета на битовый набор или что-то другое), 67 решений (пруф количества)
nums = set(range(1,14))
sm = sum(nums)
def work(nums, sm, ls = []):
if sm==0:
print(ls)
else:
for x in nums:
if sm%x==0:
work(nums-{x}, sm-x, [x]+ ls)
work(nums, sm)
- 53,555
-
Я попробовал рекурсию слева-направо. Примерно в два раза быстрее. – Stanislav Volodarskiy Dec 31 '23 at 17:59
-
Вот как... Мне умозрительно казалось, что справа быстрее отсечение происходит, но, видимо, разницы особой нет. – MBo Dec 31 '23 at 19:26
Тут есть два варианта решения задачи. Код писать не буду, напишу только как вариант решения.
Первый вариант. Долгий, не практичный
В цикле while каждый раз вызываем рандомное число, далее создаем условия.
Если сумма делиться на рандомное число без остатка, то записываем его в список. И прибовляем к сумме
Если число уже есть в списке, или оно не делится без остатка на рандомное число, то пересаздаём число.
Также нужно создать условие, на праверку дклимости всех доступных чисел. Чтобы небыло бесконечного пересоздания чисел. И при надобновсти он мог начать всё заного
И в конце условие. Если длина списка равн 13. Выводим список и пишем break
Способ не самый лучший, но с помощью него можно добиться успеха, наверное. Но это каждый раз будет отнимать рандомное время.
Второй вариант решения задачи:
Создаем 13 циклов фор, где будет происходить следующие действия:
Прогоняем по списку, проверяя, если число было, то двигаемся дальше. Если число не делиться баз остатка, то двигаемся дальше. Если мы вернулись к первому цыклу фор, то список обновляем, сумму тоже. Если не поняли о чём я, то попробую примерно объяснить в следующем коде
L = [1,2,3,4,5,6,7,8,9,10,11,12,13]
L_rez = []
Sum = 0
For _1 in L:
Sum = _1
L_rez = [_1]
For _2 in L:
if Sum % 2 == 0 and _2 not in L_rez:
L_rez.append(_2)
Sum += _2
for _3 in L:
#и дальше в таком же темпе
Если что-то не правильно понял, извиняюсь
Есть еще такой вариан решения:
def is_valid_order(order):
for i in range(1, len(order)):
if order[i] % sum(order[:i]) != 0:
return False
return True
def generate_permutations(numbers):
if len(numbers) == 1:
return [numbers]
permutations = []
for i in range(len(numbers)):
remaining = numbers[:i] + numbers[i+1:]
for perm in generate_permutations(remaining):
permutations.append([numbers[i]] + perm)
return permutations
def find_valid_orders(numbers):
permutations = generate_permutations(numbers)
valid_orders = []
for perm in permutations:
if is_valid_order(perm):
valid_orders.append(perm)
return valid_orders
numbers = list(range(1, 14))
valid_orders = find_valid_orders(numbers)
for order in valid_orders:
print(order)
- 25,888
- 86
- 3