Matura z informatyki - przydatne funkcje - Java
Zbiór funkcji, które używałem rozwiązując zadania maturalne.
W tym poście zaprezentuję funkcje, z których korzystałem rozwiązując zadania maturalne z informatyki. Nie wiem jak w innych językach, ale w Javie jest całkiem sporo wbudowanych, które od razu robią za nas robotę. Jeśli znasz jakieś lepsze/szybsze sposoby na któreś rozwiązanie lub jeszcze inne przydatne funkcje, których nie wymieniłem, to daj znać!
Wczytanie pliku
Od tego zawsze zaczynamy. Ja korzystam z funkcji, która pakuje wszystkie dane z pliku tekstowego do tablicy o rożnych wymiarach, w zależności od zadania. Przykładowo dla tego typu danych:
wygląda tak:
Należy pamiętać o escape'owaniu ukośników (\\\\) w ścieżce do pliku.
Konwersja liczb
Jak wiadomo to podstawa. Uzyskamy to szybko dzięki dwóm metodom, które przyjmują liczbę oraz system liczbowy jako argumenty:
Zaokroglanie liczb
Równie często jest to nam potrzebne. Gdy mamy podać tylko wydrukowany wynik to jest to całkiem proste. Z pomocą przychodzi printf, np:
- %.2 - określa precyzję, czyli ilość miejsc po przecinku, w tym przypadku 2
- f - typ danych, w tym przypadku float
- %n - nowa linia
Jeśli jednak musimy operować na zaokrąglonych liczbach, potrzebne jest nam coś więcej.
Na Stack OverFlow często znajdowałem takie rozwiązanie:
gdzie zera określają dokładność “przybliżenia”. Jednak nie zawsze zwraca to prawidłową odpowiedź. Przykładowo, jeśli za “x” podstawimy 265.335, to dostaniemy 265.33, co jest oczywiście niepoprawnym wynikiem, bo powinniśmy dostać 265.34.
Ja rozwiązałem to w ten sposób:
Wykorzystuje to podobną metodę co printf, tyle że później parsujemy to na double.
Zauważ, że tutaj, jako argument podałem jeszcze Locale.ROOT. Wynika to z tego, że w różnych regionach inaczej jest formatowany tekst i tak dla Polski w metodzie printf/format separatorem liczby typu double jest ",", co całkowicie nam psuje obliczenia, bo typ double korzysta z ".". Zmiana Locale na ROOT rozwiązuje ten problem.
Max/min wartość
W zadaniach zazwyczaj proszą o maksymalną lub minimalną wartość z jakiegoś zbioru. Gdy dane przetrzymujemy w tablicy mamy do tego gotowe funkcje:
Suma wartości
Również czasem sumowanie wszystkich wartości się zdarza i tu też mamy gotowca:
Wszystko dzięki streamom, które są z nami od Java 8. Jeśli operujemy na listach, też mamy gotowe metody do wyznaczania min/max:
Chociaż do sumowania już jest nieco mniej przyjaźnie i musimy użyć streamów:
Odwracanie stringa
Często w zadaniach trzeba odwracać stringi (np. aby sprawdzić czy są tzw. “palindromami”). Można to zrobić błyskawicznie z pomocą StringBuildera.
Operowanie na literach w słowie
Tu znacznie ułatwia sprawę funkcja, która każdy znak pakuje nam do tablicy, dzięki czemu później łatwo możemy na nich operować:
Znajdowanie podciągów w stringach
Sprawdzanie czy dany ciąg znaków zawiera inny podciąg jest bajecznie proste:
Zdarzyło się też porównywać prefiksy lub sufiksy między stringami, ale również do tego mamy gotowe metody, które sprawdzają czy ciąg zaczyna się lub kończy podanym stringiem:
Czasem jednak musimy dobrać się do środka ciągów. W jednym zadaniu, z genotypu trzeba było wyciągać geny, które rozpoczynały się od “AA” a kończyły na “BB” i na nich przeprowadzać operację. Do tego typu zadań warto znać klasy Pattern i Matcher oraz umieć posługiwać się regexami. Do tego zadania użyłem metodę podobną do tej, jednak tę przerobiłem do ogólnego użytku, nie tylko pod zadanie:
W skrócie, znajduję nam wszystkie podciągi miedzy argumentami a i b, oraz pakuje je do listy, którą na koniec konwertujemy na tablicę.
Gdybyśmy mieli tylko sprawdzać czy dany ciąg pasuje do innego podciągu, moglibyśmy się posłużyć tą metodą:
Kluczowy w tych metodach jest regex: (.\*?) gdzie . oznacza dowolny znak, a \*? to "leniwy" kawntyfikator? (ang. Reluctant quantifier), który określa, że . (dowolny znak) może się wystąpić zero lub więcej razy. Jeśli, np. nie uznawalibyśmy pustych ciągów między a i b to użylibyśmy kwantyfikatora +?, który określa, że znak musi wystąpić co najmniej raz. Z kolei inny rodzaj kwantyfikatora - zachłanny (ang. greedy), w np. w postaci * pobrałby najwięcej ile się da, czyli w naszym przypadku od znalezienia pierwszego 'AA' po ostatnie 'BB'. Różnica miedzy kwantyfikatorami leniwymi a zachłannymi polega na tym, że ten pierwszy dopasuje najmniej jak się da, a drugi jak najwięcej. Po więcej info odsyłam do dokumentacji Pattern
Zaprezentuje to na przykładzie. Dajmy na to, że mamy taką o to tablicę z danymi:
i wywołując tą metodę na każdym elemencie tej tablicy, dostaniemy nową tablicę z dopasowaniami, które tu w tym przykładzie od razu drukuję:
i output dla poszczególnych kwantyfikatorów wygląda następująco:
Ilości liter - statystyka
Trafiały się też zadania gdzie trzeba było znaleźć ilości liter w słowie i wykonać na tym różne operacje (np. sprawdzanie czy słowa są anagramami). Napisałem do tego taką funkcję, która zwraca tablicę z liczbą poszczególnych liter:
Kluczowym czynnikiem jest tu operacja word.charAt(i)-'A'
, dzięki której obliczane jest miejsce w tablicy, które powinno zostać policzone w aktualnej iteracji.
Jeśli nie wiesz co tu się dzieje, to znak jest przechowywany jako liczba (np. alfabet wielkich liter przyjmuje wartości od 60 - dla A, do 90 - dla Z), a my metodą charAt wyciągamy aktualny znak, dajmy na to 'B'(61) i odejmujemy od tego 'A'(60), zatem dostajemy pozycję 1 (61-60).
Nasza tablica dla pewnego słowa po wydrukowaniu wyglądałaby tak:
Warto wiedzieć też, że można inkrementować znaki!
Przykładowo:
Mając już taką wiedzę, możemy dostarczyć pełne statystyki jakiegoś tekstu. W jednym z zadań to własnie trzeba było zrobić. Najpierw wpakowałem wszystkie słowa do tablicy i następnie stworzyłem funkcję, która na podstawie podananej tablicy ze słowami, drukuje nam statystyki danego tekstu:
A wyglądało to tak:
I do tej pory to by było na tyle. Jeśli uzbieram większy zbiór przydatnych funkcji lub algorytmów, to przeleję to na kolejny wpis.