Wyniki egzaminu

Informacje o egzaminie:
  • Zawód: Technik programista
  • Kwalifikacja: INF.04 - Projektowanie, programowanie i testowanie aplikacji
  • Data rozpoczęcia: 17 kwietnia 2026 16:18
  • Data zakończenia: 17 kwietnia 2026 16:28

Egzamin zdany!

Wynik: 27/40 punktów (67,5%)

Wymagane minimum: 20 punktów (50%)

Nowe
Analiza przebiegu egzaminu- sprawdź jak rozwiązywałeś pytania
Pochwal się swoim wynikiem!
Szczegółowe wyniki:
Pytanie 1

Po wykonaniu poniższego kodu na konsoli zostanie wyświetlona liczba:

int a = 0x73;
cout << a;
A. 115
B. 73
C. 108
D. 0
Wiele osób myli się, gdy widzi zapis 0x73, uznając, że to po prostu liczba 73 w dziesiętnym, bo tak wygląda najprościej. Jednak w rzeczywistości ten prefiks „0x” informuje kompilator, że mamy do czynienia z liczbą zapisaną w systemie szesnastkowym (heksadecymalnym), a nie dziesiętnym. To jest taki bardzo charakterystyczny zapis w językach programowania (C, C++, Java, czasem nawet Python), który pozwala programiście jasno określić, w jakim systemie podaje liczbę. Zakładając, że ktoś wybierze 108 lub 73, można podejrzewać, że ta osoba nie przeliczyła heksadecymalnej liczby na dziesiętną lub po prostu nie zwróciła uwagi na prefiks. 0x73 to w rzeczywistości (7 * 16) + 3, czyli 112 + 3, co daje 115. Niektórym może się też wydawać, że heksadecymalne 0x73 to 73 dziesiętnie, ale to typowy błąd początkujących. Wybór zera z kolei może wynikać z nieporozumienia – być może ktoś pomyślał, że a nie zostało zainicjalizowane lub kod nie wypisuje nic, ale tutaj jawnie inicjujemy a wartością heksadecymalną. Praktyka pokazuje, że podobne nieporozumienia pojawiają się na początku nauki programowania, szczególnie gdy nie ma jeszcze „wyczucia” systemów liczbowych. Tak naprawdę, jeśli chcemy być profesjonalni, trzeba od razu nauczyć się, że każda liczba z 0x na początku jest heksadecymalna, a cout zawsze wypisze jej dziesiętną reprezentację, o ile nie zmienimy flagi strumienia (std::hex itd.). To takie podstawy, które potem pozwalają pewniej obracać się w kodzie, gdzie często występują maski bitowe czy operacje na rejestrach. Moim zdaniem, wielu początkujących inżynierów właśnie przez nieuwagę na takie detale traci sporo czasu na debugowanie prostych błędów. Warto więc na przyszłość za każdym razem zatrzymać się na chwilę i zastanowić, czy na pewno dobrze rozpoznajemy system liczbowy wykorzystywany w danym fragmencie kodu.

Pytanie 2

Która z poniższych metod nie należy do cyklu życia komponentu w React.js?

A. componentWillPublish()
B. componentDidMount()
C. componentWillUnmount()
D. componentDidUpdate()
Metoda componentWillPublish() nie jest częścią cyklu życia komponentu w React.js, co czyni ją poprawną odpowiedzią na to pytanie. W React.js istnieje szereg zdefiniowanych metod cyklu życia, które umożliwiają programistom zarządzanie stanem komponentów w określonych momentach ich istnienia. Do najbardziej istotnych z nich należą: componentDidMount(), componentDidUpdate() oraz componentWillUnmount(). Metoda componentDidMount() jest wywoływana po zamontowaniu komponentu w DOM, co pozwala na inicjalizację danych, takich jak pobieranie danych z API. Z kolei componentDidUpdate() jest wywoływana, gdy komponent zostaje zaktualizowany, co jest doskonałym momentem na reagowanie na zmiany w stanie lub propach. Metoda componentWillUnmount() jest wywoływana tuż przed odmontowaniem komponentu, co jest przydatne do czyszczenia zasobów, takich jak anulowanie subskrypcji lub usuwanie nasłuchiwaczy. Zrozumienie tych metod jest kluczowe dla efektywnego zarządzania cyklem życia komponentów w aplikacjach React, co prowadzi do lepszej wydajności i utrzymania kodu.

Pytanie 3

W programie stworzonym w języku C++ trzeba zadeklarować zmienną, która będzie przechowywać wartość rzeczywistą. Jakiego typu powinna być ta zmienna?

A. number
B. numeric
C. int
D. double
Intuicyjnie można by pomyśleć, że każda zmienna liczbową da się zadeklarować przez int, bo przecież to najprostszy i najpopularniejszy typ w języku C++. Jednak int przechowuje wyłącznie liczby całkowite – nie pozwala na zapis ułamków czy wartości dziesiętnych. To bardzo częsty błąd początkujących programistów, którzy próbują przechować 7.5 w int i są zaskoczeni, że wynik zawsze jest zaokrąglany w dół. Równie problematyczne są próby użycia typów, które wyglądają na sensowne, ale w rzeczywistości nie istnieją w C++. Przykłady to number i numeric – brzmią profesjonalnie, można je spotkać w innych językach (np. number w JavaScript), ale C++ nie przewiduje takich deklaracji. Kompilator po prostu zgłosi błąd i nie skompiluje programu. Z mojego doświadczenia, wielu uczniów daje się nabrać na te angielskie słówka, bo wydają się logiczne. Tymczasem C++ ma ścisłe zasady i ogranicza się do konkretnych typów jak int, float, double czy long double. Jeśli chodzi o double, to jest to oficjalnie wspierany przez standard ISO typ do zmiennych rzeczywistych, stosowany wszędzie tam, gdzie float nie daje wystarczającej precyzji. Warto też zauważyć, że korzystanie z nieistniejących typów prowadzi do błędów kompilacji, co jest nie tylko stratą czasu, ale i może utrudnić dalszą naukę programowania, bo utrwala złe nawyki. Podsumowując, jeśli chcesz przechowywać liczby rzeczywiste w C++, musisz użyć double lub ewentualnie float, a nie int, number czy numeric – te ostatnie po prostu w tym języku nie działają.

Pytanie 4

Jakie jest fundamentalne zagadnienie w projektowaniu aplikacji w architekturze klient-serwer?

A. Brak podziału na role klienta i serwera
B. Funkcjonowanie aplikacji wyłącznie w trybie offline
C. Przeniesienie wszystkich obliczeń na stronę klienta
D. Użycie serwera jako głównego miejsca przetwarzania danych
Użycie serwera jako centralnego miejsca przetwarzania danych jest kluczowym elementem architektury klient-serwer. Serwer pełni rolę centralnego punktu, który zarządza żądaniami klientów, przechowuje dane i zapewnia odpowiedzi na zapytania. Taki model zapewnia większe bezpieczeństwo danych, ułatwia zarządzanie zasobami i umożliwia skalowanie aplikacji w miarę wzrostu liczby użytkowników. Architektura klient-serwer jest szeroko stosowana w aplikacjach webowych, systemach bankowych oraz usługach chmurowych, gdzie konieczna jest centralizacja danych i ich ochrona.

