Perfekcyjne Tasowanie polega na podzieleniu talii kart na dwie, równe połowy, a następnie wstawienie kart z drugiej połowy do pierwszej w taki sposób, że pierwsza karta z drugiej połowy jest po pierwszej karcie z pierwszej i tak dalej dla każdej kolejnej pary kart. Przykładowo:
Talia | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|
Po tasowaniu | 1 | 5 | 2 | 6 | 3 | 7 | 4 | 8 |
Jak można zauważyć pierwszy i ostatni element w takim tasowaniu nie zmieniają pozycji. W tablicy wynikowej zgodnie z algorytmem tasowania elementy na indeksach nieparzystych są z pierwszej połowy tablicy wejściowej, a z parzystych z drugiej połowy. Należy oczywiście pamiętać, że algorytm ten pasuje jedynie do tablic o parzystej długości!
Okazuje się, że dla określonej liczby kart w talii po k tasowaniach uzyska się oryginalny układ elementów w talii. Jednak dla różnej ilości kart możliwe, że będzie potrzebna inna ilość tasowań. Za każdym razem tasowanie jest wykonywane opisywanym algorytmem. Kontynuując podany wcześniej przykład otrzymujemy:
Talia | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|
Tasowanie #1 | 1 | 5 | 2 | 6 | 3 | 7 | 4 | 8 |
Tasowanie #2 | 1 | 3 | 5 | 7 | 2 | 4 | 6 | 8 |
Tasowanie #3 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
W przypadku talii o n = 8 kartach otrzymujemy oryginalny układ kart w tablicy. Jak się jedna okazuje dla 6 kart potrzeba, aż 4 tasowań czyli tyle samo co dla 16 kart. Jednak dla talii o 12 elementach trzeba powótrzyć tasowanie, aż 10 razy! Najbardziej odporna na tasowanie jest oczywiście talia złożona z dwóch kart, gdzie po jednym tasowaniu otrzymujemy.. to samo ułożenie.
Poniższa funkcja perfekcyjneTasowanie() przyjmuje jako argument listę liczb, a jako wynik zwraca tą listę potasowaną zgodnie z algorytmem tasowania perfekcyjnego. Werjściowa tablica nie jest modyfikowana.
Przedstawiony algorytm na początku deklaruje nową liste, a następnie dla każdej pary liczb (z dwóch różnych połówek) dodawane są do nowej listy. Na koniec zwracana jest nowa lista.
W celu przetesowania funkcji wystarczy poniższy fragment kodu. Należy pamiętać, że zarówno ten kod jak i napisana funkcja nie sprawdzają poprawności danych wejściowych czyli np. czy przekazana długość tablicy jest parzysta.
Korzystając z przygotowanej wyżej funkcji perfekcyjneTasowanie() można napisać funkcję ileTasowan(), która zwróci ile razy trzeba przetasować listę, aby otrzymać z powrotem oryginalną listę. W tym jednak przypadku jako argument podawany jest jedynie ilość elementów, a nie ich konkretne wartości.
Na podstawie przekazanej wartości n funkcja sama generuje tablicę do potasowania. Zaletą takiego rozwiązania jest uproszczony system sprawdzania czy otrzymano z powrotem tablicę wejściową, ponieważ wszystkie elementy w tablicy to kolejne liczby nieujemne, więc wystarczy sprawdzić, że na i-tej pozycji jest wartość i.
W celu przetestowania kodu wystarczy wczytać od użytkownika liczbę i wypisać wynik:
Rozszerzmy definicję perfekcyjnego tasowania i przyjmijmy, że możn tasować tablice o nieparzystej liczbie elementów. Przykładowo jeśli mamy posortować tablice o 2n+1 elementach to w pierszej części będzie ich n + 1, a w drugiej n. Elementy drugiej tablicy powinny znaleźć się pomiędzy kolejnym parami elementów z tablicy pierwszej. Przykładowo dla n = 5:
Talia | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
Tasowanie #1 | 1 | 4 | 2 | 5 | 3 |
Tasowanie #2 | 1 | 5 | 4 | 3 | 2 |
Tasowanie #3 | 1 | 3 | 5 | 2 | 4 |
Tasowanie #4 | 1 | 2 | 3 | 4 | 5 |
Napisz funkcję perfekcyjneTasowanie() oraz ileTasowan() dla nowej definicji tasowania. Przetestuj napisane funkcje.