Был теплый летний вечер ...
когда моя глупая машина решила сломаться посреди дороги по дороге обратно из супермаркета. Я отодвинул его в сторону и решил идти домой. Я открыл сундук, чтобы достать продуктовый магазин и оставшиеся вещи. Тогда я заметил, что предметы не были равномерно упакованы. В некоторых сумках были более тяжелые вещи, в то время как в других было мало более легких вещей - в некоторых даже было несколько таких вещей. Чтобы мне было легче переносить, я решил сгруппировать все в две сумки и сделать их веса как можно ближе друг к другу.
Твоя цель
состоит в том, чтобы помочь мне переставить предметы в две хозяйственные сумки таким образом, чтобы разница между обеими сумками была близка к нулю, насколько это возможно.
Математически:
ВЕС ЛЕВАЯ РУКА - ВЕС ВПРАВО РУКА ≈ 0
пример
Если у меня было только 2 предмета - хлеб и арахисовое масло, а вес хлеба - 250 грамм, а арахисового масла - 150 грамм, то лучше всего переносить их отдельно двумя руками.
W LH - W RH = W (ХЛЕБ) - W (P.BUTTER)
250 - 150 = 100
Другая возможность:
W (ХЛЕБ, P.BUTTER) - W (пустая рука) = (250 + 150) - 0 = 400
Это не лучше, чем в нашем первом случае, поэтому вы должны пойти с первым.
Ваш код должен
- введите числа, указывающие на вес предметов в корзине. Единицы измерения не важны, но они должны быть одинаковыми (в идеале килограммы или граммы). Ввод может быть сделан один за другим или все сразу. Вы можете ограничить общее количество до 20 пунктов, если хотите.
- Формат ввода / тип зависит от вас, но ничего другого не должно быть, кроме весов.
- Разрешен любой язык, но придерживайтесь стандартных библиотек.
- Вывод на дисплей. Опять же, вы можете выбрать формат, но объясните формат в своем посте. то есть, как мы можем сказать, какие из них являются левосторонними, а какие - правосторонними.
Точки
- Самый короткий код выигрывает.
намек
Два возможных алгоритма, о которых я мог подумать, - это дифференцирование (быстрее) и перестановки / комбинации (медленнее). Вы можете использовать эти или любые другие алгоритмы, которые делают эту работу.
Ответы:
Pyth, 9 байт
Форматы ввода, вывода:
Демонстрация.
Это работает, потому что
y
возвращает подмножества в таком порядке, что каждое подмножество и его дополнение равноудалены от центра. Поскольку сумма подмножества и сумма его дополнения всегда будут равноудалены от центра, список послеosNyQ
также будет иметь это свойство. Таким образом, центр двух элементовosNyQ
является дополнением и должен иметь оптимальное разбиение. Мы извлекаем первый из этих двух элементов и печатаем его.источник
s
что изменил , и это перестало работать. Людям не понравились изменения, и ваш комментарий был последним толчком, который мне понадобился, чтобы вернуть его обратно.Pyth, 16
Это принимает входные данные как питонический список на STDIN. В результате получается список из 2 списков, первый из которых представляет собой товары в одной сумке, а второй список представляет товары во второй сумке. Этот перебор форсирует все комбинации, поэтому он будет работать очень медленно (или не хватит памяти) для больших входов.
Попробуйте это онлайн здесь
Для поддержки обработки только одного ввода это доходит до 17:
Это напечатает значения, которые идут в одну руку.
источник
[[2], [1], [1]]
, но я думаю, что оно работает именно благодаря тому, как именно это./
работает.[[x], []]
,?CJam,
1918 байтовЭто анонимная функция, которая извлекает массив целых чисел из стека и возвращает массив целых чисел, разделенных пробелом.
Спасибо @ jimmy23013 за его оригинальный
:*
трюк, который сэкономил 1 байт.Попробуйте онлайн в интерпретаторе CJam .
Как это работает
Обозначим общий вес сумок с W . Затем, если мешки в одной руке весят W / 2 - D / 2 , то мешки в другой руке должны весить и W - (W / 2 - D / 2) = W / 2 + D / 2 .
Мы пытаемся свести к минимуму разность D . Но (W / 2 - D / 2) (W / 2 + D / 2) = W ^ 2/4 - D ^ 2/4 , которая становится больше, когда D становится меньше.
Таким образом, максимальное произведение соответствует минимальной разности.
источник
:*
...W=
должно работать.Python 2.7,
161, 160код
Алгоритм
Проверьте, приближается ли каждая комбинация к половине общего веса. Итерируйте и найдите лучший.
вход
выход
Отображаемый кортеж идет в одну руку, а те, которые не отображаются, идут в другую (это не противоречит правилам).
источник
from itertools import*
JavaScript ( ES6 ) 117
Использование битовой маски для пробования каждого возможного разбиения, поэтому оно ограничено 31 элементом (хорошо с правилами). Как и ответ на вопрос, он выводит только одну руку. Примечание: я ищу минимальную разницу> = 0, чтобы избежать Math.abs, так как для каждого min <0 есть еще> 0, просто меняются руки.
Чтобы проверить: запустите фрагмент в Firefox, введите список чисел через запятую или через пробел.
источник
Haskell, 73 байта
Выводит список предметов в одну руку. Недостающие элементы переходят в другую руку.
Использование:
f [7,7,7,10,11]
->[7,7,7]
Для всех подпоследовательностей
s
входного спискаl
вычисляют абсолютное значение разницы в весе междуs
недостающими элементамиl
. Найдите минимум.источник
Haskell, 51 байт
Выходной формат таков, что левые веса являются положительными, а правые - отрицательными.
Чтобы сгенерировать каждое возможное разбиение, мы используем
mapM(\x->[x,-x])l
для отрицания все возможные подмножества элементов. Затем((,)=<<abs.sum)
пометьте каждый абсолютной суммой иsnd$minimum$((,)=<<abs.sum)
возьмите элемент с наименьшей меткой.Я не мог получить это бессмысленно из-за проблем с проверкой типов.
источник
snd.minimum.map((,)=<<abs.sum).mapM(\x->[x,-x])
. Это 47 байтов. (хотя у меня установлена более старая версия ...)R (234)
дольше и медленнее решение с R.
Функция:
Ожидаемый ввод - вектор с весами.
Ожидаемый результат - вектор с весами на одну руку.
пример
Человеко-читаемая версия кода:
источник
Аксиома, 292 байта
Применение грубой силы. Это минимизирует набор
потому что если это минимум
это тоже будет минимум
где (уменьшите (+, a) -reduce (+, r)) и уменьшите (+, r) 2 веса двух сумок (но эта последняя формула не находит для меня минимума в приложении). Унгольф и результаты
источник