В алгоритме кассира представляет собой алгоритм для внесения изменения в минимальном количестве монет , который работает достаточно хорошо для большинства валютных систем. Однако, как и большинство жадных алгоритмов, он не лишен недостатков. Если валютная система настроена правильно (или просто неправильно), существуют определенные значения, в которых алгоритм Кассира не сможет найти оптимальное изменение.
Возьмите следующий пример:
У нас есть 4, 3 и 1 монеты. Мы хотим сделать 6 ¢.
Алгоритм кассира сначала выберет как можно больше наибольшей монеты (одна 4 ¢ для начала), вычтет и повторит. Это приведет к одной 4 ¢ монете и двум 1 ¢ монетам, всего 3 монеты.
К сожалению, для алгоритма есть способ сделать 6 ¢ только с двумя монетами (две 3 ¢ монеты).
Система изменений будет считаться канонической, если для всех целочисленных значений алгоритм Кассира найдет оптимальное количество монет.
задача
Ваша задача состоит в том, чтобы взять систему в качестве неупорядоченного контейнера или отсортированного упорядоченного контейнера целых чисел, представляющих значения монет, и вывести истинное значение, если системный ввод является каноническим, а в противном случае - ошибочным.
Ваша программа должна работать для всех систем, которые могут создавать любую ценность. (т.е. все системы будут иметь монету в 1 цент)
Это код гольф наименьшего количества байтов.
Контрольные примеры
Этот список ни в коем случае не является исчерпывающим, ваша программа должна работать со всеми допустимыми данными
1, 3, 4 -> 0
1, 5, 10, 25 -> 1
1, 6, 10, 25 -> 0
1, 2, 3 -> 1
1, 8, 17, 30 -> 0
1, 3, 8, 12 -> 0
1, 2, 8, 13 -> 0
1, 2, 4, 6, 8 -> 1
источник
25, 9, 4, 1
(из этого поста math.SE ) - даже если каждая монета больше суммы меньших, нежадный25, 4, 4, 4
выигрывает у жадного25, 9, 1, 1, 1
.9, 4, 1
->4, 4, 4
быть лучше, чем9, 1, 1, 1
более жесткий пример.Ответы:
Haskell,
948782 байтаЭто решение работает путем определения функции,
j
которая выполняет алгоритм кассира и сообщает нам, сколько монет использовала кассир. Затем мы проверяем вдвое больше самого большого числа в списке, предполагая, что система была канонической для всех предыдущих чисел, что выбор самой большой возможной монеты - правильный выбор.это решение предполагает, что вход отсортирован.
Для проверки достаточно удвоить наибольшее число: предположим, что система не является канонической для некоторого числа
i
, и пусть этоk
будет самое большое число в списке, не превышающееi
. Предположим, чтоi >= 2k
и система является канонической для всех чисел меньше, чемi
.Возьмите какой-нибудь оптимальный способ сделать
i
из монет, и предположите, что это не содержит монетуk
. если мы выбрасываем одну из монет, новая сумма монет должна быть большеk
или меньше чемi
- но алгоритм кассира на этом числе будет использоватьk
монету - и, следовательно, этот набор монет можно заменить равным набором монет содержит монетуk
, и, следовательно, есть набор монет, содержащий монетуk
для числаi
, и по индукции алгоритм кассира возвращает оптимальный выбор.этот аргумент действительно показывает, что нам нужно проверять только сумму двух самых больших элементов - но это занимает больше времени.
Редактировать: пять байтов от благодаря Эрджану Йохансену!
источник
let
вместоwhere
. Вы можете поместить его как|let ...
образец защиты послеf s
или внутри списка понимания.j i=last$0:[1+j(i-k)|k<-s,k<i]
.Pyth,
1815 байтТестирование
Другой вид грубой силы. Это начинается с формирования всех коллекций монет с максимум k каждой, где k - самая большая монета, которая считается последней монетой. Я считаю, что этого всегда достаточно, чтобы сформировать два набора монет с одинаковой суммой, один жадный и один короче, когда такая пара существует.
Затем я нахожу такую пару следующим образом:
Подмножества генерируются в порядке возрастания размера и лексикографически по положению на входе вторично. Сгруппируйте коллекции монет по суммам, стабильно. Каждая коллекция монет генерируется в порядке убывания, поэтому жадное решение будет первым элементом группы тогда и только тогда, когда жадное решение является оптимальным, и оно будет последним элементом лексикографически группы. Таким образом, мы находим жадное решение и фильтруем по ненулевому индексу в группе. Если набор монет канонический, это отфильтрует все, поэтому мы просто логически отрицаем результат и вывод.
Объяснение:
источник
/opt/tryitonline/bin/pyth: line 5: 28070 Killed ... Exit code: 137
на TIO? Просто не хватает памяти?PHP, 323 байта
Так же, как и другие, считать монеты до суммы двух последних элементов в массиве
Мой лучший и самый длинный ответ, я верю> 370 байт
Я даю только расширенную версию, потому что она длиннее моего ответа
Пояснение к этому ответу
Онлайн версия
Установить все в массиве на false == X
Установите все числа в массиве под вашим контролем на S
Найдены различия между последним S и другим S или 0
Начать, наконец, S в массиве
Установите все числа на D, где Last S + одно из всех различий
Начни вообще D
УСТАНОВИТЕ «T» в D значения в массиве
GOTO 5 Повторите это со всеми найденными D Я сделал это не совсем в коде
Если следующий элемент в массиве имеет X, это ложный случай, иначе True
Дополнительные шаги Разница в случае во фрагменте 3 От 1 до 4 равны 2 X Это означает, что вам нужен второй D к шагу 5. После того, как это значение в этом случае 10 все случаи истинны, я мог видеть, что существует связь между разницей и количеством в массиве, которым вы управляете, чтобы вычислить, сколько D (шаг 5) вам нужно, чтобы получить точку, прежде чем вы найдете последний ложный случай.
Вы устанавливаете несколько значений из последнего элемента непосредственно в true. Эти Точки могут иметь значение, чтобы решить, могло ли быть, что жадное число монет со следующим значением такое же, как и кратное последнему в массиве. На другой путь вы можете установить противника
Установите первого врага на 1 + Last S
С этой точки добавьте каждое значение в массив, чтобы установить следующих врагов
Начните с последнего врага Goto 2
Если у вас теперь есть враги и истинные случаи, вероятность возрастает, что количество может быть одинаковым. Чем больше D, тем меньше вероятность.
плюс? Bytes Спасибо @JonathanAllan за неправильные контрольные примеры
262 байта Почти, но не достаточно 4 неправильных контрольных примера в данный момент
контрольные примеры [1,16,256] перед должны истина после ложного
Восходящий порядок массива
объяснение
Похоже, что то, что я видел, таблица содержит значения из [1,2,3,4,5,6], и я меняю только последний элемент до 9. Для 2to3 и 4to5 мы создаем значение более низкого значения в расчет по модулю
источник
", "
когда можете разделить","
; почему вы разделяете, когда вы можете взять список; почему вы сортируете, когда вы можете взять отсортированный список? (Я также до сих пор не уверен, что метод, который вы используете, безошибочен, есть ли у вас доказательства, потому что литература, которую я пролистал, кажется, предполагает, что это сложнее, чем, как мне кажется, ваш код делает.)[1,2,5,11,17]
канонический. Может быть, взгляните на статью в моем ответе.JavaScript (ES6), 116
125 130Для этого необходимо, чтобы входной массив был отсортирован в порядке убывания. Для каждого значения от 2N до 2 (N является максимальным значением монеты), он находит количество монет из жадного алгоритма и пытается найти меньший набор монет.
Меньше гольфа
Контрольная работа
источник
Python,
218 211205 байт-1 байт благодаря @TuukkaX (пробел может быть удален между
<3
иor
)repl.it
Ввод в порядке убывания.
Ужасная грубая сила. Любой набор монеты из одной единицы и другой монеты является каноническим. Для больших наборов наименьший случай неудачи, если он существует, будет больше или равен 3-й самой маленькой монете (не уверен сам, как она может быть равной!) И меньше суммы двух самых больших монет - см. Эту статью (которая на самом деле ссылается на другой, но также дает метод O (n ^ 3).
g
подсчитывает монеты, используемые жадным методом, а безымянная функция обходит возможные кандидаты (фактически от 0 до одной, в два раза меньшей, чем самая большая монета для сохранения байтов) и ищет любую коллекцию из меньшего числа монет, которая также суммируется с этой суммой.g
работает, выполняя то , что кассир будет, она рекурсивно занимает самую большую монету меньше или равна сумме , по- прежнему , чтобы компенсировать ,[v for v in c if v<=x][0]
прочь, и подсчитывает количество монет , используемыхn
.Безымянная функция возвращает 1, если
len(c)
меньше 3, и в противном случае проверяет, что это не так,1-...
что любые значения в диапазоне возможностейrange(c[0]*2)))
возможны при меньшем количестве монетi in range(g(x,c))
путем создания коллекции такого количества каждой монеты,c*i
и исследуя все комбинацииi
монет,combinations(c*i,i)
чтобы узнать, есть ли какая-либо сумма к одному и тому же значению.источник
3or
должно сработать.not(...)
на1-...
Желе ( вилка ),
1514 байтЭто решение использует границы контрпримеров из этой статьи . Там автор использует жесткую границу для контрпримера, но в интересах игры в гольф используется диапазон суммы номиналов монет, который больше и содержит эту границу.
Эта программа вычисляет все тестовые случаи менее чем за секунду на моей машине.
К сожалению, это зависит от ветки Jelly, где я работал над реализацией атома решения Frobenius, поэтому вы не можете попробовать это онлайн.
использование
Производительность хорошая и может решить все тестовые случаи одновременно менее чем за секунду.
объяснение
источник
JavaScript (ES6),
144132124122110 байтовТребует сортировки массива в порядке убывания. Использует наблюдение в связанной статье, что если система не является канонической, то существует хотя бы одно значение меньше 2a [0], которое требует меньше монет при разложении с использованием неиспользованных монет из исходного алгоритма жадности.
Изменить: 12 байт, поняв, что я могу проверить все монеты, даже если я уже достиг целевого значения. Сэкономил 8 байтов, переключив мой промежуточный выход с
[l,b]
на[b,-l]
; это позволило мне передать первый результат непосредственно в качестве параметра второго вызова, а также небольшое сохранение, определяющее, был ли второй вызов успешным. Сэкономили 2 байта, переместив определениеg
вsome
обратный вызов, что позволило мне избежать ненужной передачи переменной цикла дважды. Сэкономили 12 байт, переключившись с моей рекурсивной вспомогательной функции на вызовfilter
(стало возможным благодаря моему промежуточному выходному переключателю).источник
Perl, 69 байт
Включает +2 для
-pa
Дайте монеты в порядке убывания на STDIN. При желании вы можете оставить
1
монету.coins.pl
:Наращивает количество монет, используемых алгоритмом кассира,
@G
на суммы от 1 до двойной самой большой монеты. Для каждой суммы проверяется, что, если эта сумма уменьшается на 1 монету, алгоритму кассира требуется не более 1 монеты меньше. Если нет, то это контрпример (или ранее был контрпример). Я мог бы остановиться на первом контрпримере, но это занимает больше байтов. Таким образом, сложность времени есть,O(max_coin * coins)
а сложность пространстваO(max_coin)
источник