W wielu restauracjach część produktów jest sprzedawana w konkretnej ilości. Przykładowo w McDonald's® Chicken McNuggetsTM są sprzedawane w pudełkach po 4, 6, 9 i 20. Oznacza to, że często nie jest możliwe zamówienie tylu kurczaków ile byśmy chcieli. McNuggetowy problem ma za zadanie podpowiedzieć czy istnieje szansa uzyskać żądaną liczbę n wybranego produktu.
Załóżmy, że do restauracji przychodzi grupka 7 osób. Chcieliby kupić tyle Chicken McNuggetsTM, aby można je było równo rozdzielić. W tym celu należy sprawdzać każdą wielokrotność 7. Niestety 7 jest niemożliwe do uzyskania, ponieważ kupując pudełko z 6 nie ma możliwości dokupienia jednej sztuki. Można by spróbować kupić pudełko z czterema, ale wtedy też nie można uzyskać pozostałych 3. W tym przypadku odpowiedzią jest 21, ponieważ można kupić 2 pudełka po 6 i jedno po 9 co daje w sumie 21. Wtedy każdy zje po 3 sztuki.
Każda możliwa liczba sztuk do uzyskania to kombinacja liniowa liczb 4, 6, 9 oraz 20. Ze względu na fakt, że 20 jest wielokrotnością 4 to kombinacja liniowa upraszcza się do 4, 6, 9. Do rozwiązania zadania można użyć algorytmu chciwego. Należy jednak pamiętać, że bardzo często istnieje więcej niż poprawna konfiguracja kurczaków, aby uzyskać daną liczbę.
Na początek warto napisać funkcję czyKupie(), która odpowie na zasadnicze pytanie: czy dana liczba n jest kombinacją liniową liczb 4, 6 oraz 9. W tym celu wystarczy począwszy od największej liczby zmniejszać wartość n, a na koniec sprawdzić czy w pudełkach jest dokładnie taka ilość jak chcieliśmy:
Funkcja korzysta z funkcji zdejmij(), która odejmuje od wartości n wartość a dopóki jest taka możliwość. Pozwala to na uniknięcie powtarzania trzy razy pętli while.
W celu znalezienie wszystkich konfiguracji dla danej liczby n warto wykorzystać rekurencję, aby sprawdziła wszystkie konfiguracje i wypisała je o ile znaleziona konfiguracja w sumie daje liczbę n. Wszystkie poprzednie liczby będą przechowywane w utworzonej wcześniej liście. Nietrudno się domyślić, że dana liczba n może mieć maksymalnie cztery razy mniej niż wynosi n składników co wynika z faktu, ze najmniejsze pudełko zawiera 4 sztuki.
Tego typu zadanie jest nieco trudniejsze i warto rozbić je na prostsze funkcje. Dane będą wypisywane bezpośrednio na konsole przez co nie istnieje potrzeba zapamiętywania znalezionych rozkładów. Pisanie kodu najlepiej zacząć od funkcji czyKupieRozklad(). Funkcja ta alokuje pamięć gdzie zapisane zostaną kolejne liczby rozkładu:
(2.) Alokacja listy w zależności od liczby n. (3.) Wywołanie funkcji sprobujKupic(), która sprawdza kolejne konfiguracje pudełek. (4.) Dealokacja używanej pamięci.
Dobieraniem kolejnych pudełek zajmuje się funkcja sprobujKupic(), która w każdym wywołaniu sprawdza ile ma sztuk i dobiera kolejne. Funkcja znajduje wszystkie prawidłowe konfiguracje. Podczas szukania istnieje założenie, że w następnym wywołaniu dobierane jest pudełko zawierające nie więcej sztuk niż dołożono poprzednio:
(2.) Sprawdź czy można dołożyć jakiekolwiek pudełko. Jeśli tak to (3. - 17.) sprawdź dla każdego rodzaju pudełka czy można je dołożyć oraz czy dokładane pudełko jest nie większe niż poprzednio dołożone. Po wybraniu pudełka (4.) dokup pudełko, (5.) szukaj następnego pudełka (albo wypisz rozkład), ale przed próbą dołożenia kolejnego pudełka (6.) zwróć "zakupiony" produkt.
(18.) Jeśli nie można dołożyć już żadnego pudełka to: (19.) sprawdź czy zakupiono n sztuk we wszystkich pudełkach. Jeśli tak to (20. - 22.) wypisz znaleziony rozkład.
W trakcie wybierania kolejnych pudełek dochodzi do ich zakupu poprzez funkcję dokup(). Funkcja ta polega na (2.) dopisaniu jakie pudełko został zakupione oraz (3.) zmniejsza ile zostało sztuk do kupienia.
Po sprawdzeniu wszystkich możliwości z daną konfigurację istnieje potrzeba zwrócenia zakupionego towaru, dlatego została napisana funkcja zwroc(), która (2.) usuwa ostatni element na liście zakupionych pudełek oraz (3.) zwiększa ilość sztuk do zakupienia:
Poniższa funkcja main() wczytuje od użytkownika ile sztuk chciałby zakupić, a poniżej wypisane zostają wszystkie możliwe konfiguracje, aby taki wynik uzyskać:
Napisz program, który wczyta od użytkownika liczbę k, a następnie listę liczb o k elementach. Następnie program powinien spytać o liczbę n - ile sztuk chciałby zakupić użytkownik. Program powinien na ekran wypisać wszystkie możliwe konfiguracje dla podanej liczby używając tylko pudełek wczytanych początkowo na liście.
Przykładowo dla danych:
Program wypisze na ekran: