Чи можна це значення зробити унікальними монетами та / або банкнотами?


29

Напишіть програму, яка розраховує, чи введена грошова вартість, як ціле число, може бути представлена ​​унікальною комбінацією монет та / або банкнот, що означає, що та сама монета / банкнота не може використовуватися більше одного разу.

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

Ваша програма повинна виводити будь-яке значення truthy / falesy відповідно.

Зверніть увагу , що висновок списку монет / приміток , які складають значення, НЕ потрібно.

ПРИКЛАД

Використовуючи британський фунт, (£ 1,00 = 100 і 420,69 £ = 42069)

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

Виведено наступне:

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

Наступне виведе помилкове:

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

Брахілог 2 (TIO Nexus), 2 байти

⊇+

Спробуйте в Інтернеті!

Приймає список монет або за допомогою стандартного введення, або заздалегідь попередньо додаючи його до запуску програми, як буквальний масив (або буде працювати, тому ви вирішуєте, чи вважаєте ви "більш законним"; колишня дозволена за замовчуванням Правила PPCG, остання спеціально дозволена питанням); і приймає значення для отримання як аргумент командного рядка.

Пояснення

Ця програма використовує деталі впровадження способу обгортки TIO Nexus для функцій Brachylog; конкретно, це дозволяє надати аргумент командного рядка, щоб дати введення через вихід. (Це не було передбачено в оригінальній розробці для Brachylog; проте, мови визначаються їх реалізацією на PPCG, і якщо впровадження відбувається разом, щоб зробити те, що мені потрібно, я можу цим скористатися.) Це означає, що програма виглядає так:

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

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

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


Ви сказали, що ⊇ - це один байт у Брахілозі, чому б вам не вставити байти тут? Б'юсь об заклад, що в цьому є причина, я просто зацікавлений, трохи набором кодування символів.
theonlygusti

1
Вони закодовані на диску як 08 2B(ви можете подивитися кодування тут ). Причиною, що я не перерахував конкретне кодування, є те, що воно не має значення; Все, що дійсно має значення, - це те, що Брахілог використовує не більше 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

Математика, 25 байт

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

Чиста функція, приймаючи масив значень монети як перший аргумент, а цільове ціле як другий аргумент, і повертаючи Trueабо False.



3

Сітківка , 52 31 байт

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

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


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

1
@Kobi Красиво! Я врятував 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)

Тестові справи


Чи дозволено вам взяти список монет?
Leaky Nun

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

1
Тож я зашифрував цей список ні за що ...
Leaky Nun

@LeakyNun Здається так
Едді Харт

2

Haskell , 28 байт

Функція оператора (#)приймає ціле число і список цілих чисел (або, загалом, будь-який Traversableконтейнер чисел) і повертає a 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це зарезервоване слово в Р. Може перевірити кілька значень одночасно.

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для помилки, додатне ціле число для truthy.

Пояснення

à 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як фальшиве значення, так і найменше значення монети у списку, що складає число як істинне (усі цифри є truthy у 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означає truthy, означає хибність 1.

Спробуйте в Інтернеті .

  • printf %$2sвиводить рядок valueпробілів
  • "^ {${1//,/\}? {}}?$"- це розширення оболонки, яке розширює список номіналів на подібний регулярний вираз ^ {1}? {2}? {5}? {10}? ... $. Виявляється, egrepдвигун regex досить розумний, щоб правильно відповідати цьому, незалежно від того, в якому порядку знаходяться номінали
  • 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)

Анонімна функція, яка приймає масив значень монет як перший аргумент, а цільове ціле - як другий аргумент, і повертає істинне або хибне.

Спробуйте в Інтернеті!


0

Математика, 42 байти

ListQ@NumberDecompose[#,Sort[#2,Greater]]&

вхід

[15, {10,5}]

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.