Zadanie 1. Anagramy

Dwa napisy są anagramamianagramanagramami, jeśli pierwszy z nich można utworzyć przez przestawienie liter z drugiego, używając jego wszystkich znaków.

W pliku danych napisy.txt znajduje się 1000 par napisów, z których każdy jest długości od 2 do 20 znaków, składających się z wielkich liter alfabetu łacińskiego (26 liter od A do Z). Każda para napisów jest zapisana w osobnym wierszu, a napisy oddzielone są pojedynczym znakiem odstępu.

R1RRAaJKSNxcL

Przycisk do pobrania pliku TXT z wynikiem zadania.

Plik napisy.txt.
Plik TXT o rozmiarze 23.75 KB w języku polskim
Przykład 1

Przykładowe pary napisów:

  • AQWANGYBEAFTDBI HGIHPMNRAVFJGBCBGD,

  • FBJHCFYINCFPD EHADJAJOIJGDRI,

  • JHGHADJ AGFEHHEFREQQZCFC,

  • EJJHPRZWQDAIB DCAFHFXBMO,

  • IYFCNIDVBJ POYVBMJHFES.

Napisz program, który dla danych z pliku napisy.txt wyznaczy liczbę wierszy zawierających napisy będące swoimi anagramami. Wynik zapisz w pliku anagramy.txt.

Przykład 2

Dla pliku zawierającego następujące dane:

  • BBBAAB BBBABA

  • AAAA AAAAA

  • AHHAH AHHAH

  • BBABBABB BBBABB

  • BABABB CACACC

wynikiem jest liczba 2 (pierwszy i trzeci wiersz).

Do oceny oddajesz:

  • plik anagramy.txt zawierający odpowiedź (liczbę par napisów zapisanych w pliku napisy.txt będących anagramami),

  • plik(i) z komputerową realizacją zadania (kodem programu).

Praca domowa

Przedstaw rozwiązanie zadania w postaci programu w języku C++, Java lub Python. Odpowiedź do zadania znajdziesz pod omówieniem rozwiązania zapisanego za pomocą pseudokodu.

Rozwiązanie

Na egzaminie maturalnym z informatyki każdy uczeń ma możliwość wybrania jednego z dostępnych języków programowania. Z tego powodu nie będziemy dokonywać implementacji rozwiązania zadania w konkretnym języku. Zamiast tego przedstawimy je za pomocą pseudokodu.

Chcąc sprawdzić, czy podane dwa słowa są anagramami, wystarczy w obu słowach posortować litery w kolejności alfabetycznej. Jeżeli powstałe słowa będą identyczne, oznacza to, że oryginalne słowa są anagramami. W omawianym algorytmie skorzystamy z sortowania bąbelkowego.

Na początku zainicjalizujmy potrzebne zmienne i wczytajmy dane z pliku. Zmienna n będzie przechowywać liczbę par napisów do odczytania z pliku i zbadania. Zmienna anagramy będzie przechowywać liczbę wierszy z anagramami. Tablicę indeksujemy od zera, tak jak w językach programowania dostępnych na egzaminie maturalnym:

Linia 1. n ← 1000 kratka liczba par napisów w pliku. Linia 2. anagramy ← 0. Linia 3. napisy otwórz nawias kwadratowy 0 kropka kropka n minus 1 zamknij nawias kwadratowy otwórz nawias kwadratowy 0 kropka kropka 1 zamknij nawias kwadratowy ← wczytaj dane z pliku cudzysłów napisy kropka txt cudzysłów.

Zapisujemy pętlę, w której będziemy sprawdzać występowanie anagramów dla każdego wiersza. Skorzystamy z funkcji długość(), którą możemy zaimplementować w każdym z dostępnych na maturze języków programowania. Jeżeli długości wyrazów są różne, możemy pominąć sortowanie, ponieważ słowa na pewno nie są anagramami, i przejść do następnej pary:

Linia 1. n ← 1000 kratka liczba par napisów w pliku. Linia 2. anagramy ← 0. Linia 3. napisy otwórz nawias kwadratowy 0 kropka kropka n minus 1 zamknij nawias kwadratowy otwórz nawias kwadratowy 0 kropka kropka 1 zamknij nawias kwadratowy ← wczytaj dane z pliku cudzysłów napisy kropka txt cudzysłów. Linia 5. dla i znak równości 0 przecinek 1 przecinek kropka kropka kropka przecinek n minus 1 wykonuj dwukropek. Linia 6. jeżeli długość otwórz nawias okrągły Napisy otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias kwadratowy 0 zamknij nawias kwadratowy zamknij nawias okrągły wykrzyknik znak równości długość otwórz nawias okrągły Napisy otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias kwadratowy 1 zamknij nawias kwadratowy zamknij nawias okrągły dwukropek. Linia 7. przejdź do kolejnej iteracji.

Następnym krokiem będzie posortowanie obu wyrazów z pary za pomocą sortowania bąbelkowego i sprawdzenie, czy są takie same. Implementację sortowania przeanalizujemy po głównej części programu. Posortowane kopie zapisujemy do zmiennych wyraz_pierwszy oraz wyraz_drugi:

Linia 1. n ← 1000 kratka liczba par napisów w pliku. Linia 2. anagramy ← 0. Linia 3. napisy otwórz nawias kwadratowy 0 kropka kropka n minus 1 zamknij nawias kwadratowy otwórz nawias kwadratowy 0 kropka kropka 1 zamknij nawias kwadratowy ← wczytaj dane z pliku cudzysłów napisy kropka txt cudzysłów. Linia 5. dla i znak równości 0 przecinek 1 przecinek kropka kropka kropka przecinek n minus 1 wykonuj dwukropek. Linia 6. jeżeli długość otwórz nawias okrągły napisy otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias kwadratowy 0 zamknij nawias kwadratowy zamknij nawias okrągły wykrzyknik znak równości długość otwórz nawias okrągły napisy otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias kwadratowy 1 zamknij nawias kwadratowy zamknij nawias okrągły dwukropek. Linia 7. przejdź do kolejnej iteracji. Linia 9. wyraz podkreślnik pierwszy ← sortowanie otwórz nawias okrągły napisy otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias kwadratowy 0 zamknij nawias kwadratowy zamknij nawias okrągły. Linia 10. wyraz podkreślnik drugi ← sortowanie otwórz nawias okrągły napisy otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias kwadratowy 1 zamknij nawias kwadratowy zamknij nawias okrągły.

Jeżeli posortowane napisy są sobie równe, inkrementujemy zmienną anagramy:

Linia 1. n ← 1000 kratka liczba par napisów w pliku. Linia 2. anagramy ← 0. Linia 3. napisy otwórz nawias kwadratowy 0 kropka kropka n minus 1 zamknij nawias kwadratowy otwórz nawias kwadratowy 0 kropka kropka 1 zamknij nawias kwadratowy ← wczytaj dane z pliku cudzysłów napisy kropka txt cudzysłów. Linia 5. dla i znak równości 0 przecinek 1 przecinek kropka kropka kropka przecinek n minus 1 wykonuj dwukropek. Linia 6. jeżeli długość otwórz nawias okrągły napisy otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias kwadratowy 0 zamknij nawias kwadratowy zamknij nawias okrągły wykrzyknik znak równości długość otwórz nawias okrągły napisy otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias kwadratowy 1 zamknij nawias kwadratowy zamknij nawias okrągły dwukropek. Linia 7. przejdź do kolejnej iteracji. Linia 9. wyraz podkreślnik pierwszy ← sortowanie otwórz nawias okrągły napisy otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias kwadratowy 0 zamknij nawias kwadratowy zamknij nawias okrągły. Linia 10. wyraz podkreślnik drugi ← sortowanie otwórz nawias okrągły napisy otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias kwadratowy 1 zamknij nawias kwadratowy zamknij nawias okrągły. Linia 12. jeżeli wyraz podkreślnik pierwszy znak równości wyraz podkreślnik drugi dwukropek. Linia 13. anagramy ← anagramy plus 1.

Po zakończeniu pętli zapisujemy wartość zmiennej anagramy do pliku wynikowego i zamykamy pliki.

Linia 1. n ← 1000 kratka liczba par napisów w pliku. Linia 2. anagramy ← 0. Linia 3. napisy otwórz nawias kwadratowy 0 kropka kropka n minus 1 zamknij nawias kwadratowy otwórz nawias kwadratowy 0 kropka kropka 1 zamknij nawias kwadratowy ← wczytaj dane z pliku cudzysłów napisy kropka txt cudzysłów. Linia 5. dla i znak równości 0 przecinek 1 przecinek kropka kropka kropka przecinek n minus 1 wykonuj dwukropek. Linia 6. jeżeli długość otwórz nawias okrągły napisy otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias kwadratowy 0 zamknij nawias kwadratowy zamknij nawias okrągły wykrzyknik znak równości długość otwórz nawias okrągły napisy otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias kwadratowy 1 zamknij nawias kwadratowy zamknij nawias okrągły dwukropek. Linia 7. przejdź do kolejnej iteracji. Linia 9. wyraz podkreślnik pierwszy ← sortowanie otwórz nawias okrągły napisy otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias kwadratowy 0 zamknij nawias kwadratowy zamknij nawias okrągły. Linia 10. wyraz podkreślnik drugi ← sortowanie otwórz nawias okrągły napisy otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias kwadratowy 1 zamknij nawias kwadratowy zamknij nawias okrągły. Linia 12. jeżeli wyraz podkreślnik pierwszy znak równości wyraz podkreślnik drugi dwukropek. Linia 13. anagramy ← anagramy plus 1. Linia 15. zapisz anagramy do pliku cudzysłów anagramy kropka txt cudzysłów. Linia 16. zamknij plik cudzysłów napisy kropka txt cudzysłów. Linia 17. zamknij plik cudzysłów anagramy kropka txt cudzysłów.

Przejdźmy do implementacji algorytmu sortowania bąbelkowego. Na początek inicjujemy pętlę, odpowiedzialną za wykonywanie kolejnych cykli sortowania. W każdym cyklu sortowania jeden element zostanie ustawiony na odpowiednim miejscu w tablicy lub ciągu. Oznacza to, że pętla ta musi się wykonać n - 1 razy, gdzie n jest długością sortowanego ciągu. Gdy posortujemy n - 1 elementów, ostatni element również będzie znajdował się w odpowiednim miejscu. Definiujemy także zmienną zamiana, służącą do przechowywania informacji, czy w danej serii porównań nastąpiła zamiana. Ustawiamy jej wartość na fałsz:

Linia 1. sortowanie otwórz nawias okrągły napis zamknij nawias okrągły. Linia 2. n ← długość otwórz nawias okrągły napis zamknij nawias okrągły. Linia 3. dla i znak równości 0 przecinek 1 przecinek 2 przecinek kropka kropka kropka n minus 2 wykonuj dwukropek. Linia 4. zamiana ← fałsz.

Następnie zapisujemy drugą pętlę, w której zmienna sterującazmienna sterująca w pętli (iterator)zmienna sterująca będzie iterować po wszystkich znakach napisu oprócz pierwszego (ponieważ każdy znak będziemy porównywać z jego sąsiadem na lewo) oraz tych, które już znajdują się na właściwych pozycjach (zatem pominiemy i - końcowych pozycji). W celu ustalenia kolejności znaków w poszczególnych wierszach będziemy porównywać ich kody ASCIIASCIIASCII. W niektórych językach programowania, takich jak np. Python, Java i C++ (w wyrażeniach logicznych instrukcji warunkowych i pętli), możemy po prostu zapisać  znaki, a komputer porówna ich kody ASCII bez dodatkowych działań z naszej strony.  Inne języki programowania mogą potrzebować konwersji znaku do kodu ASCII. Dla ujednolicenia notacji w miejscach, w których używany będzie kod ASCII znaku, zastosujemy funkcję ascii(), zwracającą kod ASCII podanego jej znaku (funkcja taka jest łatwa do zaimplementowania – w większości języków wystarczy zwrócić znak przekonwertowany do typu całkowitoliczbowego). Jeżeli znak na pozycji o mniejszym indeksie ma większy kod ASCII, zamieniamy elementy i ustawiamy wartość zmiennej zamiana na: prawda.

