The Algorithm kasjera jest algorytm do dokonywania zmian w minimalnej ilości monet, który działa całkiem dobrze dla większości systemów walutowych. Jednak jak większość chciwych algorytmów nie jest pozbawiona wad. Jeśli system walutowy jest skonfigurowany właściwie (lub po prostu źle), istnieją pewne wartości, w których algorytm kasjera nie znajdzie optymalnej zmiany.
Weź następujący przykład:
Mamy monety 4 ¢, 3 ¢ i 1 ¢. Chcemy zarobić 6 centów.
Algorytm kasjera najpierw wybierze tyle monet o największej wartości (jedna 4 ¢ na początek), a następnie odejmie i powtórzy. W ten sposób powstanie jedna moneta 4 ¢ i dwie monety 1 ¢, w sumie 3 monety.
Niestety w przypadku algorytmu istnieje sposób na uzyskanie 6 centów za pomocą tylko dwóch monet (dwóch monet 3 centów).
System zmian zostanie uznany za kanoniczny iff dla wszystkich liczb całkowitych, algorytm kasjera znajdzie optymalną liczbę monet.
Zadanie
Twoim zadaniem będzie wzięcie systemu jako nieuporządkowanego kontenera lub posortowanego uporządkowanego kontenera liczb całkowitych reprezentujących wartości monet i wygenerowanie prawdziwej wartości, jeśli dane wejściowe systemu będą kanoniczne, a fałsz w przeciwnym razie.
Twój program powinien działać dla wszystkich systemów, które mogą tworzyć dowolne wartości. (tzn. wszystkie systemy będą miały monetę 1 ¢)
To kod wygrywa najmniej bajtów golfa.
Przypadki testowe
Ta lista w żadnym wypadku nie jest wyczerpująca, twój program powinien działać dla wszystkich prawidłowych danych wejściowych
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
źródło
25, 9, 4, 1
(z tego postu z matematyki. SE ) - chociaż każda moneta jest większa niż suma mniejszych, nie-chciwi25, 4, 4, 4
pokonują chciwych25, 9, 1, 1, 1
.9, 4, 1
->4, 4, 4
bycie lepszym niż9, 1, 1, 1
jest lepszym przykładem.Odpowiedzi:
Haskell,
948782 bajtówto rozwiązanie działa poprzez zdefiniowanie funkcji,
j
która wykonuje algorytm kasjera i mówi nam, ile monet użył kasjer. następnie sprawdzamy do dwukrotności największej liczby na liście, zakładając, że system był kanoniczny dla wszystkich poprzednich liczb, że wybranie największej możliwej monety jest właściwym wyborem.to rozwiązanie zakłada, że dane wejściowe są posortowane.
wystarczy sprawdzenie dowodu do dwukrotności największej liczby: załóżmy, że dla niektórych liczb system nie jest kanoniczny
i
i niechk
będzie największą liczbą na liście nie większą niżi
. Załóżmy, żei >= 2k
i system jest kanoniczny dla wszystkich liczb mniejszych niżi
.wybierz optymalny sposób na zrobienie
i
monet i załóż, że nie zawiera monetyk
. jeśli wyrzucimy jedną z monet, nowa suma monet musi być większak
i mniejsza niżi
- ale algorytm kasjera na tej liczbie użyłbyk
monety - i dlatego ten zestaw monet można zastąpić takim samym zestawem monet zawierający monetęk
, a zatem istnieje zestaw monet zawierających monetęk
dla numerui
, a przez indukcję algorytm kasjera zwraca optymalny wybór.ten argument naprawdę pokazuje, że musimy tylko sprawdzić sumę dwóch największych elementów - ale jest to dłuższe.
Edycja: pięć bajtów mniej dzięki Ørjan Johansen!
źródło
let
zamiastwhere
. Możesz umieścić go jako|let ...
wzorzec pof s
lub na liście.j i=last$0:[1+j(i-k)|k<-s,k<i]
.Pyth,
1815 bajtówZestaw testowy
Inny rodzaj brutalnej siły. Zaczyna się to od utworzenia wszystkich kolekcji monet o wartości do k każdej z nich, gdzie k jest największą monetą, która jest uważana za ostatnią monetę. Uważam, że zawsze wystarcza to do utworzenia dwóch zestawów monet o tej samej sumie, jednego zachłannego i jednego krótszego, ilekroć taka para istnieje.
Następnie lokalizuję taką parę w następujący sposób:
Podzbiory są generowane w kolejności rosnącego rozmiaru i leksykograficznie według pozycji na wejściu wtórnie. Stabilnie pogrupuj kolekcje monet według ich sum. Każda kolekcja monet jest generowana w kolejności malejącej, więc zachłanne rozwiązanie będzie pierwszym elementem grupy tylko wtedy, gdy zachłanne rozwiązanie jest optymalne i będzie ostatnim elementem grupy leksykograficznie. Tak więc znajdujemy chciwe rozwiązanie i filtrujemy według niezerowego indeksu w grupie. Jeśli zestaw monet jest kanoniczny, wszystko zostanie odfiltrowane, więc logicznie negujemy wynik i wynik.
Wyjaśnienie:
źródło
/opt/tryitonline/bin/pyth: line 5: 28070 Killed ... Exit code: 137
w TIO? Brakuje Ci pamięci?PHP, 323 bajtów
Tak samo jak inne liczą monety, aż suma dwóch ostatnich elementów w tablicy
Moja najlepsza i najdłuższa odpowiedź wierzę> 370 bajtów
Daję tylko wersję rozszerzoną, ponieważ jest ona dłuższa niż moja wcześniejsza odpowiedź
Wyjaśnienie tej odpowiedzi
Wersja online
Ustaw wszystko w tablicy na false == X
Ustaw wszystkie cyfry w kontrolowanej tablicy na S.
Znaleziono różnice między ostatnim S a drugim S lub 0
Zacznij od ostatniej litery S w tablicy
Ustaw wszystkie cyfry na D Where Last S + jedna ze wszystkich różnic
Rozpocznij w ogóle D
Ustaw „T” na wartości D w tablicy
GOTO 5 Powtórz to z wszystkich znalezionych DI, tak naprawdę tak naprawdę nie było w kodzie
Jeśli następny element w tablicy ma X, jest to fałszywy przypadek, inaczej Prawda
Dodatkowe kroki Różnica polega na tym, że we fragmencie 3 Pomiędzy 1 a 4 są 2 X Oznacza to, że potrzebujesz drugiego D w kroku 5. Po tej wartości w tym przypadku 10 to wszystkie przypadki prawdziwe Widziałem do tej pory, że istnieje związek między różnicą a liczbą w tablicy, którą kontrolujesz, aby obliczyć, ile D (krok 5) musisz zdobyć punkt, zanim znajdziesz ostatni fałszywy przypadek.
Ustawiasz wiele wartości z ostatniego elementu bezpośrednio na true. Punkty te mogą mieć wpływ na decyzję, czy chciwa liczba monet o następnej wartości jest taka sama, jak wielokrotność ostatniej w tablicy. Z drugiej strony możesz ustawić wroga
Ustaw pierwszego wroga na 1 + Ostatnie S.
Od tego punktu dodaj każdą wartość do tablicy, aby ustawić kolejnych wrogów
Zacznij od ostatniego wroga Goto 2
Jeśli masz teraz wrogów i prawdziwe przypadki, rośnie prawdopodobieństwo, że liczba może być taka sama. Im więcej D, tym prawdopodobieństwo maleje.
plus ? Bajty, dziękuję @JonathanAllan, aby dać mi złe przypadki testowe
262 Bajty Prawie, ale nie wystarczająco dobre 4 złe testy w tej chwili
przypadki testowe [1, 16 256] wcześniej powinny być prawdziwe po false
Rosnąca kolejność tablic
Wyjaśnienie
Wygląda na to, że to, co widziałem w tabeli, zawiera wartości z [1,2,3,4,5,6] i zmieniam tylko ostatni element do 9. dla 2to3 i 4to5 tworzymy wartość niższej wartości w obliczanie modulo
źródło
", "
kiedy możesz się podzielić","
; dlaczego dzielisz, kiedy możesz wziąć listę; dlaczego sortujesz, kiedy możesz wziąć posortowaną listę? (Nadal nie jestem pewien, czy metoda, której używasz, jest nieomylna, czy masz dowód, ponieważ literatura, którą przejrzałem, wydaje się sugerować, że jest trudniejsza niż to, co myślę, że robi twój kod.)[1,2,5,11,17]
jest kanoniczny. Może zajrzyj do artykułu połączonego w mojej odpowiedzi.JavaScript (ES6), 116
125 130To wymaga tablicy wejściowej posortowanej w kolejności malejącej. Dla każdej wartości od 2N downto 2 (N jest maksymalną wartością monety), znajduje liczbę monet z chciwego algorytmu i próbuje znaleźć mniejszy zestaw monet.
Mniej golfa
Test
źródło
Python,
218 211205 bajtów-1 bajt dzięki @TuukkaX (spacja może zostać usunięta między
<3
aor
)repl.it
Wprowadzaj w kolejności malejącej.
Okropnie brutalna siła. Każdy zestaw jednej jednostki monety i innej monety jest kanoniczny. W przypadku większych zestawów najmniejszy przypadek niepowodzenia, jeśli taki istnieje, będzie większy lub równy 3 najmniejszej monecie (nie jestem pewien, jak może być równy!) I mniejszy niż suma dwóch największych monet - zobacz ten artykuł (który w rzeczywistości odwołuje się do innej, ale daje także metodę O (n ^ 3)).
g
zlicza monety użyte w chciwej metodzie, a funkcja bez nazwy przemierza możliwych kandydatów (w rzeczywistości od 0 do jednej mniej niż dwa razy więcej niż największa moneta, aby zaoszczędzić bajty) i szuka dowolnej kolekcji mniejszej sumy, która również sumuje się do tej kwoty.g
działa wykonując co kasjer będzie, to rekurencyjnie zajmuje największą monetę mniejsza lub równa kwocie jeszcze nadrobić,[v for v in c if v<=x][0]
z dala, i zlicza liczbę monet użytychn
.Funkcja bez nazwy zwraca 1, jeśli
len(c)
jest mniejsza niż 3, a poza tym sprawdza, czy nie jest tak,1-...
że dowolne wartości w zakresie możliwościrange(c[0]*2)))
są możliwe przy mniejszeji in range(g(x,c))
liczbie monet, tworząc kolekcję tylu każdej monety,c*i
i sprawdzanie wszystkich kombinacjii
monet,combinations(c*i,i)
aby sprawdzić, czy jest to jakaś suma o tej samej wartości.źródło
3or
powinno działać.not(...)
z1-...
Galaretka ( widelec ),
1514 bajtówTo rozwiązanie wykorzystuje granice dla kontrprzykładów z tego artykułu . Tam autor stosuje ścisłe ograniczenie dla przykładu, ale w interesie golfa stosuje się zakres sumy nominałów monet, który jest większy i zawiera tę granicę.
Ten program oblicza wszystkie przypadki testowe na moim komputerze w mniej niż sekundę.
Niestety, zależy to od gałęzi Jelly, w której pracowałem nad wdrożeniem atomu Frobenius, więc nie możesz wypróbować go online.
Stosowanie
Wydajność jest dobra i może rozwiązać wszystkie przypadki testowe jednocześnie w mniej niż sekundę.
Wyjaśnienie
źródło
JavaScript (ES6),
144132124122110 bajtówWymaga sortowania tablicy w porządku malejącym. Wykorzystuje obserwację w powiązanym dokumencie, że jeśli system nie jest kanoniczny, wówczas istnieje co najmniej jedna wartość mniejsza niż 2a [0], która pobiera mniej monet po rozłożeniu przy użyciu nieużywanych monet z początkowego algorytmu chciwości.
Edycja: Zapisałem 12 bajtów, zdając sobie sprawę, że mogę sprawdzić wszystkie monety, nawet jeśli osiągnąłem już wartość docelową. Zaoszczędziłem 8 bajtów, zmieniając moje pośrednie wyjście z
[l,b]
na[b,-l]
; pozwoliło mi to przekazać pierwszy wynik bezpośrednio jako parametr drugiego połączenia, a także niewielką oszczędność wykrywającą, czy drugie połączenie zakończyło się powodzeniem. Zaoszczędziłem 2 bajty, przenosząc definicjęg
dosome
wywołania zwrotnego, co pozwala mi uniknąć niepotrzebnego dwukrotnego przekazywania zmiennej pętli. Zaoszczędziłem 12 bajtów, przełączając się z mojej rekurencyjnej funkcji pomocniczej na wywołanie dofilter
(możliwe dzięki mojemu pośredniczemu przełącznikowi wyjścia).źródło
Perl, 69 bajtów
Obejmuje +2 za
-pa
Daj monety w porządku malejącym na STDIN. Opcjonalnie możesz pominąć
1
monetę.coins.pl
:Zwiększa liczbę monet używanych przez algorytm kasjera
@G
dla kwot od 1 do dwukrotności największej monety. Dla każdej kwoty sprawdza, czy jeśli kwota ta zostanie zmniejszona o 1 wartość monety, algorytm kasjera potrzebuje najwyżej 1 monety mniej. Jeśli nie, jest to kontrprzykład (lub wcześniejszy kontrprzykład). Mógłbym zatrzymać się przy pierwszym kontrprzykładzie, ale zajmuje to więcej bajtów. Złożoność czasu jest więc złożonościąO(max_coin * coins)
przestrzeniO(max_coin)
źródło