Можно ли сделать это значение с помощью уникальных монет и / или заметок?


29

Напишите программу, которая вычисляет, может ли введенное денежное значение в виде целого числа быть представлено уникальной комбинацией монет и / или банкнот, что означает, что одна и та же монета / банкнота не может использоваться более одного раза.

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

Ваша программа должна выводить любое значение «истина / ложь» соответственно.

Обратите внимание, что вывод списка монет / купюр, составляющих значение, не требуется.

ПРИМЕР

Использование британского фунта (£ 1,00 = 100 и £ 420,69 = 42069)

coins = [1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000]

Следующее выведет true:

6 (1, 5)
15 (10, 5)
88 (1, 2, 5, 10, 20, 50)
512 (500, 10, 2)
7003 (5000, 2000, 2, 1)

Следующий выводит false:

4
209
8889
4242424242
[ANYTHING ABOVE 8888]

АЛЬТЕРНАТИВНЫЕ ТЕСТОВЫЕ ДАННЫЕ (Доллар США)

coins = [1, 5, 10, 25, 50, 100, 200, 500, 1000, 2000, 5000, 10000]

Удачи!


4
Хотелось бы, чтобы у нас было больше новичков, как ты ...
Leaky Nun


2
Вы должны добавить несколько
Leaky Nun

2
Я бы предложил добавить тестовые случаи, которые не могут быть решены с помощью жадной эвристики получения самой большой неиспользованной монеты, то есть максимальной стоимости. Также было бы хорошо иметь такие, где входные данные не отсортированы и где значение может быть задано несколькими способами. Как правило, для тестовых случаев полезно избегать вероятности того, что кто-то предпримет разумную попытку решить проблему, которая работает для тестовых случаев, но не прав на все.
xnor

2
Относящиеся . Также связано . Первый вопрос, возможно, является дубликатом, но этот вопрос лучше разработан IMO, и если мы хотим закрыть его как дубликат, я бы предпочел закрыть старый.

Ответы:


13

Brachylog 2 (TIO Nexus), 2 байта

⊇+

Попробуйте онлайн!

Принимает список монет либо посредством стандартного ввода, либо путем добавления его к началу программы в качестве литерала массива (либо будет работать, так что вам решать, что вы считаете «более легитимным»; первое допускается по умолчанию) Правила PPCG, последнее конкретно разрешено вопросом); и принимает значение для выдачи в качестве аргумента командной строки.

объяснение

Эта программа использует детали реализации способа обертки TIO Nexus для функций брахилога; в частности, он позволяет вам указать аргумент командной строки для ввода через Output. (Это не было предусмотрено в первоначальном дизайне для Brachylog; однако языки определяются их реализацией на PPCG, и если приходит реализация, которая делает то, что мне нужно, я могу воспользоваться этим.) Это означает, что Программа выглядит так:

⊇+
⊇   Some subset of {standard input}
 +  sums to {the first command-line argument}

Как полная программа, она возвращает логическое значение; true.если все утверждения в программе могут быть выполнены одновременно, или false.если они не могут быть выполнены.

(Напомним, или для людей, которые еще не знают: Brachylog 2 использует свою собственную кодировку символов, длина которой составляет один байт.)


Вы сказали, что Bra - это один байт в брахилоге, почему бы вам не вставить сюда байты? Бьюсь об заклад, есть причина для этого, мне просто интересно, немного кусочек кодировки символов.
theonlygusti

1
Они закодированы на диске как 08 2B(вы можете посмотреть кодировки здесь ). Причина, по которой я не перечислил конкретную кодировку, заключается в том, что она не имеет значения; все, что действительно имеет значение, это то, что Brachylog использует не более 256 уникальных символов, так что каждый из них может быть представлен одним байтом. Это обычно делается языками игры в гольф, чтобы сделать код более читабельным; вместо этого они могли бы использовать кодировку, подобную кодовой странице 437, но если вы это сделаете, никто не сможет ее прочитать .

10

05AB1E , 4 байта

æOså

Объяснение:

æ      Calculate the powerset of the first input
 O     Sum each element
  s    Put the second input at the top of the stack
   å   Check whether the input is in the powerset sum.

Попробуйте онлайн!


Похоже, вы официально ввели всех в заблуждение, сжав список; p
Leaky Nun

Как только вы удалите свой сжатый список и перенесете его на вход, я удалю свой ответ (потому что к тому времени наши ответы будут одинаковыми)
Leaky Nun

Это сообщество полно гениев.
Тоби

5

Mathematica, 25 байтов

!FreeQ[Tr/@Subsets@#,#2]&

Чистая функция, принимающая массив значений coin в качестве первого аргумента и целевое число в качестве второго аргумента и возвращающая Trueили False.



3

Retina , 52 31 байт

\d+
$*
^((1+) |1+ )+(?<-2>\2)+$

Попробуйте онлайн! Принимает ввод как разделенный пробелами список монет и примечаний, за которым следует желаемое значение. Редактировать: Сохранено 18 байт благодаря @Kobi, который отлаживал мой код. Пояснение: первые две строки просто преобразуются из десятичной в унарную. Третья строка затем захватывает список монет и заметок. Чередование позволяет двигателю вернуться назад и выбрать не захватывать определенные монеты / примечания. Затем группа балансировки сопоставляет значение со всеми суффиксами в списке захвата (не обязательно, но в гольфе).


Второй вариант не работает, потому что движок не возвращается в группы 0 длины (раздражающая оптимизация). Вы можете использовать ^((1+) )+(\2?(?<-2>)|){99}$(34 байта, с ограничением по количеству монет) или ^((1+) |1+ )+(\2?(?<-2>))+$(также 34 байта).
Коби

1
@ Коби Прекрасно! Я сохранил 2 байта из обоих ответов, потому что я забыл, что (?<-2>\2?)работает, а также еще один байт из вашего второго ответа, потому что ?больше нет необходимости.
Нил


2

Java (OpenJDK 8) , 125 байт

boolean f(int[]c,int n){int l=c.length;if(l<1)return n==0;int[]a=java.util.Arrays.copyOf(c,l-1);return f(a,n-c[l-1])|f(a,n);}

Попробуйте онлайн!


Выполнение этого в лямбде может сделать это короче.
Okx

@Okx Это рекурсивно (так будет дольше), плюс я не делаю лямбды, даже если они будут короче.
Утренняя монахиня

1
Итеративная версия вашего алгоритма становится намного короче, поскольку вы избавляетесь от необходимости копировать массив: boolean f(int[]c,int n){for(int l=c.length;l-->0;n-=n<c[l]?0:c[l]);return n<1;}(79 байт). С Java 8 и его лямбдами, он может быть уменьшен до 62 байтов. Что касается вашего ответа, как это в настоящее время, int l=c.length-1то lвместо использования l-1также короче
Оливье Грегуар


2

JavaScript (ES6), 81 69 67 64 байта

Принимает список монет cи целевое количество aв синтаксисе карри (c)(a). Возвращает 0или true.

c=>g=(a,m=1)=>c.map((c,i)=>x-=c*(m>>i&1),x=a)&&!x||x-a&&g(a,m+1)

Контрольные примеры


Вам разрешено брать список монет?
Утренняя монахиня

@LeakyNun "... и может взять список значений монет / банкнот ..."
Мартин Эндер,

1
Так что я зашифровал список даром ...
Leaky Nun

@LeakyNun Кажется, что так
Эдди Харт

2

Haskell , 28 байт

Функция оператора (#)принимает целое число и список целых чисел (или, в более общем случае, любой Traversableконтейнер чисел) и возвращаетBool .

Использовать как 6#[1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000].

c#l=elem c$sum<$>mapM(:[0])l

Попробуйте онлайн!

Как это работает

  • cжелаемое значение и lсписок значений монет.
  • mapM(:[0])lкарт (:[0])над l, соединяя каждое значение с 0, а затем строит декартово произведение, давая списки , где каждый элемент является либо его соответствующее значение в l, или 0.
  • sum<$>суммирует каждую комбинацию и elem c$проверяет, есть ли cв результирующем списке.

2

R, 88 83 байта

-5 байт благодаря @Jarko Dubbeldam

возвращает анонимную функцию. Он генерирует все возможные комбинации монет (используя expand.gridпары T,F) и проверяет наличие значений. kэто монеты, так как cявляется зарезервированным словом в R. Может проверять несколько значений одновременно.

function(k,v)v%in%apply(expand.grid(Map(function(x)!0:1,k)),1,function(x)sum(k[x]))

Попробуйте онлайн!


Вы можете заменить c(T,F)на !0:1, и rep(list(!0:1),length(k))поlapply(k,function(x)!0:1)
JAD

1
Собственно, сделайте этоMap(function(x)!0:1,k)
JAD

1

Japt , 7 байт

à mx èN

Попробуйте онлайн! Выходы0 для ложных, положительное целое для правдивых.

объяснение

à mx èN
          // Implicit: U = input array, V = input integer, N = array of all inputs
à         // Take all combinations of U.
  mx      // Map each combination to its sum.
     è    // Count the number of items in the result which also exist in
      N   //   the array of inputs.
          // This returns 0 if no combination sums to V, a positive integer otherwise.
          // Implicit: output result of last expression


1

Рубин , 39 байт

Возвращает nilкак ложное значение и наименьшее значение монеты в списке, которое составляет число как правдивое (в Ruby все числа являются правдивыми).

f=->c,n{n!=0?c.find{|i|f[c-[i],n-i]}:1}

Имейте в виду, однако, что этот алгоритм безумно медленный, со O(C!)сложностью времени, где Cдлина списка монет. Это в конечном итоге заканчивается, но большинство тестовых случаев будет тайм-аут на большинстве онлайн-переводчиков, дажеf(UK_POUND, 5) .

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

f=->c,n{n>0?c.find{|i|f[c-[i],n-i]}:n==0}

Попробуйте онлайн!


1

Утилиты Bash + GNU, 56 39

printf %$2s|egrep "^ {${1//,/\}? {}}?$"

Входной список наименований (несортированный) задается в виде списка через запятую. Список ввода и значение задаются в качестве параметров командной строки.

Вывод дан в виде кода возврата оболочки. Проверьте echo $?после запуска скрипта. 0значит правдиво,1 значит ложный.

Попробуйте онлайн .

  • printf %$2sвыводит строку valueпробелов
  • "^ {${1//,/\}? {}}?$"это расширение оболочки, которое расширяет список наименований до регулярных выражений ^ {1}? {2}? {5}? {10}? ... $. Оказывается, чтоegrep движок регулярных выражений достаточно умен, чтобы правильно соответствовать этому, независимо от того, в каком порядке находятся деноминации.
  • egrep проверяет, соответствует ли строка пробелов регулярному выражению

1

C 66 байтов

m;v;f(n){for(m=1e5;m/=10;)for(v=5;n-=n<v*m?0:v*m,v/=2;);return!n;}

Видеть это работает здесь .

C, 53 байта

g(c,w,n)int*c;{for(;n-=n<c[--w]?0:c[w],w;);return!n;}

Этот вариант принимает массив монет, который побеждает цель этой задачи, потому что сводится к простому вычитанию.

Первый аргумент - это массив монет, второй - количество монет, а третий - значение.

C, 48 байтов

g(c,n)int*c;{for(;n-=n<*c?0:*c,*++c;);return!n;}

Альтернатива предыдущему варианту. Предполагается, что массив монет может быть обращен и завершен нулем.



0

CJam , 18 17 байтов

q~_,2\m*\f.*::+#)

Попробуйте онлайн!

объяснение

q~                  e# Read and eval input.
  _,                e# Duplicate the money list and take its length.
    2\m*            e# Take the (length)th Cartesian power of [0 1].
        \f.*        e# Element-wise multiplication of each set of 0's and 1's with the money
                    e#   list. This is essentially the powerset, but with 0s instead of 
                    e#   missing elements.
            ::+     e# Sum each set.
               #    e# Find the index of the desired amount in the list. (-1 if not found)
                )   e# Increment. -1 => 0 (falsy), anything else => nonzero (truthy)



0

Октава, 39 байт

 @(L,n)any(cellfun(@sum,powerset(L))==n)

Анонимная функция, которая принимает массив значений coin в качестве первого аргумента и целевое целое число в качестве второго аргумента и возвращает true или false.

Попробуйте онлайн!


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.