Linia 1. sortowanie otwórz nawias okrągły napis zamknij nawias okrągły. Linia 2. n ← długość otwórz nawias okrągły napis zamknij nawias okrągły. Linia 3. dla i znak równości 0 przecinek 1 przecinek 2 przecinek kropka kropka kropka n minus 2 wykonuj dwukropek. Linia 4. zamiana ← fałsz. Linia 6. dla j znak równości 1 przecinek 2 przecinek kropka kropka kropka przecinek n minus i minus 1 wykonuj dwukropek. Linia 7. jeżeli ascii otwórz nawias okrągły napis otwórz nawias kwadratowy j minus 1 zamknij nawias kwadratowy zamknij nawias okrągły zamknij nawias ostrokątny ascii otwórz nawias okrągły napis otwórz nawias kwadratowy j zamknij nawias kwadratowy zamknij nawias okrągły dwukropek. Linia 8. zamień napis otwórz nawias kwadratowy j minus 1 zamknij nawias kwadratowy z napis otwórz nawias kwadratowy j zamknij nawias kwadratowy. Linia 9. zamiana ← prawda.

Jeżeli w serii porównań w wewnętrznej pętli nie wystąpiła zamiana (wartość zmiennej zamiana jest równa fałsz), to oznacza, że elementy są już posortowane i można przerwać działanie pętli. Po zakończeniu sortowania zwracamy uporządkowaną kopię napisu:

Linia 1. sortowanie otwórz nawias okrągły napis zamknij nawias okrągły. Linia 2. n ← długość otwórz nawias okrągły napis zamknij nawias okrągły. Linia 3. dla i znak równości 0 przecinek 1 przecinek 2 przecinek kropka kropka kropka n minus 2 wykonuj dwukropek. Linia 4. zamiana ← fałsz. Linia 6. dla j znak równości 1 przecinek 2 przecinek kropka kropka kropka przecinek n minus i minus 1 wykonuj dwukropek. Linia 7. jeżeli ascii otwórz nawias okrągły napis otwórz nawias kwadratowy j minus 1 zamknij nawias kwadratowy zamknij nawias okrągły zamknij nawias ostrokątny ascii otwórz nawias okrągły napis otwórz nawias kwadratowy j zamknij nawias kwadratowy zamknij nawias okrągły dwukropek. Linia 8. zamień napis otwórz nawias kwadratowy j minus 1 zamknij nawias kwadratowy z napis otwórz nawias kwadratowy j zamknij nawias kwadratowy. Linia 9. zamiana ← prawda. Linia 10. jeżeli zamiana znak równości fałsz dwukropek. Linia 11. przerwij pętlę. Linia 12. zwróć napis.

Odpowiedź dla danych z pliku napisy.txt

R1DGgTU8uQwkK

Przycisk do pobrania pliku TXT z wynikiem zadania.

Plik anagramy.txt.
Plik TXT o rozmiarze 2.00 B w języku polskim

Słownik

anagram
anagram

słowo powstałe w wyniku przestawienia liter innego słowa, zawierające wszystkie jego litery

ASCII
ASCII

(ang. American Standard Code for Information Interchange) pierwotnie siedmiobitowy system kodowania znaków (współcześnie rozszerzony do ośmiu bitów); w oryginalnej wersji kodom z zakresu 0–127 przyporządkowano 26 liter łacińskich, 10 cyfr (0...9) oraz dodatkowe znaki

zmienna sterująca w pętli (iterator)
zmienna sterująca w pętli (iterator)

zmienna tworzona i używana do sterowania wykonaniem instrukcji iteracyjnej; zmienna sterująca przyjmuje kolejne wartości z pewnego zdefiniowanego zakresu; w wielu językach programowania przy przejściu do kolejnej iteracji następuje automatyczne nadanie nowej wartości zmiennej sterującej; w związku z tym zmienna sterująca pętlą powinna być typu porządkowego