Pytanie 5

Podczas programowania kontrolki stepper przedstawionej na ilustracji w aplikacji mobilnej, należy zarządzać zmienną, która zawsze przechowuje jej bieżącą wartość. Jakie zdarzenie można wykorzystać do osiągnięcia tej funkcjonalności?

Ilustracja do pytania
A. DescendantAdded
B. ValueChanged
C. Unfocused
D. SizeChanged
Zdarzenie ValueChanged jest kluczowe w kontekście programowania kontrolek takich jak stepper w aplikacjach mobilnych. To zdarzenie jest wywoływane zawsze, gdy wartość kontrolki zostaje zmieniona przez użytkownika, co umożliwia natychmiastowe przetwarzanie tej zmiany i aktualizację interfejsu użytkownika lub innych powiązanych komponentów. W praktyce, użycie zdarzenia ValueChanged to dobry przykład reaktywnego programowania, gdzie aplikacja reaguje na akcje użytkownika w czasie rzeczywistym. Przy implementacji takiego zdarzenia należy zadbać o poprawne sprawdzanie zakresu wartości, aby uniknąć błędów logicznych. Warto również pamiętać o optymalizacji wydajności takiej obsługi, zwłaszcza w aplikacjach złożonych z wielu komponentów zależnych od wartości steppera. Praktyczne zastosowanie tego zdarzenia można znaleźć w aplikacjach e-commerce, gdzie steppery mogą być używane do wyboru ilości produktów w koszyku, a zmiana wartości natychmiast wpływa na obliczenie ceny całkowitej. Używanie zdarzeń takich jak ValueChanged jest zgodne z dobrymi praktykami projektowania interfejsów użytkownika, poprawiając ich responsywność i interaktywność.

Pytanie 6

Zamieszczony fragment kodu w Android Studio wdraża metodę nasłuchującą dla obsługi zdarzenia:

przycisk = (Button) findViewById(R.id.yes_button);
przycisk.setOnClickListener(new View.OnClickListener() { ... });
A. wybierania daty
B. zmiany stanu kontrolki Switch
C. zmiany w polu tekstowym
D. naciśnięcia przycisku
Kod wykorzystuje metodę setOnClickListener, która jest podstawowym sposobem przypisywania reakcji na kliknięcie przycisku (Button) w Androidzie. To taki klasyczny wzorzec nasłuchiwania zdarzeń, w tym przypadku – kliknięcia użytkownika. Moim zdaniem, ta konstrukcja pojawia się praktycznie w każdym większym projekcie Androidowym, bo trudno sobie wyobrazić interfejs bez przycisków, które coś faktycznie robią. Co ciekawe, korzystając z setOnClickListener, przekazujemy obiekt anonimowej klasy implementującej interfejs View.OnClickListener, a w jej metodzie onClick() umieszczamy kod, który ma się wykonać po naciśnięciu przycisku. To bardzo elastyczne rozwiązanie, bo możemy tu zarówno wyświetlić Toast, przejść do innego activity, wysłać dane do internetu czy nawet ukryć inny widok. Warto pamiętać, że praktycznie wszystkie kontrolki dziedziczące po View mogą mieć własnych listenerów, ale Button to najbardziej naturalny przypadek użycia. To taka podstawa obsługi UI w Android Studio i moim zdaniem każdy, kto chce pisać apki na Androida, powinien mieć to opanowane na pamięć. Dodatkowo, od wersji Android API 26 można używać także lambda expressions, co jeszcze bardziej skraca kod, ale sama idea zostaje ta sama – reagujemy na kliknięcie przycisku.

Pytanie 7

Która metoda cyklu życia komponentu w React.js jest wywoływana tuż po zamontowaniu komponentu w DOM?

A. componentDidMount()
B. componentWillMount()
C. componentDidUpdate()
D. componentWillUnmount()
Odpowiedź 'componentDidMount()' jest poprawna, ponieważ jest to metoda cyklu życia komponentu w React, która jest wywoływana tuż po zamontowaniu komponentu w DOM. To oznacza, że w tym momencie komponent jest już dostępny w drzewie DOM i możemy bezpiecznie wykonywać operacje, które wymagają dostępu do elementów DOM. Przykładem zastosowania tej metody może być wykonywanie zapytań do API w celu pobrania danych, które następnie będą renderowane w komponencie. Dobrą praktyką jest umieszczanie logiki inicjalizacyjnej, takiej jak ustawienie stanu komponentu na podstawie danych z API, w tej metodzie, co pozwala na odpowiednie zarządzanie cyklem życia komponentu. Dodatkowo, 'componentDidMount()' jest także idealnym miejscem do dodawania subskrypcji do zewnętrznych źródeł danych, takich jak sockety lub WebSocket, co również wymaga, aby komponent był zamontowany. Warto pamiętać, że metody cyklu życia są kluczowym elementem architektury React i mają istotny wpływ na wydajność oraz czytelność kodu.

Pytanie 8

Zapis w języku C# przedstawia definicję klasy Car, która:

public class Car: Vehicle { ... }
A. jest zaprzyjaźniona z klasą Vehicle
B. jest klasą podstawową (nie dziedziczy po innej klasie)
C. używa pól prywatnych klasy Vehicle
D. odziedzicza po Vehicle
Słusznie, zapis public class Car : Vehicle { ... } w języku C# oznacza, że klasa Car dziedziczy po klasie Vehicle. To jest tak zwane dziedziczenie, jeden z fundamentalnych mechanizmów programowania obiektowego. Dzięki temu Car odzyskuje wszystkie publiczne i chronione (protected) człony klasy Vehicle, a dodatkowo może wprowadzać własne składowe albo nadpisywać metody bazowe. Przykładowo, jeśli Vehicle ma metodę Start(), to Car również ją posiada, chyba że ją nadpisze słówkiem override. Moim zdaniem, znajomość dziedziczenia ułatwia projektowanie czytelnych oraz rozszerzalnych systemów, zwłaszcza w większych projektach. W praktyce — jeśli tworzysz aplikację zarządzającą różnymi pojazdami, to możesz mieć np. klasę Vehicle z uniwersalnymi funkcjami i kilka pochodnych (takich jak Car, Truck, Motorcycle), co pozwala trzymać wspólną logikę w jednym miejscu. Warto pamiętać, że w C# jest tylko dziedziczenie pojedyncze jeśli chodzi o klasy (w przeciwieństwie do niektórych innych języków). To też zgodne z SOLID, gdzie jedna klasa powinna mieć jasno określoną odpowiedzialność. Ja często spotykam się z tym podejściem w kodzie produkcyjnym – porządek w strukturze to podstawa, a dziedziczenie bardzo w tym pomaga.

Pytanie 9

Która technologia jest używana do tworzenia animacji na stronach internetowych?

A. CSS Animations
B. SQL Queries
C. HTTP Headers
D. XML Schema
CSS Animations to technologia, która umożliwia tworzenie zaawansowanych efektów animacyjnych na stronach internetowych, bez konieczności użycia JavaScriptu. Dzięki CSS Animations, projektanci mogą definiować kluczowe klatki (keyframes), które określają stany stylów w określonym czasie. Przykładem praktycznego zastosowania może być animacja przycisku, który zmienia kolor i rozmiar po najechaniu na niego myszką. Tego rodzaju animacje są wspierane przez wszystkie nowoczesne przeglądarki i są zgodne z W3C, co czyni je standardem w branży. Dobrze zaprojektowane animacje poprawiają doświadczenia użytkowników, ułatwiając im interakcję z elementami strony. Warto również wspomnieć, że użycie CSS do animacji jest bardziej efektywne pod względem wydajności, ponieważ procesor graficzny (GPU) może lepiej obsługiwać animacje niż tradycyjne metody, takie jak JavaScript. W kontekście projektowania responsywnego, CSS Animations pozwala na płynniejsze i bardziej estetyczne przejścia między różnymi stanami interfejsu, co jest kluczowe dla utrzymania zaangażowania użytkowników.

Pytanie 10

Który z języków programowania jest najczęściej wykorzystywany do budowania aplikacji internetowych po stronie serwera?

A. HTML
B. PHP
C. JavaScript
D. CSS
PHP to jeden z najczęściej używanych języków programowania do tworzenia aplikacji webowych po stronie serwera. Jest to język skryptowy, który umożliwia dynamiczne generowanie treści stron internetowych, zarządzanie sesjami użytkowników, obsługę formularzy oraz integrację z bazami danych. PHP napędza popularne systemy zarządzania treścią (CMS), takie jak WordPress, Joomla czy Drupal. Dzięki swojej prostocie, szerokiemu wsparciu społeczności oraz dużej liczbie gotowych bibliotek i frameworków (np. Laravel), PHP pozostaje jednym z czołowych języków backendowych. PHP pozwala również na szybkie wdrażanie aplikacji i jest kompatybilny z wieloma serwerami WWW, co czyni go uniwersalnym wyborem w budowie aplikacji webowych.

Pytanie 11

Jakie rezultaty pojawią się po uruchomieniu poniższego kodu napisanego w języku C++?

class KlasaBazowa {
    public:
        virtual void metoda() {
            cout << "Bazowa. ";
        }
};

class KlasaPochodna : public KlasaBazowa {
    public:
        void metoda() {
            cout << "Pochodna. ";
        }
};

int main() {
    KlasaBazowa *bazowa = new KlasaPochodna();
    KlasaPochodna *pochodna = new KlasaPochodna();

    bazowa->metoda();
    pochodna->metoda();
    return 0;
}
A. Pochodna. Pochodna.
B. Bazowa. Pochodna.
C. Bazowa. Bazowa.
D. Pochodna. Bazowa.
Kod wyświetla 'Pochodna. Pochodna.', co wskazuje, że metody klasy pochodnej przejęły kontrolę nad tymi z klasy bazowej. To fajny przykład polimorfizmu, jaki mamy w C++. Tutaj metoda w klasie pochodnej jest lepsza od metody w klasie bazowej. To, jakie wywołanie się wykona, zależy od konkretnego obiektu, a nie od tego, jaką metodę zdefiniowaliśmy w klasie bazowej.

Pytanie 12

Polecenia wydane w kontekście repozytorium Git, przy założeniu, że folder projektu jest aktualnie wybrany, mają na celu

git init
git add .
git commit -m 'first commit'
A. rozpoczęcie sesji z już istniejącym repozytorium oraz pobranie kodu projektu do lokalnego folderu
B. rozpoczęcie pracy z nowym repozytorium, dodanie oraz zatwierdzenie kodu projektu jako first commit
C. zamknięcie projektu, co spowoduje zarchiwizowanie wszystkich rewizji do lokalnego archiwum pod nazwą first commit
D. utworzenie kopii istniejącego repozytorium z jedynie tą rewizją, która zostanie zapisana pod nazwą first commit
Polecenia git init git add . oraz git commit -m 'first commit' są podstawowymi komendami do rozpoczęcia pracy z nowym repozytorium Gita. git init inicjalizuje puste repozytorium w aktualnym katalogu co tworzy podkatalog .git zawierający wszystkie metadane i historię w wersjonowania. Następnie git add . dodaje wszystkie nowe i zmodyfikowane pliki w bieżącym katalogu do indeksu co oznacza że są one gotowe do zatwierdzenia w repozytorium. Kolejne polecenie git commit -m 'first commit' tworzy pierwszy snapshot aktualnego stanu projektu z przypisaną wiadomością 'first commit' co jest dobrą praktyką sygnalizującą początek nowej historii projektu. Taki proces inicjacji jest standardem w zarządzaniu wersjami w branży IT umożliwiając śledzenie zmian w kodzie ułatwiając współpracę zespołową oraz zapewniając kontrolę nad rozwojem oprogramowania. Ważne jest by w pierwszym commicie umieścić podstawowe działające elementy projektu co stanowi solidną bazę do dalszego rozwoju.

Pytanie 13

Który z wymienionych poniżej typów danych stanowi przykład typu stałoprzecinkowego?

A. float
B. double
C. decimal
D. int
Typ 'float' przechowuje liczby zmiennoprzecinkowe, co oznacza, że może reprezentować wartości z częściami dziesiętnymi, ale nie jest to typ stałoprzecinkowy. Typ 'double' to również typ zmiennoprzecinkowy, charakteryzujący się większą precyzją niż 'float'. Typ 'decimal' służy do przechowywania liczb zmiennoprzecinkowych z dużą dokładnością, głównie w aplikacjach finansowych, gdzie precyzja jest kluczowa, ale nie zalicza się do typów stałoprzecinkowych.

Pytanie 14

Programista pragnie wybrać algorytm, który najszybciej przetwarza dane w jego aplikacji. Na podstawie złożoności obliczeniowej przedstawionej w tabeli, należy wskazać algorytm numer

Algorytm 1O(n²)
Algorytm 2O(n!)
Algorytm 3O(n³)
Algorytm 4O(n)
Algorytm 5O(n²)
A. 2 lub 3
B. 1 lub 5
C. 4
D. 3
Wybierając algorytm o najniższej złożoności obliczeniowej, zawsze warto patrzeć na oznaczenia w notacji dużego O. O(n) oznacza, że czas wykonywania algorytmu rośnie liniowo wraz z rozmiarem danych wejściowych. To zdecydowanie najlepszy wynik z dostępnych, szczególnie jeśli porównać do O(n²), O(n³) albo już totalnie niepraktycznego przy większych n: O(n!). Dlatego Algorytm 4, który ma złożoność O(n), to najrozsądniejszy wybór, jeśli zależy nam na szybkości działania programu. Z mojego doświadczenia, właśnie takie algorytmy są wykorzystywane np. do przetwarzania dużych zbiorów danych w aplikacjach webowych albo w sytuacjach, gdzie liczy się czas odpowiedzi dla użytkownika końcowego. W branży IT, jeśli tylko można zejść poniżej złożoności kwadratowej – raczej zawsze warto to zrobić. Oczywiście, sama złożoność to nie wszystko – czasem prostszy, liniowy algorytm może mieć duże stałe ukryte w implementacji, ale w praktyce O(n) to standard optymalny. Warto też pamiętać, że w rekrutacjach często padają pytania o takie porównania złożoności, bo to podstawowa wiedza każdego programisty. Takie podejście pozwala budować skalowalne systemy, które nie „duszą się” przy większej ilości danych. Moim zdaniem, to jedna z tych rzeczy, które naprawdę się przydają w codziennej pracy.

