Dana jest pewna liczba początkowa x i końcowa y. Napisz algorytm, który przy użyciu podanych operacji arytmetycznych zwróci ile najmniej trzeba wykonać kroków, aby z x uzyskać y.
Zakładamy, że liczby 0 ≤ x, y ≤ 100 000. Operacja jest zdefiniowana przez parę (znak, liczba). Przykładowo para (+, 2) oznacza, że x' = x + 2. Zakładamy, że poprawne operacje to dodawanie, odejmowanie, mnożenia oraz dzielenie (pod warunkiem, że wynikiem operacji jest liczba całkowita).
Program musi przeszukać wszystkie możliwe rozwiązania. Należy jednak zauważyć, że takie obliczenia należy odpowiednio ograniczyć. Otóż mogą zostać zdefiniowane dwie przeciwne operacj. Wtedy program może błąkać się pomiędzy dwoma wartościami. Przykładowo jeśli mamy operacje +1, -1 to program będzie przechodził przykładowo pomiędzy 1 i 2.
Podobny problem pojawia się podczas przeszukiwania BFS grafu. Zabezpieczenie algorytmu przed wpadnięciem w nieskończoną pętle polega na przechowywaniu / odznaczaniu elementów już odwiedzonych. Dzięki temu algorytm w momencie napotkania tego samego wierzchołka już drugi raz nie wykonuje dla niego określonych operacji.
Zauważmy, że przekształcenia liczby x na y możnaby przedstawić w postaci grafu. Program jednak nie będzie generował grafu dla wszystkich możliwych wyników, ponieważ nie ma to większego sensu - wszystkie gałęzie można na bieżąco określić. Ważne jest, aby po odwiedzeniu kolejnej liczby sprawdzić czy nie była już przeglądana. Jeśli tak to algorytm kończy przeglądanie, a jeśli nie to kontynuuje. Możliwy zakres liczb również pozwala ograniczyć ilość potrzebnych operacji.
W programie zostaną wykorzystane dwie struktury. Pierwsza z nich przypomina krok wykonywany w agorytmie BFS. W tym przypadku będzie przetrzymywana obliczona kolejna wartość przekształcenia oraz poziom czyli ile do tej pory wykonano operacji.
Z kolei druga struktura dotyczy przechowywania informacji o możliwej operacji arytmetycznej.
Funkcja ileOperacji() przyjmuje następujące argumenty: x i y tj. początkowa i końcowa wartość, operacje - możliwe przekształcenia oraz min i max zakres poszukiwań. Jako wynik zostaje zwrócona liczba, która określa ile potrzeba przekształceń, aby z x otrzymać y, albo -1 jeśli jest to niemożliwe.
Na początku deklarowana jest pusta lista oraz kolejka. Do kolejki dodawany jest pierwsze "węzeł" tj. wartość początkowa o poziomie 0 (czyli, że żadna operacja nie została wykonana). Dopóki kolejka nie jest pusta to pobierany jest element z początku kolejki. Następnie należy sprawdzić czy jest on elementem szukanym. Jeśli tak to należy go zwrócić. W przeciwnym wypadku do kolejki należy dodać wszystkie możliwe przekształcenia na wartości, które do tej pory nie były przeglądane i które mieszczą się w zakresie.
Funkcję do wykonania operacji jest najwygodniej zaimplementować poprzez instrukcję switch. W przypadku, gdy dana liczba nie może zostać podzielona to wystarczy zwrócić aktualną wartość. Ze względu na to, że znajduje się ona już na liście to drugi raz nie będzie rozpatrywana.
W celu przetestowania napisanego kodu można skorzystać z poniższego fragmentu programu:
Zmodyfikuj program tak, aby na koniec wyświetlił informację jakie operacje należy wykonać, aby liczbę x przekształcić w y. Postaraj się wypisać jak najmniej nawiasów. Przykładowo po podaniu następujących danych:
program powinien zwrócić: