Wskazówka:
Zadanie możemy rozwiązać, śledząc działanie funkcji „krok po kroku”, pamiętając przy tym
o całej hierarchii wywołań rekurencyjnych. Przedstawimy nieco inne rozwiązanie, korzystające z drzewa wywołań rekurencyjnych, które utworzyliśmy, rozwiązując zadanie 1. Tworząc
drzewo, stosowaliśmy zasadę, że wywołania funkcji wieże wykonywane w trakcie działania
wieże(i, x, y, z) są wypisywane pod wywołaniem wieże(i, x, y, z), w kolejności od lewej do
prawej, zgodnie kolejnością ich wykonań w trakcie działania wieże(i, x, y, z). Na przykład
wywołanie wieże(2, A, C, B) jest wykonywane przed wieże(2, C, B, A) w trakcie wieże(3, A, B, C), co odpowiada ich kolejności „od lewej do prawej” w naszym drzewie.
Z powyższej obserwacji i treści funkcji wynika, że dla każdego węzła naszego drzewa najpierw wypisywane będą ruchy z jego „lewego poddrzewa”, potem ruch „wypisz x => y”,
a następnie ruchy z jego „prawego poddrzewa”. Na przykład dla wieże(2, C, B, A) mamy ciąg
ruchów:
C => A; C => B; A => B,
gdzie podkreślony ruch C => B jest wynikiem instrukcji „wypisz x => y” wykonanej
w wieże(2, C, B, A), a pozostałe ruchy są wynikiem wywołań rekurencyjnych.
Stosując powyższą obserwację, widzimy, że ciąg ruchów wygenerowany przez wieże(3, A, B,
C) to:
A => B; A => C; B => C; A => B; C => A; C => B; A => B,
gdzie podkreślony ruch A => B jest wynikiem instrukcji „wypisz x => y” wykonanej
w wieże(3, A, B, C), ruchy na lewo od podkreślonego A => B to efekt działania wieże(2, A, C,
B), a ruchy na prawo od podkreślonego A => B to efekt działania wieże(2, C, B, A).