Pytanie 15

Wskaż język programowania, który pozwala na stworzenie aplikacji mobilnej w środowisku Android Studio?

A. Swift
B. Objective-C
C. C++
D. Java
Java to jeden z podstawowych języków programowania używanych do tworzenia aplikacji mobilnych na platformę Android. Jest to język, który został stworzony przez firmę Sun Microsystems, a jego pierwsza wersja została wydana w 1995 roku. Java charakteryzuje się silnym typowaniem, obiektowością oraz wsparciem dla programowania wielowątkowego, co czyni go idealnym do tworzenia wydajnych aplikacji mobilnych. Android Studio, oficjalne zintegrowane środowisko programistyczne (IDE) dla Androida, oferuje pełne wsparcie dla Javy, w tym możliwość korzystania z bibliotek Android SDK. Dzięki temu programiści mogą łatwo tworzyć interfejsy użytkownika, zarządzać zasobami oraz implementować logikę aplikacji. Przykładowo, pisząc aplikację do zarządzania zadaniami, programista może użyć Javy do stworzenia klas modelujących zadania oraz do obsługi interfejsu graficznego z wykorzystaniem XML i Java. Ponadto, Java jest zgodna z zasadami programowania obiektowego, co pozwala na łatwe zarządzanie kodem i jego ponowne wykorzystanie. Warto również zaznaczyć, że Java jest wspierana przez dużą społeczność, co zapewnia bogaty ekosystem bibliotek oraz narzędzi, ułatwiających rozwój aplikacji na Androida.

Pytanie 16

Jaki będzie wynik działania poniższego kodu JavaScript?

let x = 5;
let y = '10';
console.log(x + y);
A. undefined
B. 510
C. 15
D. error
Wynik działania podanego kodu to 510, co może być zaskakujące dla osób nieznających typów danych w JavaScript. W tym przypadku zmienna x jest liczbą całkowitą (5), a zmienna y jest łańcuchem tekstowym ('10'). Kiedy używamy operatora + w JavaScript, następuje tzw. "przesunięcie typów". Gdy jeden z operandów jest łańcuchem, to JavaScript konwertuje pozostałe typy na łańcuch, a następnie wykonuje konkatenację. W efekcie 5 konwertowane jest na '5', a wynik końcowy to '5' + '10', co daje '510'. To zachowanie jest zgodne z regułami języka JavaScript i jego dynamicznym typowaniem. Warto zwrócić uwagę, że taka konwersja może prowadzić do niezamierzonych wyników, dlatego ważne jest, aby zrozumieć, kiedy i jak działają operatory w JavaScript. Dla większej jasności, w sytuacjach, gdy chcemy dodać dwie liczby, lepiej jest upewnić się, że obie zmienne mają ten sam typ danych, np. przez użycie funkcji parseInt() lub parseFloat().

Pytanie 17

Jakie z wymienionych czynności można zrealizować przy pomocy składnika statycznego danej klasy?

A. Wywołanie destruktora klasy bez jej usuwania
B. Umożliwienie dzielenia pól klasy pomiędzy zaprzyjaźnione klasy
C. Zachowanie wartości wspólnych dla wszystkich instancji klasy
D. Tworzenie prywatnych kopii pól dla każdej instancji
Tworzenie prywatnych kopii pól dla każdego obiektu to cecha pól niestatycznych – każda instancja klasy ma swoją własną kopię takich pól. Dzielenie pól klasy pomiędzy zaprzyjaźnione klasy nie odnosi się do mechanizmu statycznego – przyjaźń między klasami pozwala na dostęp do prywatnych składowych, ale nie oznacza współdzielenia pól między instancjami. Destruktory nie mogą być wywoływane w sposób statyczny – są one automatycznie uruchamiane w momencie usunięcia obiektu, a nie przez klasę jako całość.

Pytanie 18

Który z wymienionych poniżej przykładów ilustruje prawidłowy szkielet zarządzania wyjątkami w języku C++?

A. try { kod } catch { obsługa }
B. try { kod } finally { obsługa }
C. try { kod } handle { obsługa }
D. try { kod } except { obsługa }
Jak to wygląda w C++? Kluczowym elementem jest szkielet z blokami 'try' i 'catch'. W bloku 'try' piszesz kod, który może spowodować błąd, a 'catch' zajmuje się sytuacjami, kiedy coś pójdzie nie tak. Dzięki temu nie musisz się martwić, że program nagle przestanie działać, bo masz kontrolę nad tym, jak reagować w trudnych momentach. Obsługa wyjątków to naprawdę ważna sprawa w programowaniu, bo pomaga wyłapać różne problemy, czy to z danymi, z pamięcią, czy z plikami. Z mojego doświadczenia, to po prostu sprawia, że aplikacje są bardziej stabilne i działa to na korzyść zarówno programisty, jak i użytkownika.

Pytanie 19

W którym przypadku algorytm sortowania bąbelkowego działa z optymalną wydajnością?

A. Dla tablicy losowej
B. Dla tablicy z dużą liczbą powtórzeń
C. Dla tablicy uporządkowanej malejąco
D. Dla tablicy uporządkowanej rosnąco
Algorytm sortowania bąbelkowego działa z optymalną wydajnością w przypadku, gdy tablica jest już posortowana rosnąco. W takiej sytuacji algorytm wykona jedynie jedno przejście przez tablicę, bez konieczności dokonywania zamian, co sprawia, że jego złożoność wynosi O(n). To znacząco zwiększa jego efektywność w przypadku niemal posortowanych danych, choć nadal pozostaje mniej wydajny niż algorytmy takie jak QuickSort czy MergeSort dla dużych zbiorów. Sortowanie bąbelkowe jest jednak łatwe do zrozumienia i implementacji, co czyni je popularnym narzędziem edukacyjnym.

Pytanie 20

Technika konstruowania algorytmu polegająca na rozbiciu na dwa lub więcej mniejszych podproblemów, aż do momentu, gdy ich części będą wystarczająco proste do bezpośredniego rozwiązania, nosi nazwę:

