Данный:
- Натуральное число S .
- Список из N рациональных весов W , сумма которых равна 1.
Вернуть список L из N неотрицательных целых чисел, такой что:
(1) sum(L) = S
(2) sum((S⋅W_i - L_i)^2) is minimal
Другими словами, приближайте S⋅W_i
s с целыми числами как можно ближе.
Примеры:
1 [0.4 0.3 0.3] = [1 0 0]
3 [0 1 0] = [0 3 0]
4 [0.3 0.4 0.3] = [1 2 1]
5 [0.3 0.4 0.3] = [2 2 1] or [1 2 2] but not [1 3 1]
21 [0.3 0.2 0.5] = [6 4 11]
5 [0.1 0.2 0.3 0.4] = [1 1 1 2] or [0 1 2 2]
4 [0.11 0.3 0.59] = [1 1 2]
10 [0.47 0.47 0.06] = [5 5 0]
10 [0.43 0.43 0.14] = [4 4 2]
11 [0.43 0.43 0.14] = [5 5 1]
Правила:
- Вы можете использовать любой формат ввода вообще или просто предоставить функцию, которая принимает входные данные в качестве аргументов.
Фон:
Эта проблема возникает при отображении S различных типов элементов в различных пропорциях W i относительно типов.
Другим примером этой проблемы является пропорциональное политическое представительство, см. Парадокс распределения . Последние два тестовых случая известны как парадокс Алабамы.
Как статистик, я признал эту проблему эквивалентной проблеме, возникающей при определении размеров выборки при проведении стратифицированной выборки. В этой ситуации мы хотим сделать пропорцию каждого слоя в выборке равной доле каждого слоя в популяции. - @tomi
code-golf
number
arithmetic
glebm
источник
источник
round(A + B) != round(A) + round(B)
что короткое решение требует понимания того, что здесь происходит.L[i] - S*W[i]
квадратов расстояний , вместо правила 2 и правила 3. Это будет приблизительноS*W[i]
.[0 1 2 2]
есть еще одно возможное решение для5 [0.1 0.2 0.3 0.4]
Ответы:
APL, 21
Это перевод 37-байтового ответа CJam от aditsu .
Проверьте это онлайн .
объяснение
источник
Python 2,
9583132125143У моего первого (и второго) (и третьего) алгоритма были проблемы, поэтому после (еще одного!) Переписывания и дополнительного тестирования (я очень надеюсь) правильное и быстрое решение:
Источник до минификатора теперь выглядит так:
Тесты возвращаются:
Этот алгоритм похож на другие ответы здесь. Это O (1) для num, поэтому он имеет одинаковое время выполнения для целых 10 и 1000000. Теоретически это O (nlogn) для количества весов (из-за сортировки). Если это выдержит все другие хитрые варианты ввода, он заменит алгоритм, приведенный ниже в моем наборе инструментов программирования.
Пожалуйста, не используйте этот алгоритм ни с чем, кроме гольфа. Я пошел на компромиссы в скорости, чтобы минимизировать размер источника. Следующий код использует ту же логику, но гораздо быстрее и полезнее:
Значение num существенно не влияет на скорость. Я проверил это со значениями от 1 до 10 ^ 19. Время выполнения линейно зависит от количества весов. На моем компьютере это занимает 0,15 секунды с 10 ^ 5 весами и 15 секунд с 10 ^ 7 весами. Обратите внимание, что весовые коэффициенты не ограничиваются дробными суммами, равными единице. Используемая здесь методика сортировки также примерно в два раза быстрее, чем традиционный
sorted((v,i) for i,v in enumerate...)
стиль.Оригинальный алгоритм
Это была функция в моем наборе инструментов, немного измененная для гольфа. Это было первоначально из SO ответа . И это неправильно.
Это дает приближение, но не всегда правильно, хотя сумма (outseq) == num сохраняется. Быстро, но не рекомендуется.
Спасибо @alephalpha и @ user23013 за обнаружение ошибок.
РЕДАКТИРОВАТЬ: Установите totalw (d) равным 1, так как OP указывает, что сумма весов всегда будет 1. Теперь 83 байта.
РЕДАКТИРОВАТЬ 2: Исправлена ошибка, найденная для [0,4, 0,3, 0,3], 1.
EDIT3: заброшенный некорректный алгоритм. Добавлен лучший.
EDIT4: это становится смешным. Заменен на правильный (я очень надеюсь) алгоритм.
РЕДАКТИРОВАТЬ5: Добавлен не-гольфовый код для других, которые могут использовать этот алгоритм.
источник
a([0.4, 0.3, 0.3], 1)
возвращается[0, 1, 0]
, пока правильный ответ[1, 0, 0]
.a([0.11,0.3,0.59],4)
вернулся[0, 1, 3]
. Должно быть[1, 1, 2]
.f([0.47,0.47,0.06],10)
вернулся[5, 4, 1]
. Должно быть[5, 5, 0]
.Mathematica,
67504645 символовUngolfed:
Пример:
источник
CJam - 37
Попробуйте онлайн
Объяснение:
Ноты:
Другая идея - 46
Попробуйте онлайн
Это гораздо проще и эффективнее, но, увы, немного дольше. Идея здесь состоит в том, чтобы начать с L_i = floor (S * W_i), определить разницу (скажем, D) между S и их суммой, найти индексы D с наибольшей дробной частью S * W_i (путем сортировки и получения вершины D) и увеличить L_i для этих индексов. Сложность O (N * log (N)).
источник
:e<
.JavaScript (ES6) 126
130 104 115 156 162 194После всех комментариев и тестовых случаев в ответе @ CarpetPython вернемся к моему первому алгоритму. Увы, умное решение не работает. Реализация немного сокращена, она все еще пробует все возможные решения, вычисляет квадрат расстояния и соблюдает минимум.
Редактировать Для каждого выходного элемента веса w «все» возможные значения: 2: trunc (w * s) и trunc (w * s) +1, поэтому есть только (2 ** elements) возможных решений, которые можно попробовать.
Тест в консоли Firefox / FireBug
Вывод
Это более разумное решение. Один проход массива весов.Для каждого прохода я нахожу текущее максимальное значение в w. Я меняю это значение на месте с помощью взвешенного целого значения (округляется в большую сторону), поэтому, если s == 21 и w = 0,4, мы получили 0,5 * 21 -> 10,5 -> 11. Я сохраняю это значение как отрицательное, поэтому оно не может быть найден как Макс в следующем цикле. Затем я уменьшаю общую сумму соответственно (s = s-11), а также уменьшаю общее количество весов в переменной f.
Цикл заканчивается, когда не найдено максимальное значение, превышающее 0 (все значения! = 0 были обработаны).
Наконец я возвращаю значения, измененные на положительные снова. Предупреждение: этот код изменяет массив весов на месте, поэтому его нужно вызывать с копией исходного массива
Моя первая попытка
Не очень разумное решение. Для каждого возможного результата он оценивает разницу и сохраняет минимум.
Ungolfed И объяснил
источник
CJam, 48 байтов
Прямое решение проблемы.
Ввод идет как
Объяснение:
Попробуйте онлайн здесь
источник
Pyth: 40 байт
Это определяет функцию
g
с 2 параметрами. Вы можете назвать это какMhosm^-*Ghded2C,HNfqsTGmms+*G@Hb}bklHyUHg5 [0.1 0.2 0.3 0.4
.Попробуйте онлайн: Pyth Compiler / Executor
Объяснение:
Это создает все возможные решения
L
, гдеL[i] = floor(S*W[i])
илиL[i] = floor(S*W[i]+1)
. Например, ввод4 [0.3 0.4 0.3
создает[[1, 1, 1], [2, 1, 1], [1, 2, 1], [1, 1, 2], [2, 2, 1], [2, 1, 2], [1, 2, 2], [2, 2, 2]]
.Только
[[2, 1, 1], [1, 2, 1], [1, 1, 2]]
остаться.источник
Mathematica 108
объяснение
Ungolfed
IntegerPartitions[s,{Length@w},0~Range~s]
возвращает все целые разбиенияs
, используя элементы , взятые из набора{0, 1, 2, ...s}
с ограничением , что выходной сигнал должен содержать такое же количество элементов , как в наборе весов,w
.Permutations
дает все упорядоченные расположения каждого целочисленного раздела.{Tr[(s *w-#)^2],#}
возвращает список упорядоченных пар{error, permutation}
для каждой перестановки.Sort[...]
сортирует список{{error1, permutation1},{error2, permutation2}...according to the size of the error.
[[1,2]]]
илиPart[<list>,{1,2}]
возвращает второй элемент первого элемента в отсортированном списке{{error, permutation}...}
. Другими словами, он возвращает перестановку с наименьшей ошибкой.источник
R
858076Использует метод Hare Quota.
Удалена пара после просмотра спецификации, которую W составит 1
Тестовый забег
источник
Python,
139128117 байтПредыдущий раствор itertools, 139 байт
источник
O(S^len(W))
самом деле: P. Новое решение намного быстрее, но все еще медленноеОктава
8776Golfed:
Ungolfed:
(Взорвано «endfor» и «endfunction»! Я никогда не выиграю, но мне нравится играть в гольф с «настоящим» языком.)
источник
zeros(size(w))
на0*w
.T-SQL,
167265Потому что мне нравится пробовать и решать эти задачи в запросе.
Превратил это в встроенную функцию, чтобы лучше соответствовать спецификации и создал тип для данных таблицы. Это стоило немного, но это никогда не будет претендентом. Каждое утверждение должно выполняться отдельно.
В использовании
источник