Przeczytaj
Zadanie 1. Znaczki pocztowe
Pani Rekursywna ma kolekcję znaczków. Każdy znaczek określony jest -cyfrową liczbą oznaczającą rok (cztery pierwsze cyfry od lewej strony) oraz miesiąc powstania (dwie cyfry z prawej strony) znaczka.
Przykładowe dane:
201302
201709
201310
Pani Rekursywna chce znaleźć znaczki, które zostały wydrukowane w 2013 roku, oraz uporządkować je w kolejności od najnowszego do najstarszego.
Plik znaczki.txt
zawiera 300 wierszy z oznaczeniami znaczków, które posiada pani Rekursywna. Każde oznaczenie zapisane jest w osobnej linii.
Napisz program (w wybranym języku programowania), który znajdzie i uporządkuje poszukiwane kody znaczków od najnowszego do najstarszego, a następnie zapisze je w pliku znalezione.txt
, każdy kod w osobnej linii.
Do oceny oddajesz:
plik
znalezione.txt
zawierający odpowiedź (uporządkowane od najnowszego do najstarszego kody znaczków, każdy kod zapisany w osobnej linii)plik(i) z komputerową realizacją zadania (kodem programu)
Przedstaw rozwiązanie zadania w postaci programu napisanego w wybranym języku programowania. Zadbaj o prawidłowe wczytanie i zapisanie danych z/do pliku tekstowego. Odpowiedź do zadania znajdziesz w osobnym pliku umieszczonym pod omówieniem pseudokodu.
Rozwiązanie
Rozwiązanie zadania przedstawimy w postaci pseudokodu, ponieważ na egzaminie maturalnym można korzystać z wybranego języka programowania: C++, Java lub Python.
Do rozwiązania zadania potrzebna będzie tablica zawierająca znaczki wyprodukowane w 2013 roku. Następnie, w celu uporządkowania ich w kolejności od najnowszego do najstarszego, skorzystamy z dwóch algorytmów sortowania. Przyjmujemy indeksowanie tablic od , tak jak jest to reprezentowane w komputerze.
Pierwszym będzie sortowanie bąbelkowe, które ma dużą czasową złożoność obliczeniową . Dokładne informacje na temat działania tego algorytmu znajdziesz w e‑materiale Sortowanie bąbelkoweSortowanie bąbelkowe.
Drugim algorytmem, który przeanalizujemy, będzie sortowanie szybkie. Ma ono lepszą złożoność czasową: liniowo‑logarytmiczną . Zagadnienie to zostało omówione w e‑materiale Sortowanie szybkieSortowanie szybkie.
Przykładowe rozwiązanie
Główną część kodu rozpoczynamy od wczytania danych z pliku oraz zadeklarowania długości tablicy ze znaczkami. [linie kodu 1, 2]
Następnie deklarujemy pustą tablicę przeznaczoną do przechowywania znaczków wydrukowanych w 2013 roku oraz zmienną, do której będziemy zapisywać liczbę tych znaczków. [linie kodu 4, 5]
Kolejnym krokiem jest iteracja po wszystkich elementach tablicy
Znaczki
w celu odnalezienia tych, które zostały wyprodukowane w 2013 roku. Kiedy natrafimy na taki znaczek, zapisujemy go do tablicyZnaczki2013
na pierwszą wolną pozycję oraz zwiększamy zmiennąliczbaZnaczków2013
. [linie kodu 7, 8, 9, 10]W tym momencie następuje wywołanie funkcji sortującej, której implementację omówimy, uwzględniając wybrany wariant sortowania. [linia kodu 12]
Ostatnim krokiem jest zapisanie posortowanych danych do pliku wynikowego. [linie kodu 14, 15]
Sortowanie bąbelkowe
Definiujemy funkcję sortowania bąbelkowego, która ułoży dane w tablicy w kolejności niemalejącej. [linia kodu 1]
Inicjujemy pętlę, która pozwoli nam przejść po każdym indeksie komórki w tablicy tyle razy, ile wynosi długość tablicy. Definiujemy zmienną
zamiana
, która będzie przechowywać informację, czy w danej serii porównań nastąpiła zamiana. Liczba przejść po tablicy gwarantuje, że dla najgorszego przypadku (tablica posortowana odwrotnie do ustalonego porządku) wszystkie elementy znajdą się na odpowiednich pozycjach. W drugiej pętli pomijamy pierwszy indeks, ponieważ każda komórka sprawdzana jest z poprzednią (musimy zatem uważać, żeby nie wyjść poza zakres tablicy). [linie kodu 2, 3, 4]Sprawdzamy, czy następny element w tablicy nie jest większy od obecnie badanego. Jeżeli jest, zamieniamy ich kolejność oraz ustawiamy wartość zmiennej
zamiana
na prawdę. [linie kodu 6, 7]Jeżeli w poprzedniej serii porównań nie wystąpiła zamiana, oznacza to, że elementy są już posortowane i możemy przerwać działanie pętli. [linia kodu 8]
Sortowanie szybkie
Definiujemy funkcję sortowania szybkiego, która będzie dzielić tablicę na części, a następnie sortować je osobno. [linia kodu 1]
Sprawdzamy, czy tablica, na której chcemy dokonać podziału, nie jest jednoelementowa. [linia kodu 2]
Wywołujemy funkcję, która wyznaczy punkt podziału tablic. [linia kodu 3]
Inicjujemy rekurencyjnerekurencyjne wywołanie funkcji dla utworzonych podtablic. [linie kodu 4, 5]
Definiujemy funkcję, która wyznaczy element środkowy
punktPodziału
, a następnie ułoży dane według następującej zasady:punktPodziału
na środku, równe lub mniejsze odpunktPodziału
po lewej stronie tablicy, większe odpunktPodziału
po prawej stronie tablicy. [linia kodu 1]Wybieramy element środkowy (na przykład ostatni). Następnie w zmiennych
i
orazj
zapisujemy miejsca przed pierwszym oraz za ostatnim elementem tablicy, którą chcemy posortować. [linie kodu 2, 3, 4]Zwiększamy indeks
i
, do momentu znalezienia elementu tablicy większego niżpunktPodziału
. Indeksj
zmniejszamy, aby w końcu znaleźć element mniejszy odpunktPodziału
. [linie kodu od 6 do 11]Po znalezieniu mniejszego elementu zmieniamy te elementy, aby uzyskać w podtablicach odpowiednie wartości. [linie kodu 12, 13]
Powtarzamy dwa powyższe punkty do momentu, gdy
i
osiągnie wartość większą lub równąj
. Wtedy zwracamyj
, czyli punkt podziału tablicy. [linie kodu 14, 15]
Odpowiedź do zadania
Prawidłowe wyniki dla danych z pliku:
Słownik
określenie liczby operacji wymaganych do wykonania danego algorytmu; zależy od danych wejściowych
określenie ilości pamięci operacyjnej wymaganej do wykonania danego algorytmu; zależna od danych wejściowych
technika programowania, w której funkcja wywołuje samą siebie, aż do napotkania przypadku podstawowego, czyli takiego, którego nie da się rozłożyć na mniejsze problemy