Zadanie na 'fail' i rekurencję

0

Witam mam takie zadanie:

Korzystając z predykatu fail napisz program wypisujący wszystkie możliwe kombinacje rzutów trzema kostkami takie, że suma oczek daje podaną wartość.

Nie wiem kompletnie jak to zrobić. Próbuję i próbuję ale nic mi nie wychodzi. Póki co wykombinowałem coś takiego:

rzut(X):-X<3,write('Za mala liczba'),!,fail.
rzut(X):-X>18,write('Za duza liczba'),!,fail.

to uchroni przed podaniem nieprawidłowych danych. Ale jak do cholery znaleźć te kombinacje oczek których suma równa się X? Jeśli ktoś ma chwilę czasu i chęci to bardzo proszę o pomoc i udzielenie jakichś wskazówek bo sam ni jak nie mogę tego ruszyć. Z góry dzięki.

0

Co ostatnio taki najazd prologowców na forum? Tym lepiej, Prolog to piękny język :] Chociaż wymaga niestandardowego podejścia...

Ok, może najpierw teoria - to co chcesz zrobić to sprawdzić czy trzy wylosowane kostki (z dowolną ilością kostek byłoby w sumie niewiele trudniej jeśli się już wpadnie na sposób) dają w sumie pewną cyfrę - nazwijmy ją Szukana (Seeked).

Moglibyśmy więc napisać szkielet predykatu:

rzut(K1, K2, K3, Seeked) :- ...?

Najprościej byłoby dać się ponieść deklaratywności Prologa i napisać

rzut(K1, K2, K3, Seeked) :- K1 + K2 + K3 =:= Seeked.

To niestety nie ma szans zadziałać. Prolog stara się być inteligentny, ale królem matematyki to on nie jest. Arytmetyczna unifikacja ( =:= ) wymaga pełnej instantyzacji (firefox twierdzi że tak to się tłumaczy) poszczególnych stron równania.

Co więcej, musimy zaznaczyć że poszczególne rzuty to wyniki kostek, żeby nie otrzymać w wyniku na przykład -10 6 i 9.

W tym celu wprowadzamy predykat oczka(X) sprawdzający czy dana liczba jest prawidłową ilością oczek.

Możemy teraz napisać tak:

oczka(1).
oczka(2).
oczka(3).
oczka(4).
oczka(5).
oczka(6).
 
rzut(K1, K2, K3, Seeked) :-
        oczka(K1),
        oczka(K2),
        oczka(K3),
        K1 + K2 + K3 =:= Seeked.

I... To działa! Prolog Backtracuje sobie wyniki i ładnie podaje wszystkie możliwości. Dla wywołania np. rzut(K1, K2, K3, 4) znajdzie wszystkie możliwości, czyli [1, 1, 2], [1, 2, 1] i [2, 1, 1]. :]


...I teraz najzabawniejsza część posta. Zadanie niby rozwiązanie w kilku linijkach, ale tak naprawdę nie mamy jeszcze nic. Czemu? Bo nie użyłem fail... I szczerze mówiąc nie wiem co zrobić żeby w sensowny sposób fail regulował wyniki :(.

Tymczasowo może być to: (nazwa kodowa tego fragmentu = porażka)

oczka(1).
oczka(2).
oczka(3).
oczka(4).
oczka(5).
oczka(6).
 
rzut(K1, K2, K3, Seeked) :-
        oczka(K1),
        oczka(K2),
        oczka(K3),
        K1 + K2 + K3 =\= Seeked,
        fail.
 
rzut(K1, K2, K3, Seeked) :-
        oczka(K1),
        oczka(K2),
        oczka(K3),
        K1 + K2 + K3 =:= Seeked,
        true.

Zupełny bezsens, nie? Spróbuję nad tym jeszcze pomyśleć (bo teraz czas mnie trochę goni) i dam znać jeśli wymyślę lepszy 'algorytm'.

Tak czy inaczej mam nadzieję że chociaż trochę pomogłem...

0

Kurcze, dobry w tym jesteś :]. Dzięki Ci wielkie, właśnie o to mi chodziło.

0

Znajomo brzmiące zadanie, czyżby z Polluba? ;).

Wydaje mi się, że w tym przypadku użycie !,fail zastosowanie ma w celu uniknięcia wyszukiwania liczby oczek, dla nieprawdopodobnych wartości SUMA.

oczka(1).
oczka(2).
oczka(3).
oczka(4).
oczka(5).
oczka(6).
kostka(SUMA,_,_,_):-N<3,!, fail.
kostka(SUMA,_,_,_):-N>18,!, fail.
kostka(SUMA,K1,K2,K3):-oczka(K1),oczka(K2),oczka(K3), N=:=K1+K2+K3.
0

Jak najbardziej z polluba od mgradzi ;)

0

Halo, pomocy. Jest 2017 a my dalej mamy z tym problem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1