Czy tę wartość można uzyskać za pomocą unikalnych monet i / lub banknotów?


29

Napisz program, który oblicza, czy wprowadzona wartość pieniężna, jako liczba całkowita, może być reprezentowana przez unikalną kombinację monet i / lub banknotów, co oznacza, że ​​tej samej monety / banknoty nie można użyć więcej niż jeden raz.

Twój program powinien przyjmować wartość jako dane wejściowe i może pobierać listę wartości monet / banknotów przez dane wejściowe lub przez odpowiednik tablicy w Twoim języku. Lista monet / banknotów powinna być w stanie się zmieniać, więc upewnij się, że jest jasne, gdzie to jest zdefiniowane, jeśli używasz stałej.

Twój program powinien wypisać odpowiednio dowolną wartość prawdy / fałszu.

Należy pamiętać, że generowanie listy monet / banknotów, które składają się na wartość, nie jest wymagane.

PRZYKŁAD

Przy użyciu funta brytyjskiego (1,00 GBP = 100 i 420,69 GBP = 42069)

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

Następujące wartości wyjściowe będą prawdziwe:

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

Poniższe wyświetli wartość false:

4
209
8889
4242424242
[ANYTHING ABOVE 8888]

ALTERNATYWNE DANE TESTOWE (dolar amerykański)

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

Powodzenia!


4
Chciałbym, żebyśmy mieli więcej nowych przybyszów takich jak ty ...
Leaky Nun


2
Powinieneś dodać kilka przypadków testowych, używając innego zestawu monet
Leaky Nun

2
Sugeruję dodanie przypadków testowych, których nie można rozwiązać za pomocą chciwej heurystyki przyjmowania największej niewykorzystanej monety, czyli co najwyżej pozostałej wartości. Dobrze byłoby również mieć takie, w których dane wejściowe nie są sortowane i w których wartość można ustalić na więcej niż jeden sposób. Zasadniczo dobrze jest w przypadkach testowych unikać możliwości, że ktoś podejmie rozsądną próbę rozwiązania problemu, który działa w przypadku przypadków testowych, nie mając racji we wszystkim.
xnor

2
Związane . Również powiązane . Pierwsze pytanie jest prawdopodobnie duplikatem, ale to pytanie jest lepiej zaprojektowane przez IMO, a jeśli mamy zamknąć jedno jako duplikat, wolę zamknąć starsze.

Odpowiedzi:


13

Brachylog 2 (TIO Nexus), 2 bajty

⊇+

Wypróbuj online!

Pobiera listę monet albo za pomocą standardowego wejścia, albo przygotowując ją na początek programu jako literał tablicowy (każda z nich będzie działać, więc to od ciebie zależy, co uważasz za „bardziej uzasadnione”; ta pierwsza jest domyślnie dozwolona Zasady PPCG, te ostatnie są wyraźnie dozwolone w pytaniu); i przyjmuje wartość do wygenerowania jako argument wiersza polecenia.

Wyjaśnienie

Ten program wykorzystuje szczegóły implementacji sposobu, w jaki opakowanie TIO Nexus dla funkcji Brachylog; w szczególności pozwala podać argument wiersza poleceń, aby podać dane wejściowe za pośrednictwem Output. (Nie było to przewidziane w oryginalnym projekcie Brachylog; jednak języki są definiowane przez ich implementację w PPCG, a jeśli pojawi się implementacja, która akurat robi to, czego potrzebuję, mogę z tego skorzystać.) program wygląda następująco:

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

Jako pełny program zwraca wartość logiczną; true.czy wszystkie twierdzenia w programie mogą być jednocześnie spełnione, lub false.jeśli nie mogą.

(Przypomnienie lub dla osób, które jeszcze nie wiedzą: Brachylog 2 używa własnego kodowania znaków, w którym jest to jeden bajt.)


Powiedziałeś, że ⊇ jest jednym bajtem w Brachylog, dlaczego nie wkleisz tutaj bajtów? Założę się, że jest ku temu powód, jestem po prostu zainteresowany, trochę nub kodowania znaków.
theonlygusti

1
Są one zakodowane na dysku jako 08 2B(możesz sprawdzić kodowanie tutaj ). Powodem, dla którego nie wymieniłem konkretnego kodowania, jest to, że nie ma on znaczenia; najważniejsze jest to, że Brachylog używa nie więcej niż 256 unikalnych znaków, dzięki czemu każdy z nich może być reprezentowany w jednym bajcie. Jest to zwykle wykonywane przez języki gry w golfa, aby kod był bardziej czytelny; zamiast tego mogliby użyć kodowania takiego jak strona kodowa 437, ale gdybyś to zrobił, nikt nie byłby w stanie go odczytać .

10

05AB1E , 4 bajty

æOså

Wyjaśnienie:

æ      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.

Wypróbuj online!


Wygląda na to, że oficjalnie wprowadziłeś wszystkich w błąd, aby skompresować listę; p
Dziurawa zakonnica

Po usunięciu skompresowanej listy i przeniesieniu jej do danych wejściowych usunę moją odpowiedź (bo zanim nasze odpowiedzi będą takie same)
Leaky Nun

Ta społeczność jest pełna geniuszy.
Tobi

5

Mathematica, 25 bajtów

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

Czysta funkcja przyjmująca tablicę wartości monet jako pierwszy argument i docelową liczbę całkowitą jako drugi argument i zwracająca Truelub False.



3

Siatkówka , 52 31 bajtów

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

Wypróbuj online! Pobiera dane wejściowe jako rozdzieloną spacjami listę monet i banknotów, po której następuje żądana wartość. Edycja: Zapisałem 18 bajtów dzięki @Kobi, który debugował mój kod. Objaśnienie: Pierwsze dwa wiersze po prostu konwertują z dziesiętnego na jednoargumentowy. Trzeci wiersz przechwytuje listę monet i banknotów. Ta zmiana umożliwia silnikowi cofnięcie się i wybranie opcji, aby nie przechwytywać określonych monet / banknotów. Grupa bilansująca dopasowuje następnie wartość do wszystkich przyrostków listy przechwytywania (niepotrzebne, ale bardziej golfowe).


Druga opcja nie działa, ponieważ silnik nie powraca do grup o zerowej długości (denerwująca optymalizacja). Możesz użyć ^((1+) )+(\2?(?<-2>)|){99}$(34 bajty, z ograniczeniem liczby monet) lub ^((1+) |1+ )+(\2?(?<-2>))+$(również 34 bajty).
Kobi

1
@Kobi Beautiful! Zapisałem 2 bajty z obu odpowiedzi, ponieważ zapomniałem, że to (?<-2>\2?)działa, oraz dodatkowy bajt z drugiej odpowiedzi, ponieważ ?nie jest już potrzebny.
Neil


2

Java (OpenJDK 8) , 125 bajtów

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);}

Wypróbuj online!


Robienie tego u lambda może być krótsze.
Okx,

@Okx Jest rekurencyjny (więc byłby dłuższy), a ponadto nie robię lambda, nawet gdyby byłyby krótsze.
Leaky Nun

1
Iteracyjna wersja twojego algorytmu jest znacznie krótsza, ponieważ eliminujesz potrzebę kopiowania tablicy: boolean f(int[]c,int n){for(int l=c.length;l-->0;n-=n<c[l]?0:c[l]);return n<1;}(79 bajtów). W Javie 8 i jej lambdach można ją dodatkowo zmniejszyć do 62 bajtów. Jeśli chodzi o twoją odpowiedź taką, jaka jest obecnie, int l=c.length-1to użycie lzamiast l-1jest również krótsze.
Olivier Grégoire,


2

JavaScript (ES6), 81 69 67 64 bajtów

Pobiera listę monet ci docelową kwotę aw składni curry (c)(a). Zwraca 0lub true.

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

Przypadki testowe


Czy wolno ci wziąć listę monet?
Leaky Nun

@LeakyNun „... i może wziąć listę wartości monet / banknotów ...”
Martin Ender

1
Więc za darmo zakodowałem listę ...
Leaky Nun

@LeakyNun Wydaje się, że tak
Eddie Hart

2

Haskell , 28 bajtów

Funkcja operatora (#)pobiera liczbę całkowitą i listę liczb całkowitych (lub, bardziej ogólnie, dowolny Traversablekontener liczb) i zwraca a Bool.

Użyj jako 6#[1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000].

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

Wypróbuj online!

Jak to działa

  • cjest pożądaną wartością i llistą wartości monet.
  • mapM(:[0])lmapy (:[0])ciągu l, łącząc każdą wartość 0, a następnie tworzy iloczyn kartezjański, nadając list w którym każdy element jest albo jej odpowiednia wartość l, lub 0.
  • sum<$>sumuje każdą kombinację i elem c$sprawdza, czy cznajduje się na wynikowej liście.

2

R, 88 83 bajtów

-5 bajtów dzięki @Jarko Dubbeldam

zwraca anonimową funkcję. Generuje wszystkie możliwe kombinacje monet (przy użyciu expand.gridpar T,F) i sprawdza, czy wartości są obecne. kto monety, ponieważ cjest zastrzeżonym słowem w R. Może sprawdzać wiele wartości jednocześnie.

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

Wypróbuj online!


Można zastąpić c(T,F)przez !0:1i rep(list(!0:1),length(k))zalapply(k,function(x)!0:1)
JAD

1
Właściwie to zróbMap(function(x)!0:1,k)
JAD

1

Japt , 7 bajtów

à mx èN

Wypróbuj online! Wyjścia 0dla fałszu, dodatnia liczba całkowita dla prawdy.

Wyjaśnienie

à 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

Rubin , 39 bajtów

Zwraca nilwartość fałszowania i najmniejszą wartość monety na liście, która sprawia, że ​​liczba jest prawdziwa (wszystkie liczby są prawdziwe w Rubim).

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

Uważaj jednak, że ten algorytm jest niezwykle powolny, ze O(C!)złożonością czasową, gdzie Cjest długość listy monet. W końcu się kończy, ale większość przypadków testowych przekroczy limit czasu nawet u większości tłumaczy internetowych f(UK_POUND, 5).

Oto 41-bajtowa wersja, która kończy się znacznie szybciej, dodając dodatkowy warunek zakończenia i znacznie trudniej jest przekroczyć limit czasu

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

Wypróbuj online!


1

Narzędzia Bash + GNU, 56 39

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

Lista nazw wejściowych (nieposortowana) jest podawana jako lista oddzielona przecinkami. Lista wejściowa i wartość są podane jako parametry wiersza polecenia.

Dane wyjściowe podane w postaci kodu powrotu powłoki. Sprawdź echo $?po uruchomieniu skryptu. 0oznacza prawdę, 1oznacza fałsz.

Wypróbuj online .

  • printf %$2swypisuje ciąg valuespacji
  • "^ {${1//,/\}? {}}?$"jest rozszerzeniem powłoki, które rozszerza listę nazw do wyrażeń regularnych ^ {1}? {2}? {5}? {10}? ... $. Okazuje się, że egrepsilnik regex jest wystarczająco inteligentny, aby poprawnie się z tym dopasować, bez względu na kolejność nominałów
  • egrep sprawdza, czy ciąg spacji pasuje do wyrażenia regularnego

1

C, 66 bajtów

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

Zobacz, jak to działa tutaj .

C, 53 bajty

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

Ten wariant przyjmuje tablicę monet, która pokonuje cel tego problemu, ponieważ sprowadza się do zwykłego odejmowania.

Pierwszy argument to tablica monet, drugi to liczba monet, a trzeci to wartość.

C, 48 bajtów

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

Alternatywa dla poprzedniego wariantu. Zakłada, że ​​tablicę monet można odwrócić i zerować.



0

CJam , 18 17 bajtów

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

Wypróbuj online!

Wyjaśnienie

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

Oktawa, 39 bajtów

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

Anonimowa funkcja, która przyjmuje tablicę wartości monet jako pierwszy argument i docelową liczbę całkowitą jako drugi argument i zwraca wartość true lub false.

Wypróbuj online!


0

Mathematica, 42 bajty

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

wkład

[15, {10,5}]

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.