A. komiwojażera
B. dziel i zwyciężaj
C. heurystycznej
D. najkrótszej trasy
W pytaniu pojawiły się odpowiedzi, które dość często mylą się osobom zaczynającym z algorytmiką, ale każda z nich odnosi się do innych pojęć niż te związane z rozbijaniem problemów na mniejsze podzadania. Najkrótsza trasa to raczej rodzaj konkretnego problemu optymalizacyjnego, a nie technika konstruowania algorytmu – tutaj przykładem jest choćby problem znajdowania najkrótszej ścieżki w grafie, który można rozwiązywać różnymi sposobami, nie tylko „dziel i zwyciężaj”, i zdecydowanie nie jest to samodzielna metoda konstruowania algorytmu. Odpowiedź heurystyczna sugeruje podejście oparte bardziej na przybliżeniach niż na systematycznym rozkładaniu na podproblemy – w praktyce heurystyki stosuje się tam, gdzie nie da się lub nie opłaca znaleźć idealnego rozwiązania, a nie do klasycznego podziału problemu na prostsze części. Komiwojażer z kolei to nazwa jednego, bardzo znanego problemu NP-trudnego (problem komiwojażera, TSP – travelling salesman problem), który można próbować rozwiązywać na rozmaite sposoby, m.in. heurystykami, metodami przybliżonymi, czasem nawet „dziel i zwyciężaj”, ale sama nazwa nie opisuje techniki konstrukcji algorytmów, tylko konkretne zadanie. Moim zdaniem często spotykanym błędem jest utożsamianie nazw znanych algorytmów czy problemów z metodami rozwiązywania – to dwie różne sprawy. Warto pamiętać, że w praktyce, kiedy wybieramy technikę algorytmiczną, najpierw określamy rodzaj problemu i wtedy dobieramy właściwe narzędzie, a nie na odwrót. Dobrą branżową praktyką jest rozpoznanie, czy problem nadaje się do rozbicia na mniejsze części i wtedy właśnie wybiera się „dziel i zwyciężaj” – pozostałe odpowiedzi tego nie zapewniają.

Pytanie 21

Mobilna aplikacja przedstawia listę, w której każdy element można dotknąć palcem, aby zobaczyć jego detale. Zdarzenie, które odpowiada tej czynności, to

A. toggled.
B. button clicked.
C. tapped.
D. value changed.
Zdarzenie 'toggled' mówi o przełącznikach, czyli o tych małych suwakach, co zmieniają stan. 'Value changed' to w sumie zmiana wartości w różnych kontrolkach, takich jak suwaki czy pola tekstowe. A 'Button clicked' dotyczy przycisków, a nie elementów z listy. Każde z tych zdarzeń ma swój cel w interfejsie, więc warto o tym pamiętać.

Pytanie 22

Jakie jest najważniejsze właściwość algorytmów szyfrowania symetrycznego?

A. Zastosowanie odmiennych kluczy do szyfrowania i deszyfrowania
B. Funkcjonowanie bez użycia klucza
C. Szyfrowanie wyłącznie tekstowych plików
D. Zastosowanie identycznego klucza do szyfrowania oraz deszyfrowania
Algorytmy szyfrowania symetrycznego to takie, które używają tego samego klucza do szyfrowania i deszyfrowania danych. To jedna z najstarszych metod i, co ważne, bardzo często stosowanych, bo działa dość szybko i nie wymaga wielkich zasobów. Przykłady, które na pewno słyszałeś, to AES i DES. Symetryki są super w komunikacji sieciowej, przy przechowywaniu danych, a także w różnych protokołach bezpieczeństwa. Fajnie, że są szybkie, ale z drugiej strony trzeba pamiętać o tym, żeby klucz był bezpiecznie przechowywany, bo to może stanowić nie lada problem.

Pytanie 23

Czym jest 'refaktoryzacja' w kontekście inżynierii oprogramowania?

A. Optymalizacja wydajności poprzez zmianę algorytmów
B. Proces modyfikowania kodu w celu poprawy jego struktury bez zmiany funkcjonalności
C. Usuwanie niepotrzebnych funkcji z kodu
D. Dodawanie nowych funkcji do istniejącego kodu
Refaktoryzacja to kluczowy proces w inżynierii oprogramowania pozwalający na modyfikację istniejącego kodu, aby poprawić jego strukturę bez zmieniania zewnętrznego zachowania programu. To podejście jest niezwykle istotne, ponieważ kod, podobnie jak każdy inny twór ludzki, z czasem może stać się trudny do zrozumienia i utrzymania. Refaktoryzacja pomaga utrzymać kod w czystości i zrozumiałości, co jest kluczowe dla długoterminowego rozwoju projektu. Praktyczne przykłady refaktoryzacji obejmują takie działania jak eliminacja powtórzeń w kodzie, zmiana nazw zmiennych na bardziej opisowe, czy też rozdzielanie dużych funkcji na mniejsze, bardziej zrozumiałe fragmenty. Ten proces jest zgodny z zasadami KISS (Keep It Simple, Stupid) i DRY (Don't Repeat Yourself), które są fundamentami dobrych praktyk programistycznych. Moim zdaniem, regularna refaktoryzacja jest jak sprzątanie biurka - początkowo może wydawać się niepotrzebna, ale w dłuższej perspektywie znacznie ułatwia pracę. Warto dodać, że narzędzia takie jak IntelliJ IDEA czy Visual Studio oferują wsparcie dla automatycznej refaktoryzacji, co czyni ten proces bardziej efektywnym.

Pytanie 24

Co zostanie wypisane w konsoli po wykonaniu poniższego kodu?

let i = 0;
while (i < 5) {
  i++;
  if (i === 3) continue;
  console.log(i);
}
A. 1, 2, 4, 5
B. 0, 1, 2, 4, 5
C. 0, 1, 2, 3, 4
D. 1, 2, 3, 4, 5
W przedstawionym kodzie mamy do czynienia z pętlą while, która działa, dopóki zmienna i jest mniejsza od 5. Na początku i jest równe 0, a w każdej iteracji pętli i jest zwiększane o 1. Wewnątrz pętli mamy warunek, który sprawdza, czy i jest równe 3. Jeżeli tak, to używamy instrukcji continue, co oznacza, że pomijamy resztę kodu w tej iteracji i wracamy do początku pętli. Przeanalizujmy, co się stanie w kolejnych iteracjach: w pierwszej iteracji i jest 1, więc wypisujemy 1, w drugiej iteracji i jest 2, więc wypisujemy 2. Gdy i osiąga 3, warunek if jest spełniony i przechodzimy do następnej iteracji, nie wypisując nic. Następnie i staje się 4 i 5, które również są wypisywane. W efekcie na konsoli zostanie wypisane 1, 2, 4, 5. Takie podejście pokazuje, jak ważne jest zrozumienie działania pętli i instrukcji sterujących w JavaScript, co jest kluczowe w programowaniu i pozwala na efektywne zarządzanie przepływem kodu.

Pytanie 25

Który element HTML5 służy do osadzania wideo na stronie?

A. &lt;player&gt;
B. &lt;video&gt;
C. &lt;movie&gt;
D. &lt;media&gt;
Zastosowanie elementów takich jak &lt;media&gt;, &lt;movie&gt; czy &lt;player&gt; do osadzania wideo wskazuje na pewne nieporozumienie dotyczące struktury HTML5 i jego standardów. Element &lt;media&gt; nie istnieje w specyfikacji HTML5; nie jest to poprawny tag, co może prowadzić do problemów z interpretacją treści przez przeglądarki. Z kolei &lt;movie&gt; również nie jest uznawanym elementem w HTML5. Użytkownicy mogą mylić go z terminologią używaną w programowaniu lub w kontekście multimediów, co może wskazywać na niewłaściwe zrozumienie tematu. Natomiast &lt;player&gt; jest ogólną nazwą, która nie odnosi się do konkretnego elementu HTML, lecz raczej do pojęcia odtwarzacza multimedialnego, który może być zrealizowany w różnorodny sposób, często przy pomocy JavaScript lub zewnętrznych bibliotek. Tworząc strony internetowe, ważne jest stosowanie odpowiednich tagów HTML5, aby zapewnić kompatybilność z różnymi przeglądarkami i urządzeniami. Stosowanie nieistniejących tagów lub nienależycie zdefiniowanych elementów prowadzi do błędów w ładowaniu treści i negatywnie wpływa na doświadczenie użytkownika. Warto dobrze zrozumieć i stosować zalecane praktyki oraz standardy, aby uniknąć nieporozumień i problemów technicznych, które mogą wynikać z użycia niewłaściwych elementów.

Pytanie 26

Jaką instrukcję należy wykorzystać do poprawnej deklaracji zmiennej typu string w C++?

A. string name = "Jan"
B. float name = "Jan"
C. bool name = "Jan"
D. int name = "Jan"
Ta deklaracja 'string name = "Jan"' to naprawdę dobry sposób na zdefiniowanie zmiennej łańcuchowej w C++. Wiesz, 'string' to typ danych, 'name' to nazwa tej zmiennej, a 'Jan' to wartość, która jest jej przypisana. Typ 'string' jest częścią biblioteki <string> i daje nam wiele możliwości, gdy pracujemy z tekstem. Możemy łączyć, porównywać i modyfikować różne łańcuchy znaków bez większego problemu. To jest mega ważne w aplikacjach, które mają do czynienia z danymi tekstowymi, interfejsami użytkownika czy analizą danych, które wprowadzamy.

Pytanie 27

Który z poniższych opisów najlepiej definiuje kompilator?

A. Program łączący dynamiczne biblioteki z kodem źródłowym
B. Narzędzie przekształcające kod źródłowy na plik wykonywalny
C. Narzędzie do analizy kodu w czasie rzeczywistym
D. System monitorujący zmiany w kodzie źródłowym
Kompilator to narzędzie, które przekształca kod źródłowy napisany w języku programowania na plik wykonywalny (binarny), który może być uruchomiony bez potrzeby ponownej kompilacji. Proces ten obejmuje kilka etapów, takich jak analiza leksykalna, analiza składniowa, optymalizacja kodu oraz generowanie kodu maszynowego. Kompilator jest nieodzownym elementem w językach takich jak C, C++ czy Java. Generowany plik wykonywalny może działać szybciej niż kod interpretowany, ponieważ nie wymaga tłumaczenia w czasie rzeczywistym.

Pytanie 28

Która z poniższych technik NIE jest związana z optymalizacją wydajności strony internetowej?

A. Deep linking
B. Lazy loading
C. Użycie CDN
D. Minifikacja kodu
Minifikacja kodu, lazy loading i użycie CDN to techniki ściśle związane z optymalizacją wydajności stron internetowych. Minifikacja kodu polega na usuwaniu zbędnych znaków, takich jak spacje, komentarze czy nowe linie, co skutkuje zmniejszeniem rozmiaru plików CSS i JavaScript. Dzięki temu przeglądarki mogą szybciej pobierać i interpretować skrypty, co bezpośrednio wpływa na czas ładowania strony. Z kolei lazy loading to technika, która polega na opóźnionym ładowaniu obrazów i innych zasobów, co pozwala na szybsze przekazywanie pierwszej wersji strony użytkownikowi. Tylko zasoby, które są aktualnie widoczne w oknie przeglądarki, są ładowane na początku, co zmniejsza obciążenie serwera oraz przyspiesza renderowanie strony. Użycie CDN (Content Delivery Network) z kolei polega na rozproszeniu treści na serwerach rozmieszczonych geograficznie, co umożliwia użytkownikom dostęp do zasobów z najbliższej lokalizacji, co także przyspiesza ładowanie strony. Zrozumienie tych technik jest kluczowe, ponieważ ich wdrażanie może znacząco poprawić wskaźniki wydajności, a tym samym satysfakcję użytkowników. Ignorowanie tych metod optymalizacji może prowadzić do długich czasów ładowania i niezadowolenia użytkowników, co w dłuższym okresie może wpływać na konwersje i ogólną reputację strony.

Pytanie 29

Która metoda w obrębie klasy jest uruchamiana automatycznie podczas tworzenia kopii obiektu?

A. Destruktor
B. Metoda statyczna
C. Konstruktor kopiujący
D. Metoda zaprzyjaźniona
Metoda statyczna jest związana z klasą, a nie z jej obiektami, więc nie wywołuje się automatycznie, gdy kopiujemy obiekt. Destruktor to kolejna metoda, która odpowiada za usuwanie obiektu i zwalnianie zasobów, ale jego rola pojawia się dopiero na końcu życia obiektu, a nie podczas samego kopiowania. Co do metody zaprzyjaźnionej, to ona ma dostęp do prywatnych i chronionych elementów klasy, ale też nie jest wywoływana automatycznie w procesie kopiowania. Tylko konstruktor kopiujący robi to właściwie, tworząc kopie obiektów.

Pytanie 30

Wskaż fragment kodu, który wykreuje przedstawioną kontrolkę?

Ilustracja do pytania
A. Kod1
B. Kod2
C. Kod4
D. Kod3
Odpowiednim kodem do wygenerowania przedstawionej kontrolki jest Kod3 który korzysta z klasy RatingBar w Androidzie. RatingBar to bardzo przydatny element interfejsu użytkownika pozwalający użytkownikom na ocenę w skali gwiazdek. W tym przypadku RatingBar posiada atrybut android:rating ustawiony na 2.5 co oznacza że kontrolka wyświetli dwie pełne gwiazdki i jedną połowę co odpowiada przedstawionej grafice. Dodatkowo atrybut android:progressTint ustawiony na #4682B4 zmienia kolor gwiazdek na niebieski. Użycie RatingBar jest standardową praktyką w aplikacjach mobilnych dla zbierania opinii użytkowników. Ważne jest aby pamiętać że RatingBar może być konfigurowany do obsługi różnych wartości minimalnych i maksymalnych oraz do dostosowywania wyglądu za pomocą stylów i tematów. Dobrym zwyczajem jest dbanie o czytelność i intuicyjność interfejsu co osiąga się m.in. przez odpowiednie oznaczanie i rozmieszczanie kontrolek takich jak RatingBar.

Pytanie 31

Jakie określenie w programowaniu obiektowym odnosi się do "zmiennej klasy"?

A. Obiekt
B. Konstruktor
C. Pole
D. Metoda
Obiekt to instancja klasy, która posiada swoje pola i metody, ale sam w sobie nie jest zmienną klasy – jest to jednostka przechowująca dane i wykonująca operacje. Metoda to funkcja należąca do klasy, która definiuje zachowanie obiektu, ale różni się od pola, które przechowuje dane. Konstruktor to specjalna metoda klasy, która jest wywoływana podczas tworzenia obiektu i służy do inicjalizacji jego pól, ale sam w sobie nie jest zmienną klasy – raczej definiuje, jak te zmienne są ustawiane podczas tworzenia obiektu.

Pytanie 32

Jakie znaczenie ma określenie "klasa zaprzyjaźniona" w kontekście programowania obiektowego?

A. Klasa, która nie ma możliwości zawierania metod statycznych
B. Klasa, która może być dziedziczona przez inne klasy
C. Klasa, w której wszystkie komponenty są publiczne
D. Klasa, która ma dostęp do prywatnych i chronionych elementów innej klasy
Klasa zaprzyjaźniona (ang. 'friend class') to klasa, która ma dostęp do prywatnych i chronionych składowych innej klasy, dzięki specjalnej deklaracji 'friend' wewnątrz tej klasy. Jest to kluczowe narzędzie w programowaniu obiektowym, które umożliwia ściślejszą współpracę między klasami, jednocześnie zapewniając hermetyzację kodu w miejscach, gdzie jest to wymagane. Używanie klas zaprzyjaźnionych umożliwia bardziej efektywne zarządzanie zależnościami między klasami, co jest istotne w dużych projektach programistycznych. Klasy zaprzyjaźnione są często stosowane w bibliotekach standardowych i frameworkach, pozwalając na eleganckie rozwiązania problemów związanych z ukrywaniem implementacji i udostępnianiem tylko niezbędnych fragmentów kodu innym komponentom systemu.

Pytanie 33

Jaki z wymienionych komponentów jest kluczowy do inicjalizacji pola klasy podczas tworzenia instancji obiektu?

A. Instrukcja warunkowa
B. Funkcja zaprzyjaźniona
C. Konstruktor
D. Metoda statyczna
Metoda statyczna działa na poziomie klasy, a nie obiektu, i nie jest używana do inicjalizacji pól instancji. Funkcja zaprzyjaźniona może mieć dostęp do prywatnych pól klasy, ale jej głównym celem nie jest inicjalizacja obiektu – służy do wykonywania operacji na istniejących obiektach. Instrukcja warunkowa kontroluje przepływ programu, ale nie jest odpowiedzialna za inicjalizację pól klasy – jest to zadanie konstruktora, który działa automatycznie przy tworzeniu obiektu.

Pytanie 34

Co to jest destructuring assignment w JavaScript?

A. Proces konwersji typów danych w JavaScript
B. Technika optymalizacji kodu przez kompilator
C. Składnia pozwalająca na rozpakowanie wartości z tablic lub obiektów do oddzielnych zmiennych
D. Metoda usuwania nieużywanych zmiennych z kodu
Odpowiedzi, które wybierasz, mogą prowadzić do mylnych interpretacji dotyczących możliwości i funkcji JavaScript. Na przykład, sugestia, że destructuring assignment to metoda usuwania nieużywanych zmiennych, jest nieprawdziwa. Technika destructuring nie zajmuje się usuwaniem zmiennych, lecz ich rozpakowywaniem. Usuwanie zmiennych, które nie są używane, jest związane z zarządzaniem pamięcią i optymalizacją kodu, co jest zupełnie inną koncepcją. Ponadto, konwersja typów danych w JavaScript to proces, który dotyczy zmiany jednego typu danych na inny, a nie ma bezpośredniego związku z destrukturyzacją. Zrozumienie różnic pomiędzy tymi pojęciami jest kluczowe, aby nie wprowadzać w błąd podczas nauki JavaScript. Destructuring assignment jest także odzwierciedleniem nowoczesnych praktyk programowania, które skupiają się na zwięzłości i czytelności kodu. Uznawanie go za technikę optymalizacji kodu przez kompilator również jest mylne, ponieważ optymalizacja kodu to proces, który nie ma bezpośredniego związku z destrukturyzacją. Takie nieprecyzyjne zrozumienie może prowadzić do późniejszych problemów z implementacją kodu oraz jego utrzymywaniem.

Pytanie 35

Które z wymienionych poniżej błędów podczas wykonywania programu można obsłużyć poprzez zastosowanie wyjątków?

A. Błąd w składni
B. Niekompatybilność typów danych w kodzie
C. Błąd kompilacyjny
D. Błąd dzielenia przez zero
Błędy składniowe są wykrywane na etapie kompilacji i nie mogą być obsługiwane za pomocą wyjątków – kompilator generuje komunikat o błędzie, zanim program zostanie uruchomiony. Błędy kompilacji, takie jak niezgodność typów danych, również są wychwytywane na etapie kompilacji i wymagają poprawienia kodu źródłowego. Wyjątki są przeznaczone do obsługi błędów, które występują w czasie wykonywania programu, a nie błędów wykrywanych przez kompilator. Dlatego obsługa błędów składniowych i kompilacyjnych wymaga innego podejścia niż mechanizm wyjątków.

Pytanie 36

W przedstawionym filmie ukazano kreator interfejsu użytkownika, dla którego automatycznie powstaje

A. kod XML
B. kod Java
C. obsługa przycisku ekranu dotykowego
D. obsługa wciśniętego przycisku
Kod XML jest obecnie najczęściej stosowanym formatem do definiowania wyglądu interfejsów użytkownika w takich narzędziach jak Android Studio czy różnego rodzaju designery graficzne. Kiedy projektujesz layout aplikacji mobilnej albo desktopowej, duża część nowoczesnych narzędzi tworzy właśnie pliki XML, które następnie są interpretowane przez system w czasie uruchamiania aplikacji. Ułatwia to rozdzielenie logiki aplikacji od jej prezentacji, co wydaje się fundamentalne przy większych projektach. Moim zdaniem takie podejście daje ogromne korzyści – można łatwo modyfikować wygląd bez dotykania kodu źródłowego. W praktyce, jeśli używasz np. Android Studio, zbudujesz interfejs przeciągając przyciski czy pola tekstowe, a pod spodem dostaniesz czytelny plik XML. To przyspiesza pracę, zwiększa czytelność projektu i pozwala na późniejsze automatyczne generowanie dokumentacji albo testów interfejsu. Takie standardy są rekomendowane nie tylko przez Google, ale też szeroko stosowane w innych środowiskach, jak chociażby XAML w Microsoft czy FXML w JavaFX. Przezroczystość działania tych narzędzi sprawia, że łatwiej jest pracować zespołowo, bo każdy może szybko zorientować się w strukturze UI patrząc na XML-a. Samo generowanie kodu XML przez narzędzia graficzne to duży krok w kierunku lepszej organizacji pracy i zgodności ze współczesnymi praktykami branżowymi.

Pytanie 37

Przeprowadzając analizę kodu interfejsu graficznego napisanego w języku XAML, można zauważyć, że:

<StackLayout Orientation="Vertical">
  <Label Text="Fotograf" />
  <Image Source="obraz.jpg" Aspect="AspectFill" />
  <StackLayout Orientation="Horizontal">
    <Button Text="Like" />
    <Button Text="Share" />
  </StackLayout>
  <Label Text="Fotka z moich wakacji" />
</StackLayout>
A. obraz znajduje się po lewej stronie, a pozostałe elementy po prawej
B. tekst "Fotograf" znajduje się po prawej stronie obrazu
C. przyciski są ustawione poziomo obok siebie
D. elementy: tekst, obraz, przycisk Like, przycisk Share, tekst są ułożone jeden pod drugim
W analizowanym kodzie XAML widzimy, że element <StackLayout> z atrybutem Orientation="Horizontal" zawiera przyciski <Button> z tekstami "Like" i "Share". W XAML, stosując stack layout z orientacją poziomą, elementy w nim zawarte są umieszczane obok siebie w rzędzie. To sprawia, że przyciski "Like" i "Share" są widoczne na interfejsie użytkownika ułożone poziomo, zgodnie z tym, co jest opisane w poprawnej odpowiedzi. Użycie StackLayout z orientacją poziomą to często spotykana praktyka w projektowaniu interfejsów, gdy chcemy zorganizować elementy w rzędzie, na przykład przyciski na pasku narzędzi. Zrozumienie tego mechanizmu jest istotne, ponieważ pozwala na efektywne zarządzanie przestrzenią w aplikacjach mobilnych i webowych, gdzie dostępne miejsce może być ograniczone. Praktyczne zastosowanie takiego układu można zobaczyć na przykład w projektowaniu formularzy, gdzie grupujemy elementy w logiczny sposób, ułatwiając użytkownikowi interakcję z aplikacją. Dobre praktyki w projektowaniu interfejsów użytkownika zalecają, aby układ elementów był intuicyjny i zgodny z oczekiwaniami użytkowników, co StackLayout z orientacją poziomą doskonale realizuje w wielu przypadkach.

Pytanie 38

Co będzie wynikiem działania poniższego kodu SQL?

SELECT COUNT(*)
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
A. Liczba pracowników z pensją powyżej średniej
B. Średnia pensja wszystkich pracowników
C. Liczba pracowników z najwyższą pensją
D. Błąd składni SQL
Odpowiedź, że wynik działania zapytania SQL to liczba pracowników z pensją powyżej średniej, jest całkowicie poprawna. Zapytanie to korzysta z funkcji agregującej COUNT(*), która zlicza liczbę rekordów spełniających określony warunek. W tym przypadku warunkiem jest, że pensja pracownika jest większa od średniej pensji wszystkich pracowników, którą obliczamy za pomocą wewnętrznego zapytania (subquery). Tego rodzaju operacje są powszechnie stosowane w analizie danych w bazach danych, gdzie często musimy wykonać porównania względem wartości agregatów, takich jak średnia, mediana czy suma. Przykładowo, w analizie wynagrodzeń w danej firmie, można użyć podobnych zapytań do oceny, jaki odsetek pracowników jest wynagradzanych powyżej średniej, co może być istotne z punktu widzenia polityki płacowej oraz budżetowania. Pamiętaj, że dobre praktyki w pracy z bazami danych obejmują optymalizację zapytań oraz unikanie niepotrzebnych obliczeń, co może wpłynąć na wydajność systemu.

Pytanie 39

Które z wymienionych oznaczeń wskazuje na liniową złożoność algorytmu?

A. O(n)
B. O(log n)
C. O(1)
D. O(n²)
Złożoność O(n) oznacza liniową zależność czasu wykonania algorytmu od rozmiaru danych wejściowych. Oznacza to, że dla każdego dodatkowego elementu algorytm wykonuje jedną dodatkową operację. Algorytmy liniowe są jednymi z najczęściej stosowanych w praktyce, ponieważ oferują dobrą równowagę między szybkością a złożonością implementacji. Przykłady algorytmów o złożoności O(n) to przeszukiwanie liniowe (Linear Search), sumowanie elementów tablicy oraz niektóre algorytmy sortowania, takie jak Counting Sort dla określonych warunków. Liniowa złożoność czyni te algorytmy bardzo efektywnymi przy przetwarzaniu dużych zbiorów danych.

Pytanie 40

Dokumentacja, która została przedstawiona, dotyczy algorytmu sortowania

To prosta metoda sortowania opierająca się na cyklicznym porównywaniu par sąsiadujących ze sobą elementów i zamianie ich miejscami w przypadku, kiedy kryterium porządkowe zbioru nie zostanie spełnione. Operacje te wykonywane są dopóki występują zmiany, czyli tak długo, aż cały zbiór zostanie posortowany.
A. szybkie (Quicksort)
B. bąbelkowe
C. przez wybór
D. przez wstawianie
Opisany w pytaniu algorytm to właśnie sortowanie bąbelkowe (ang. bubble sort). Polega ono na wielokrotnym przechodzeniu przez zbiór danych i zamienianiu miejscami sąsiadujących elementów, jeśli są w złej kolejności. Czynność ta powtarzana jest do momentu, gdy cały zbiór zostanie uporządkowany i żadne zamiany nie będą już potrzebne. Moim zdaniem, to chyba jeden z najbardziej intuicyjnych algorytmów sortowania, jakie się poznaje na początku nauki programowania – łatwo go zaimplementować, bo wymaga właściwie tylko dwóch pętli i porównania sąsiednich elementów. W praktyce bubble sort raczej rzadko używa się w profesjonalnych projektach, bo jego złożoność czasowa to O(n^2), co przy dużych zbiorach jest nieefektywne. Jednak czasami, na bardzo małych listach albo gdy szybko trzeba zrobić prosty prototyp, to można sięgnąć po „bąbelki”. Z mojego doświadczenia wynika też, że sortowanie bąbelkowe dobrze obrazuje podstawowe zasady algorytmiki, na przykład jak działa iteracja czy wymiana miejscami zmiennych – to przydatne w nauce. W wielu językach programowania, nawet tych nowoczesnych, można spotkać przykłady z bubble sort jako ilustrację podstaw. To taki klasyk – mało kto używa go zawodowo, ale każdy programista powinien wiedzieć, jak działa. Warto też pamiętać, że istnieją optymalizacje bubble sortu, np. wcześniejsze zakończenie, gdy w danej iteracji nie wystąpiła żadna zamiana. No i taka ciekawostka: choć algorytm nie jest specjalnie szybki, to bardzo łatwo go zaimplementować nawet w językach niskopoziomowych, bo nie wymaga dodatkowej pamięci.