Maj 2025

Matura Rozszerzona Informatyka 2025 Maj
Rozwiązania krok po kroku

Oficjalny arkusz CKE z informatyki na poziomie rozszerzonym. Egzamin sprawdza wiedzę z kluczowych dziedzin informatyki: od analizy algorytmów rekurencyjnych i programowania (przetwarzanie ciągów znaków, tablice wielowymiarowe, systemy liczbowe), przez teorię i architekturę komputerów (arytmetyka binarna, cyberbezpieczeństwo), aż po zaawansowaną analizę danych z wykorzystaniem arkuszy kalkulacyjnych oraz relacyjnych baz danych i języka SQL.

Czas: 210 min
📄 Pobierz Arkusz PDF

Matura Rozszerzona Informatyka Maj 2025

3 pkt
Zadanie 1.

Funkcja rekurencyjna

Dana jest rekurencyjna funkcja przestaw, której parametrem jest nieujemna liczba całkowita:

przestaw(n):
  r <- n mod 100
  a <- r div 10
  b <- r mod 10
  n <- n div 100
  jeżeli n > 0
      w <- a + 10 * b + 100 * przestaw(n)
  w przeciwnym razie
      jeżeli a > 0
          w <- a + 10 * b
      w przeciwnym razie
          w <- b
  wynikiem jest w

Uwaga:
Operator mod oznacza resztę z dzielenia, natomiast div – część całkowitą z dzielenia.

Podpunkt 1.1. (0–3 pkt)

Uzupełnij tabelę – wpisz w drugiej kolumnie wynik funkcji przestaw(n) dla podanych wartości argumentu nn oraz wpisz w trzeciej kolumnie liczbę wywołań funkcji przestaw łącznie z pierwszym wywołaniem z parametrem nn.

nnWynik działania funkcji przestawLiczba wywołań funkcji przestaw
3164981346893
43657688
154005710
998877665544321
💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Zrozumienie algorytmu

    Analizując kod widzimy, że algorytm odcina od końca po dwie cyfry z liczby (dzięki r <- n mod 100). Następnie dzieli tę dwucyfrową końcówkę na dziesiątki (a) i jedności (b).

    Konstrukcja a + 10 * b sprawia, że cyfry w wyciętej parze zamieniają się miejscami. Algorytm robi to rekurencyjnie dla każdej kolejnej pary cyfr, mnożąc wynik wywołania rekurencyjnego przez 100, aby przesunąć go w lewo.

    Liczba wywołań: Funkcja jest wywoływana raz dla każdej pary cyfr. Jeśli liczba ma nieparzystą liczbę cyfr, ostatnia przetwarzana cyfra (najbardziej znacząca) traktowana jest jako "para" z jedną cyfrą (wtedy a = 0). Liczba wywołań to matematycznie liczba cyfr2\lceil \frac{\text{liczba cyfr}}{2} \rceil. Jeśli liczba n=0n=0, liczba wywołań wynosi 1.

  • 2

    Krok 2: Analiza dla n = 43657688

    Dzielimy liczbę na pary od prawej strony: 43 | 65 | 76 | 88. Zamieniamy cyfry w każdej parze miejscami:

    • 88 staje się 88
    • 76 staje się 67
    • 65 staje się 56
    • 43 staje się 34

    Sklejamy od lewej: 34566788. Liczba składa się z 8 cyfr, więc mamy 4 pary. Liczba wywołań wynosi 4.

  • 3

    Krok 3: Analiza dla n = 154005710

    Liczba ma 9 cyfr. Dzielimy na pary od prawej: 1 | 54 | 00 | 57 | 10. Zamieniamy w każdej parze:

    • 10 staje się 01
    • 57 staje się 75
    • 00 staje się 00
    • 54 staje się 45
    • 1 staje się 1 (samotna cyfra pozostaje bez zmian)

    Sklejamy od lewej: 145007501. Mamy 9 cyfr, czyli 5 porcji do przetworzenia. Liczba wywołań wynosi 5.

  • 4

    Krok 4: Analiza dla n = 998877665544321

    Liczba ma 15 cyfr. Podział od prawej: 9 | 98 | 87 | 76 | 65 | 54 | 43 | 21. Zamieniamy cyfry w parach:

    • ... 21 \rightarrow 12
    • ... 43 \rightarrow 34
    • (i tak dalej, każda para jest po prostu odwracana)
    • ... 9 \rightarrow 9

    Wynik po sklejeniu: 989786756453412. 15 cyfr oznacza 8 wywołań rekurencyjnych (7 pełnych par + jedna resztkowa jedynka). Liczba wywołań wynosi 8.

Matura Rozszerzona Informatyka

2 pkt
Zadanie 1.2.

Oceń prawdziwość podanych zdań. Zaznacz P, jeśli zdanie jest prawdziwe, albo F – jeśli jest fałszywe.

Niech nn będzie liczbą kk-cyfrową, gdzie k>0k > 0. Liczba wywołań funkcji przestaw w zależności od kk jest równa:

1.k2\frac{k}{2}PF
2.

(k+1) div 2(k + 1) \text{ div } 2 (gdzie div oznacza dzielenie całkowite)

PF
3.{k2gdy k jest liczbą parzystąk+12gdy k jest liczbą nieparzystą\begin{cases} \frac{k}{2} & \text{gdy } k \text{ jest liczbą parzystą} \\ \frac{k+1}{2} & \text{gdy } k \text{ jest liczbą nieparzystą} \end{cases}PF
4.k+12\frac{k+1}{2}PF
💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Wnioski z poprzedniego podpunktu

    Z zadania 1.1 wiemy, że funkcja pobiera po dwie cyfry. Jeśli liczba ma nieparzystą liczbę cyfr, ostatnia (najbardziej znacząca) cyfra wymaga dodatkowego wywołania.

    Dla k=4k=4 (np. 1234) mamy 2 wywołania.
    Dla k=5k=5 (np. 12345) mamy 3 wywołania.
    Dla k=8k=8 mamy 4 wywołania.
    Dla k=9k=9 mamy 5 wywołań.

    Możemy wykorzystać te testowe wartości, by sprawdzić poprawność każdego ze wzorów z tabeli.

  • 2

    Krok 2: Analiza wierszy 1 i 4 (Fałsz)

    Liczba wywołań funkcji zawsze musi być liczbą całkowitą (nie można wywołać funkcji 2,5 raza).

    • Wiersz 1: Wzór k2\frac{k}{2}. Jeśli podstawimy nieparzyste k=5k=5, otrzymamy 2,52,5. To nie jest liczba całkowita, więc zdanie jest Fałszywe (F).
    • Wiersz 4: Wzór k+12\frac{k+1}{2}. Jeśli podstawimy parzyste k=4k=4, otrzymamy 52=2,5\frac{5}{2} = 2,5. Znowu ułamek, więc zdanie jest Fałszywe (F).
  • 3

    Krok 3: Analiza wiersza 2 (Prawda)

    Wzór to (k+1) div 2(k + 1) \text{ div } 2. Zobaczmy, jak zachowa się dla naszych wartości testowych:

    • Dla parzystego k=4k=4: (4+1) div 2=5 div 2=2(4+1) \text{ div } 2 = 5 \text{ div } 2 = 2. Zgadza się z naszymi ustaleniami.
    • Dla nieparzystego k=5k=5: (5+1) div 2=6 div 2=3(5+1) \text{ div } 2 = 6 \text{ div } 2 = 3. Również się zgadza.

    Ten wzór to programistyczny sposób na zapisanie "sufitu" z dzielenia przez 2 dla liczb całkowitych. Zdanie jest Prawdziwe (P).

  • 4

    Krok 4: Analiza wiersza 3 (Prawda)

    Wzór rozdziela logikę na dwa przypadki:

    • Gdy kk jest parzyste, stosuje k2\frac{k}{2}. Dla k=4k=4 mamy 42=2\frac{4}{2} = 2. Zgadza się.
    • Gdy kk jest nieparzyste, stosuje k+12\frac{k+1}{2}. Dla k=5k=5 mamy 5+12=62=3\frac{5+1}{2} = \frac{6}{2} = 3. Również się zgadza.

    To matematyczny zapis tego samego algorytmu, co w wierszu 2. Zdanie jest Prawdziwe (P).

    Ostateczne odpowiedzi: 1 - F, 2 - P, 3 - P, 4 - F

Matura Rozszerzona Informatyka Maj 2025

4 pkt
Zadanie 1.3.

W postaci pseudokodu lub w wybranym języku programowania napisz nierekurencyjną funkcję przestaw2, która dla danej nieujemnej liczby całkowitej nn da taką samą wartość jak przestaw(n).

Uwaga: Twój algorytm może używać wyłącznie zmiennych przechowujących liczby całkowite oraz może operować wyłącznie na liczbach całkowitych. W zapisie możesz wykorzystać tylko operacje arytmetyczne: dodawanie, odejmowanie, mnożenie, dzielenie, dzielenie całkowite, resztę z dzielenia oraz porównywanie liczb, instrukcje sterujące, przypisania do zmiennych lub samodzielnie napisane funkcje, wykorzystujące wyżej wymienione operacje.

Zabronione jest używanie funkcji wbudowanych oraz operatorów innych niż wymienione, w tym – funkcji przestaw.

Specyfikacja:
Dane
  • nn – nieujemna liczba całkowita
Wynik
  • ww – nieujemna liczba całkowita, wynik działania taki sam jak po wykonaniu przestaw(n)
💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Zrozumienie mechanizmu usuwania rekurencji

    Rekurencja w oryginalnej funkcji działała tak, że odkładała kolejne pary cyfr na "stos", a przy wracaniu (zwijaniu rekurencji) mnożyła wyniki przez 100, aby przesunąć je na odpowiednie pozycje dziesiętne w lewo.

    Aby napisać wersję nierekurencyjną (iteracyjną), musimy użyć pętli (np. while). Zamiast polegać na stosie wywołań do przesuwania wartości o 100, stworzymy własną zmienną pomocniczą (nazwijmy ją mnoznik), która będzie startować od 1 i w każdym obiegu pętli będzie mnożona przez 100.

  • 2

    Krok 2: Odwzorowanie logiki warunkowej

    Musimy przenieść logikę z oryginalnej funkcji do wnętrza pętli dopóki n > 0:

    • Wyciągamy dwie ostatnie cyfry: r = n mod 100
    • Rozbijamy je na dziesiątki (a = r div 10) i jedności (b = r mod 10)
    • Skracamy n o dwie cyfry: n = n div 100
    • Dodajemy do wyniku przeliczone wartości pomnożone przez obecny mnoznik. Musimy dokładnie skopiować instrukcje warunkowe jeżeli, które obsługiwały ostatnią, niepełną parę cyfr.
  • 3

    Krok 3: Implementacja algorytmu

    Oto trzy poprawne sposoby zapisu tego algorytmu – możesz wybrać ten, który jest dla Ciebie najbardziej czytelny (na maturze wystarczy podać jeden z nich).

    Opcja A: Pseudokod
    funkcja przestaw2(n):
      jeżeli n = 0
          zwróć 0
          
      w <- 0
      mnoznik <- 1
      
      dopóki n > 0 wykonuj:
          r <- n mod 100
          a <- r div 10
          b <- r mod 10
          n <- n div 100
          
          jeżeli n > 0
              w <- w + (a + 10 * b) * mnoznik
          w przeciwnym razie
              jeżeli a > 0
                  w <- w + (a + 10 * b) * mnoznik
              w przeciwnym razie
                  w <- w + b * mnoznik
                  
          mnoznik <- mnoznik * 100
          
      wynikiem jest w
    Opcja B: Język C++
    int przestaw2(int n) {
      if (n == 0) return 0;
      
      int w = 0;
      int mnoznik = 1;
      
      while (n > 0) {
          int r = n % 100;
          int a = r / 10;
          int b = r % 10;
          n = n / 100;
          
          if (n > 0) {
              w = w + (a + 10 * b) * mnoznik;
          } else {
              if (a > 0) {
                  w = w + (a + 10 * b) * mnoznik;
              } else {
                  w = w + b * mnoznik;
              }
          }
          mnoznik = mnoznik * 100;
      }
      return w;
    }
    Opcja C: Język Python
    def przestaw2(n):
      if n == 0:
          return 0
          
      w = 0
      mnoznik = 1
      
      while n > 0:
          r = n % 100
          a = r // 10
          b = r % 10
          n = n // 100
          
          if n > 0:
              w = w + (a + 10 * b) * mnoznik
          else:
              if a > 0:
                  w = w + (a + 10 * b) * mnoznik
              else:
                  w = w + b * mnoznik
                  
          mnoznik = mnoznik * 100
          
      return w

Matura Rozszerzona Informatyka Maj 2025

2 pkt
Zadanie 2.1.

Zapis symboliczny – Wstęp do zadania

W pliku symbole.txt zapisano 2000 napisów. Każdy z nich jest zapisany w osobnym wierszu i składa się z dokładnie 12 znaków spośród: o, +, *.

Napisz program (lub kilka programów) znajdujący(-ch) odpowiedzi do podanych zadań. Każdą odpowiedź zapisz w pliku wyniki2.txt i poprzedź ją numerem oznaczającym zadanie.

Do Twojej dyspozycji jest plik symbole_przyklad.txt, który zawiera 20 wierszy danych spełniających warunki zadania. Odpowiedzi dla pliku symbole_przyklad.txt są podane pod każdym zadaniem. Pamiętaj, że Twój program musi ostatecznie zadziałać na pliku symbole.txt zawierającym 2000 napisów.

Zadanie 2.1. (0–2 pkt)

Podaj wszystkie takie napisy z pliku symbole.txt, które są palindromami (czytane od przodu i od tyłu są takie same). Wypisz je po jednym w wierszu, w kolejności takiej jak w pliku symbole.txt.

Odpowiedź dla pliku symbole_przyklad.txt to:
oooo+**+oooo
(w tym pliku jest jeden palindrom)

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Analiza problemu i algorytm

    Zadanie polega na wczytaniu pliku linia po linii i sprawdzeniu dla każdego napisu, czy jest palindromem.

    Palindrom to ciąg znaków, który wygląda tak samo niezależnie od tego, czy czytamy go od lewej do prawej, czy od prawej do lewej. Najprostszym algorytmicznym sposobem na weryfikację jest:

    • Utworzenie odwróconej kopii badanego napisu.
    • Porównanie oryginalnego napisu z jego odwróconą wersją. Jeśli są identyczne – mamy palindrom.

    W języku Python można to zrobić za pomocą tzw. slicingu (napis[::-1]), a w C++ używając funkcji std::reverse.

  • 2

    Krok 2: Implementacja – Python

    def solve_2_1():
      with open('symbole.txt', 'r') as file:
          lines = file.read().splitlines()
          
      print("Odpowiedzi do zadania 2.1:")
      for line in lines:
          # line[::-1] tworzy odwrócony ciąg znaków
          if line == line[::-1]:
              print(line)
    
    solve_2_1()
  • 3

    Krok 3: Implementacja – C++

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <algorithm>
    
    using namespace std;
    
    int main() {
      ifstream file("symbole.txt");
      string line;
      
      cout << "Odpowiedzi do zadania 2.1:" << endl;
      while (file >> line) {
          string reversed_line = line;
          // Odwracamy skopiowany string
          reverse(reversed_line.begin(), reversed_line.end());
          
          // Porównujemy oryginał z odwróconym
          if (line == reversed_line) {
              cout << line << endl;
          }
      }
      return 0;
    }

Matura Rozszerzona Informatyka Maj 2025

4 pkt
Zadanie 2.2.

W pliku symbole.txt szukamy „kwadratów” złożonych z dziewięciu sąsiadujących identycznych symboli:

+ + +
+ + +
+ + +
lub
o o o
o o o
o o o
lub
* *
*
* *

Podaj, ile takich kwadratów występuje w pliku symbole.txt. Jeżeli w pliku występuje jeden taki kwadrat, podaj numer wiersza i numer pozycji w wierszu (licząc od 1) jego środkowego pola. Jeżeli jest więcej takich kwadratów, podaj numer wiersza i numer pozycji w wierszu dla środkowego pola każdego z nich.

Przykład:

Poniżej podano 6 wierszy przykładowych danych (po 12 znaków w każdym wierszu):

1. + * * + o * o + + * o +
2. + + + o o o o * o * * *
3. + o * o o o o * * + + +
4. * + * o o o o o + + +
5. o * * o + + + o + + +
6. o o o o + + * * * * + o
💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Strategia wyszukiwania kwadratu

    Mamy do czynienia z dwuwymiarową tablicą znaków (gdzie wiersze to kolejne linie pliku, a kolumny to znaki w napisie). Naszym celem jest znalezienie bloków 3×33 \times 3 wypełnionych tym samym znakiem.

    Najbardziej logicznym punktem zaczepienia jest środkowe pole takiego kwadratu. Zamiast sprawdzać lewy górny róg, możemy iterować po wszystkich potencjalnych "środkach".

    • Współrzędna yy (wiersz) środka może znajdować się od indeksu 1 do liczba_wierszy - 2 (zakładając indeksowanie od 0).
    • Współrzędna xx (kolumna) środka może znajdować się od indeksu 1 do 10 (ponieważ każdy wiersz ma długość 12 znaków, indeksy to 0-11, a środek kwadratu 3×33 \times 3 nie może dotykać krawędzi).
  • 2

    Krok 2: Warunek "Kwadratu"

    Będąc w wybranym polu (wiersz, kolumna), sprawdzamy, jaki jest tam znak (np. char = tablica[wiersz][kolumna]).

    Następnie musimy sprawdzić 88 otaczających go sąsiadów. Jeśli wszystkie 88 znaków wokół środka ma taką samą wartość jak środek, znaleźliśmy pełny kwadrat 3×33 \times 3. Możemy do tego użyć zagnieżdżonej pętli z przesunięciami (offsetami) [-1, 0, 1] dla wiersza i kolumny. Pamiętamy też, by do wyniku (numeru wiersza i kolumny) na końcu dodać 1, ponieważ zadanie wymaga współrzędnych liczonych od jedynki, a w programowaniu indeksujemy od zera.

  • 3

    Krok 3: Implementacja – Python

    def solve_2_2():
      with open('symbole.txt', 'r') as file:
          grid = file.read().splitlines()
          
      rows = len(grid)
      cols = len(grid[0]) if rows > 0 else 0
      
      found_squares = []
      
      # Iterujemy tylko po potencjalnych "środkach"
      for r in range(1, rows - 1):
          for c in range(1, cols - 1):
              center_char = grid[r][c]
              is_square = True
              
              # Sprawdzamy otoczenie 3x3
              for dr in [-1, 0, 1]:
                  for dc in [-1, 0, 1]:
                      if grid[r + dr][c + dc] != center_char:
                          is_square = False
                          break
                  if not is_square:
                      break
                      
              if is_square:
                  # Zapisujemy pozycję (indeksowane od 1)
                  found_squares.append((r + 1, c + 1))
                  
      print(f"Liczba kwadratów: {len(found_squares)}")
      for r, c in found_squares:
          print(f"Środek w wierszu: {r}, na pozycji: {c}")
    
    solve_2_2()
  • 4

    Krok 4: Implementacja – C++

    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <string>
    
    using namespace std;
    
    struct Point {
      int row;
      int col;
    };
    
    int main() {
      ifstream file("symbole.txt");
      vector<string> grid;
      string line;
      
      // Wczytywanie danych do dwuwymiarowej tablicy (wektora stringów)
      while (file >> line) {
          grid.push_back(line);
      }
      
      int rows = grid.size();
      if (rows == 0) return 0;
      int cols = grid[0].length();
      
      vector<Point> found_squares;
      
      // Iterujemy po potencjalnych środkach kwadratu
      for (int r = 1; r < rows - 1; ++r) {
          for (int c = 1; c < cols - 1; ++c) {
              char center_char = grid[r][c];
              bool is_square = true;
              
              // Weryfikacja wszystkich 9 komórek kwadratu
              for (int dr = -1; dr <= 1; ++dr) {
                  for (int dc = -1; dc <= 1; ++dc) {
                      if (grid[r + dr][c + dc] != center_char) {
                          is_square = false;
                          break;
                      }
                  }
                  if (!is_square) break;
              }
              
              if (is_square) {
                  // Zapamiętujemy pozycję (indeksowane od 1)
                  found_squares.push_back({r + 1, c + 1});
              }
          }
      }
      
      cout << "Liczba kwadratów: " << found_squares.size() << endl;
      for (const auto& pt : found_squares) {
          cout << "Srodek w wierszu: " << pt.row << ", na pozycji: " << pt.col << endl;
      }
      
      return 0;
    }

Matura Rozszerzona Informatyka Maj 2025

2 pkt
Zadanie 2.3.

Informacja do zadań 2.3. i 2.4.

Każdy z napisów podanych w pliku symbole.txt będziemy traktować jako liczbę zapisaną w systemie trójkowym, w którym:

  • znak o odpowiada cyfrze 0
  • znak + odpowiada cyfrze 1
  • znak * odpowiada cyfrze 2.

Zadanie 2.3. (0–2 pkt)

Podaj największą liczbę spośród liczb zapisanych w pliku symbole.txt. W odpowiedzi podaj tę liczbę w zapisie dziesiętnym oraz napis jej odpowiadający.

Odpowiedź dla pliku symbole_przyklad.txt to:
519789 **+oooo++o

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Algorytm zamiany na system dziesiętny

    Aby porównać liczby i znaleźć największą z nich, musimy zamienić napisane ciągi znaków na standardowe liczby dziesiętne. System trójkowy opiera się na potęgach liczby 3.

    Możemy to zrobić za pomocą klasycznego algorytmu Hornera lub iterując po znakach od lewej do prawej:

    • Inicjujemy zmienną wartosc = 0.
    • Dla każdego znaku w ciągu, mnożymy wartosc przez 3 i dodajemy wartość odpowiadającą temu znakowi (o to 0, + to 1, * to 2).

    Następnie dla każdej linii w pliku sprawdzamy, czy wyliczona wartość jest większa od dotychczasowego maksimum. Jeśli tak, aktualizujemy maksimum oraz zapamiętujemy oryginalny ciąg znaków.

  • 2

    Krok 2: Implementacja – Python

    W Pythonie możemy wykorzystać wbudowaną funkcję int(ciąg, podstawa), najpierw zamieniając znaki na odpowiednie cyfry.

    def solve_2_3():
      with open('symbole.txt', 'r') as file:
          lines = file.read().splitlines()
          
      max_dec = -1
      max_sym = ""
      
      # Tworzymy mapowanie znaków na cyfry
      trans = str.maketrans('o+*', '012')
      
      for line in lines:
          # Zamieniamy 'o+*' na '012' i parsujemy jako system trójkowy
          dec_val = int(line.translate(trans), 3)
          
          if dec_val > max_dec:
              max_dec = dec_val
              max_sym = line
              
      print("Odpowiedź do zadania 2.3:")
      print(f"{max_dec} {max_sym}")
    
    solve_2_3()
  • 3

    Krok 3: Implementacja – C++

    W C++ napiszemy własną funkcję konwertującą, aby mieć pełną kontrolę i zachować czytelność bez zewnętrznych bibliotek. Używamy long long, aby uniknąć przepełnienia (overflow).

    #include <iostream>
    #include <fstream>
    #include <string>
    
    using namespace std;
    
    long long to_decimal(const string& sym) {
      long long value = 0;
      for (char c : sym) {
          value *= 3;
          if (c == 'o') value += 0;
          else if (c == '+') value += 1;
          else if (c == '*') value += 2;
      }
      return value;
    }
    
    int main() {
      ifstream file("symbole.txt");
      string line;
      
      long long max_dec = -1;
      string max_sym = "";
      
      while (file >> line) {
          long long current_dec = to_decimal(line);
          if (current_dec > max_dec) {
              max_dec = current_dec;
              max_sym = line;
          }
      }
      
      cout << "Odpowiedz do zadania 2.3:" << endl;
      cout << max_dec << " " << max_sym << endl;
      
      return 0;
    }

Matura Rozszerzona Informatyka Maj 2025

3 pkt
Zadanie 2.4.

Oblicz sumę wszystkich liczb z pliku symbole.txt. Podaj jej wartość w zapisie dziesiętnym oraz w zapisie trójkowym z użyciem symboli: o, +, *.

Odpowiedź dla pliku symbole_przyklad.txt to:
4841542 +oooo****+oo+o+

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Sumowanie i algorytm zamiany na system trójkowy

    Sumę dziesiętną łatwo policzymy dodając do siebie wartości wyliczone funkcją z poprzedniego podpunktu. Problem pojawia się w drugim kroku – musimy zamienić uzyskaną (dużą) sumę dziesiętną z powrotem na system symboliczny.

    Konwersję z systemu dziesiętnego na dowolny inny (tutaj na system o podstawie 3) przeprowadzamy metodą reszt z dzielenia:

    • Dzielimy liczbę przez 3 i odczytujemy resztę.
    • Jeśli reszta to 0, dopisujemy z przodu znak o. Jeśli 1, dopisujemy +. Jeśli 2, dopisujemy *.
    • Wynik dzielenia całkowitego staje się nową wartością do podzielenia w następnym kroku.
    • Proces kończy się, gdy liczba do podzielenia spadnie do 0.
  • 2

    Krok 2: Implementacja – Python

    def solve_2_4():
      trans_to_dec = str.maketrans('o+*', '012')
      total_sum = 0
      
      with open('symbole.txt', 'r') as file:
          for line in file:
              line = line.strip()
              total_sum += int(line.translate(trans_to_dec), 3)
              
      # Konwersja sumy dziesiętnej z powrotem na symbole trójkowe
      temp = total_sum
      sym_result = ""
      symbols = ['o', '+', '*']
      
      if temp == 0:
          sym_result = "o"
      else:
          while temp > 0:
              remainder = temp % 3
              sym_result = symbols[remainder] + sym_result
              temp = temp // 3
              
      print("Odpowiedź do zadania 2.4:")
      print(f"{total_sum} {sym_result}")
    
    solve_2_4()
  • 3

    Krok 3: Implementacja – C++

    #include <iostream>
    #include <fstream>
    #include <string>
    
    using namespace std;
    
    long long to_decimal(const string& sym) {
      long long value = 0;
      for (char c : sym) {
          value *= 3;
          if (c == 'o') value += 0;
          else if (c == '+') value += 1;
          else if (c == '*') value += 2;
      }
      return value;
    }
    
    string to_symbolic(long long num) {
      if (num == 0) return "o";
      
      string result = "";
      while (num > 0) {
          int remainder = num % 3;
          if (remainder == 0) result = "o" + result;
          else if (remainder == 1) result = "+" + result;
          else if (remainder == 2) result = "*" + result;
          
          num /= 3;
      }
      return result;
    }
    
    int main() {
      ifstream file("symbole.txt");
      string line;
      long long total_sum = 0;
      
      while (file >> line) {
          total_sum += to_decimal(line);
      }
      
      cout << "Odpowiedz do zadania 2.4:" << endl;
      cout << total_sum << " " << to_symbolic(total_sum) << endl;
      
      return 0;
    }

Matura Rozszerzona Informatyka Maj 2025

2 pkt
Zadanie 3.1.

Dron

Tor lotu pewnego drona składa się z prostych odcinków. Lot rozpoczyna się w punkcie (0,0)(0, 0), a kończy w punkcie (20000,0)(20000, 0). Dron poza startem i lądowaniem jest zawsze na wysokości większej od zera.

Plik dron.txt zawiera 100 wierszy, w których zapisano dane dotyczące ruchu drona. W każdym wierszu jest zapisana para liczb całkowitych rozdzielonych znakiem spacji. Pierwsza liczba oznacza przemieszczenie drona (odległość) w poziomie od ostatniej pozycji – jest to zawsze liczba dodatnia. Druga liczba oznacza przemieszczenie w pionie od ostatniej pozycji. Jeśli druga liczba jest dodatnia, to dron wykonał ruch w górę, jeśli ujemna – w dół, a jeśli równa 0 – nie zmieniał wysokości.

Przykład 1.
Dla przykładowych danych:
3000 2000
2000 9000
5000 -7000
5000 4000
3000 6000
2000 -14000

gdzie:
xx – odległość w poziomie od punktu startowego
yy – wysokość (odległość w pionie od punktu startowego)
[A,B][A, B] – umieszczone na wykresie pary liczb oznaczające przemieszczenia drona odpowiednio w poziomie i w pionie.

Do Twojej dyspozycji jest plik dron_przyklad.txt zawierający 10 wierszy danych w opisanej postaci. Odpowiedzi dla pliku dron_przyklad.txt są podane pod każdym zadaniem. Pamiętaj, że Twój program musi ostatecznie zadziałać na pliku dron.txt zawierającym 100 wierszy danych.

Podpunkt 3.1. (0–2 pkt)

Dla każdego przesunięcia [A,B][A, B] zapisanego w pliku dron.txt oblicz największy wspólny dzielnik (NWD) wartości bezwzględnych liczb AA i BB. Podaj liczbę par [A,B][A, B], dla których największy wspólny dzielnik wartości bezwzględnych liczb AA i BB jest większy od 1.

Uwaga: przyjmujemy, że NWD(A, 0) = A.

Odpowiedź dla pliku dron_przyklad.txt to:
6

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Analiza problemu matematycznego

    Naszym celem jest iteracja po wszystkich parach [A,B][A, B] z pliku tekstowego i sprawdzenie warunku: NWD(A,B)>1\text{NWD}(|A|, |B|) > 1.

    • Wartość bezwzględna: Z treści zadania wynika, że AA jest zawsze dodatnie, więc nie musimy zmieniać jego znaku. Liczba BB może być ujemna (gdy dron opada), dlatego musimy na niej wymusić wartość bezwzględną (np. za pomocą funkcji abs()).
    • Algorytm NWD (Największy Wspólny Dzielnik): Najlepszą i najszybszą metodą obliczania NWD jest algorytm Euklidesa. Warto zauważyć, że klasyczny algorytm Euklidesa (oparty na reszcie z dzielenia) naturalnie obsługuje przypadek podany w uwadze do zadania, czyli NWD(A,0)=A\text{NWD}(A, 0) = A.
  • 2

    Krok 2: Implementacja – Python

    W Pythonie możemy skorzystać z gotowej funkcji math.gcd(), która jest zoptymalizowana i poprawnie obsługuje zera oraz wartości ujemne (choć dla porządku i tak zastosujemy abs() zgodnie z poleceniem).

    import math
    
    def solve_3_1():
      count = 0
      with open('dron.txt', 'r') as file:
          for line in file:
              # Rozdzielamy linię na dwie liczby
              a_str, b_str = line.split()
              A = int(a_str)
              B = int(b_str)
              
              # Pobieramy wartość bezwzględną dla B
              B_abs = abs(B)
              
              # Sprawdzamy warunek zadania
              if math.gcd(A, B_abs) > 1:
                  count += 1
                  
      print(f"Odpowiedź do zadania 3.1: {count}")
    
    solve_3_1()
  • 3

    Krok 3: Implementacja – C++

    W C++ od standardu C++17 istnieje wbudowana funkcja std::gcd w bibliotece <numeric>. Poniżej jednak zapisałem własną, klasyczną implementację algorytmu Euklidesa, co jest bardzo dobrą i bezpieczną praktyką maturalną.

    #include <iostream>
    #include <fstream>
    #include <cmath>
    
    using namespace std;
    
    // Klasyczny Algorytm Euklidesa (wersja iteracyjna z resztą z dzielenia)
    int nwd(int a, int b) {
      while (b != 0) {
          int temp = b;
          b = a % b;
          a = temp;
      }
      // Zauważ, że jeśli na start b = 0, pętla się nie wykona i zwrócimy a.
      // Daje to poprawny wynik NWD(A, 0) = A.
      return a;
    }
    
    int main() {
      ifstream file("dron.txt");
      int A, B;
      int count = 0;
      
      // Wczytywanie pliku para po parze dopóki są dane
      while (file >> A >> B) {
          int B_abs = abs(B); // Wartość bezwzględna
          
          if (nwd(A, B_abs) > 1) {
              count++;
          }
      }
      
      cout << "Odpowiedz do zadania 3.1: " << count << endl;
      return 0;
    }

Matura Rozszerzona Informatyka Maj 2025

4 pkt
Zadanie 3.2.

Podpunkt 3.2. (0–4 pkt)

Rozważmy wszystkie punkty, w których dron znajdował się po wykonaniu kolejnych ruchów (przesunięć).

Dla danych z przykładu 1. będą to punkty: (3000,2000)(3000, 2000), (5000,11000)(5000, 11000), (10000,4000)(10000, 4000), (15000,8000)(15000, 8000), (18000,14000)(18000, 14000) i (20000,0)(20000, 0).

a) Podaj, ile spośród wszystkich rozważanych punktów znajduje się wewnątrz kwadratu o wierzchołkach (0,0)(0, 0), (0,5000)(0, 5000), (5000,5000)(5000, 5000), (5000,0)(5000, 0). Nie liczymy punktów leżących na krawędziach kwadratu.

b) Spośród wszystkich rozważanych punktów znajdź i podaj trzy różne, takie, że jeden z nich jest środkiem odcinka o końcach w pozostałych dwóch. Jest tylko jedna taka trójka punktów.

Uwaga: punkty należące do szukanej trójki nie muszą być trzema kolejnymi punktami, do których przemieszczał się dron.

Odpowiedź dla pliku dron_przyklad.txt to:
a) 2 b) (14000, 3000), (16000, 2000), (18000, 1000)

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Przetworzenie przesunięć na współrzędne punktów

    Plik wejściowy podaje nam jedynie "wektory" przesunięć (o ile zmienia się xx i yy). Aby odpowiedzieć na pytania z zadania, musimy najpierw obliczyć dokładne współrzędne każdego punktu.

    Dron startuje w punkcie (0,0)(0, 0). Po wczytaniu każdej linii z pliku, do aktualnej pozycji xx dodajemy pierwszą liczbę, a do yy drugą. Nowe współrzędne zapisujemy na listę/do tablicy. W ten sposób otrzymamy 100 punktów docelowych.

  • 2

    Krok 2: Logika dla podpunktu A

    Musimy sprawdzić, czy punkt znajduje się wewnątrz kwadratu, z wyłączeniem jego krawędzi. Współrzędne wierzchołków to granice od 0 do 5000.

    Dla każdego wygenerowanego w Kroku 1 punktu (x,y)(x, y) sprawdzamy warunek:
    x > 0 AND x < 5000 AND y > 0 AND y < 5000.
    Zliczamy wszystkie punkty spełniające ten warunek.

  • 3

    Krok 3: Logika dla podpunktu B

    Szukamy trzech punktów P1,P2,P3P_1, P_2, P_3, gdzie jeden jest środkiem odcinka łączącego dwa pozostałe. Z treści (oraz faktu, że przesunięcie w osi X jest zawsze dodatnie) wiemy, że punkty są naturalnie posortowane względem osi X.

    Jeśli weźmiemy trzy chronologiczne punkty Pi,Pj,PkP_i, P_j, P_k (gdzie indeksy i<j<ki < j < k), to jedynym kandydatem na środek jest punkt "środkowy" w czasie, czyli PjP_j.

    Punkt Pj=(xj,yj)P_j = (x_j, y_j) jest środkiem odcinka pomiędzy Pi=(xi,yi)P_i = (x_i, y_i) a Pk=(xk,yk)P_k = (x_k, y_k) wtedy i tylko wtedy, gdy:
    xj=xi+xk2x_j = \frac{x_i + x_k}{2} oraz yj=yi+yk2y_j = \frac{y_i + y_k}{2}.

    Dla uniknięcia ułamków warunek ten można zapisać jako:
    2 * x_j == x_i + x_k AND 2 * y_j == y_i + y_k.
    Aby to sprawdzić, użyjemy trzech zagnieżdżonych pętli przechodzących przez wszystkie możliwe trójki punktów.

  • 4

    Krok 4: Implementacja – Python

    def solve_3_2():
      points = []
      curr_x, curr_y = 0, 0
      
      # KROK 1: Generowanie punktów
      with open('dron.txt', 'r') as file:
          for line in file:
              dx, dy = map(int, line.split())
              curr_x += dx
              curr_y += dy
              points.append((curr_x, curr_y))
              
      # KROK 2: Podpunkt A
      count_inside = 0
      for x, y in points:
          if 0 < x < 5000 and 0 < y < 5000:
              count_inside += 1
              
      print(f"a) {count_inside}")
      
      # KROK 3: Podpunkt B
      n = len(points)
      # 3 zagnieżdżone pętle dla wyboru 3 punktów (i < j < k)
      for i in range(n):
          for j in range(i + 1, n):
              for k in range(j + 1, n):
                  xi, yi = points[i]
                  xj, yj = points[j]
                  xk, yk = points[k]
                  
                  # Sprawdzamy czy punkt j jest środkiem
                  if xi + xk == 2 * xj and yi + yk == 2 * yj:
                      print(f"b) ({xi}, {yi}), ({xj}, {yj}), ({xk}, {yk})")
                      return # Przerywamy po znalezieniu pierwszej trójki
    
    solve_3_2()
  • 5

    Krok 5: Implementacja – C++

    #include <iostream>
    #include <fstream>
    #include <vector>
    
    using namespace std;
    
    struct Point {
      long long x;
      long long y;
    };
    
    int main() {
      ifstream file("dron.txt");
      vector<Point> points;
      long long dx, dy;
      long long curr_x = 0, curr_y = 0;
      
      // KROK 1: Wczytywanie i generowanie współrzędnych
      while (file >> dx >> dy) {
          curr_x += dx;
          curr_y += dy;
          points.push_back({curr_x, curr_y});
      }
      
      // KROK 2: Podpunkt A
      int count_inside = 0;
      for (const auto& p : points) {
          if (p.x > 0 && p.x < 5000 && p.y > 0 && p.y < 5000) {
              count_inside++;
          }
      }
      cout << "a) " << count_inside << endl;
      
      // KROK 3: Podpunkt B
      int n = points.size();
      for (int i = 0; i < n; ++i) {
          for (int j = i + 1; j < n; ++j) {
              for (int k = j + 1; k < n; ++k) {
                  // Warunek środka odcinka: 2 * srodek = poczatek + koniec
                  if (2 * points[j].x == points[i].x + points[k].x && 
                      2 * points[j].y == points[i].y + points[k].y) {
                      
                      cout << "b) (" << points[i].x << ", " << points[i].y << "), ("
    << points[j].x << ", " << points[j].y << "), ("
    << points[k].x << ", " << points[k].y << ")" << endl;
                      return 0; // Znaleziono trójkę, kończymy
                  }
              }
          }
      }
      
      return 0;
    }

Matura Rozszerzona Informatyka Maj 2025

1 pkt
Zadanie 4.

Złośliwe oprogramowanie

Dokończ zdanie. Zaznacz właściwą odpowiedź spośród podanych.

Program typu keylogger służy do

A. szyfrowania informacji do postaci uniemożliwiającej jej odczytanie bez zdefiniowanego klucza.

B. przechowywania danych logowania, w tym haseł, w bezpiecznym miejscu na dysku użytkownika.

C. generowania kodu, który umożliwia użytkownikowi bankowości elektronicznej wykonanie operacji.

D. przechwytywania i gromadzenia informacji o naciśniętych klawiszach.

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Wyjaśnienie pojęć

    Pojęcie keylogger pochodzi z języka angielskiego i stanowi zbitkę dwóch słów: key (klawisz) oraz logger (rejestrator/dziennik).

    • Opcja A opisuje działanie oprogramowania typu Ransomware lub narzędzi kryptograficznych.
    • Opcja B to definicja menedżera haseł (np. KeePass, 1Password).
    • Opcja C odnosi się do tokenów bezpieczeństwa lub aplikacji uwierzytelniających (np. Google Authenticator).
    • Opcja D to poprawna definicja keyloggera, czyli złośliwego oprogramowania (bądź urządzenia sprzętowego), które w tajemnicy przed użytkownikiem nagrywa wszystko, co ten wpisuje na klawiaturze.

    Prawidłowa odpowiedź to zatem D.

Matura Rozszerzona Informatyka Maj 2025

2 pkt
Zadanie 5.

Arytmetyka binarna

Poniżej sposobem pisemnym dodano dwie liczby podane w zapisie binarnym. Uzupełnij brakujące cyfry tak, aby działanie było wykonane poprawnie.

      1  1 [ ] 0  1  0  1  1  0 [ ] 1
+        1  1  0  0 [ ] 1  0  1  1  1
-------------------------------------
 1 [ ] 0  1  1  0  0  1 [ ][ ] 1  0
💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Analiza od prawej strony (pozycje 1–4)

    Dodawanie pisemne w systemie binarnym wykonujemy od prawej do lewej, pamiętając, że 1+1=1021 + 1 = 10_2 (zapisujemy 0 i przenosimy 1 dalej), a 1+1+1=1121 + 1 + 1 = 11_2 (zapisujemy 1 i przenosimy 1 dalej).

    • 1. kolumna: 1+1=1021 + 1 = 10_2. Zapisano 0 na dole, a 1 przechodzi dalej. Zgadza się.
    • 2. kolumna: Mamy górne okienko, dolne 1 oraz przeniesione 1. Wynik na dole to 1.
      Działanie: [ ] + 1 + 1 = ...1. Musi to być 3 (czyli 11211_2), by zapisać 1. Stąd górne okienko to 1. Przenosimy 1.
    • 3. kolumna: Górne 0, dolne 1, przeniesione 1.
      Działanie: 0+1+1=1020 + 1 + 1 = 10_2. Dolne okienko to 0. Przenosimy 1.
    • 4. kolumna: Górne 1, dolne 0, przeniesione 1.
      Działanie: 1+0+1=1021 + 0 + 1 = 10_2. Dolne okienko to 0. Przenosimy 1.
  • 2

    Krok 2: Analiza środkowej części (pozycje 5–8)

    Kontynuujemy z przeniesieniem 1 z poprzedniego kroku.

    • 5. kolumna: Górne 1, dolne 1, przeniesione 1. 1+1+1=1121 + 1 + 1 = 11_2. Na dole zapisano 1, a 1 przechodzi dalej. Zgadza się.
    • 6. kolumna: Górne 0, dolne okienko, przeniesione 1. Wynik ma wynosić 0.
      Działanie: 0 + [ ] + 1 = ...0. Aby z jedynki zrobić 0, musimy otrzymać 10210_2. Dolne okienko to 1. Przenosimy 1.
    • 7. kolumna: Górne 1, dolne 0, przeniesione 1. 1+0+1=1021 + 0 + 1 = 10_2. Zapisano 0, 1 przechodzi dalej. Zgadza się.
    • 8. kolumna: Górne 0, dolne 0, przeniesione 1. 0+0+1=120 + 0 + 1 = 1_2. Zapisano 1, brak przeniesienia (czyli przenosimy 0).
  • 3

    Krok 3: Analiza lewej strony (pozycje 9–12)

    Tym razem nie mamy przeniesienia (przeniesienie wynosi 0).

    • 9. kolumna: Górne okienko, dolne 1, brak przeniesienia. Wynik wynosi 1.
      Działanie: [ ] + 1 + 0 = 1_2. Stąd górne okienko to 0. Brak przeniesienia.
    • 10. kolumna: Górne 1, dolne 1. 1+1=1021 + 1 = 10_2. Zapisano 0, przenosimy 1. Zgadza się.
    • 11. kolumna: Górne 1, brak dolnego (0), przeniesione 1.
      Działanie: 1+0+1=1021 + 0 + 1 = 10_2. W okienku wyniku na dole zapisujemy 0. Przenosimy 1.
    • 12. kolumna: Przeniesiona 1 ląduje na samym przodzie wyniku. Zgadza się.
    1 1 [0] 0 1 0 1 1 0 [1] 1 + 1 1 0 0 [1] 1 0 1 1 1 ------------------------------------- 1 [0] 0 1 1 0 0 1 [0][0] 1 0

Matura Rozszerzona Informatyka Maj 2025

2 pkt
Zadanie 6.

Martianeum

W 2033 roku na Marsie wylądowała automatyczna stacja wydobywcza wyposażona w transporter i w autonomiczny dron pobierający ładunki skał zawierających minerał niewystępujący na Ziemi – martianeum.

Stacja działa według następujących zasad:
  • dron codziennie przywozi ładunek z pewnego obszaru Marsa
  • stacja waży ładunek przywieziony przez drona i bada zawartość martianeum
  • jeśli zawartość martianeum w przywiezionym ładunku wynosi co najmniej 1%, to stacja automatycznie wydobywa cały minerał z tego ładunku
  • jeśli na koniec dnia (po wydobyciu martianeum) ilość minerału na stacji osiągnie co najmniej 100 kg, to transporter zabiera 100 kg na orbitę, skąd ładunek jest wysyłany na Ziemi, a transporter wraca do stacji (jeśli na stacji zgromadzone jest więcej niż 100 kg, to nadmiar pozostaje na stacji)
  • początkowy stan magazynu na stacji – 0 kg martianeum.

W pliku tekstowym martianeum.txt w kolejnych wierszach zapisano dane z lat 2033–2038:

data
– data przywozu ładunku w formacie rrrr-mm-dd
nazwa_obszaru
– nazwa obszaru Marsa, z którego ładunek został pobrany
masa [kg]
– masa ładunku drona w kilogramach
zawartość [%]
– zawartość martianeum w próbce w % (nieujemna liczba z jednym miejscem po przecinku, np. 0,1 oznacza 0,1%)
Dane w pliku rozdzielono znakami tabulacji.
Przykład:
data            nazwa_obszaru     masa [kg]     zawartosc [%]
2033-03-03      Cebrenia          27,8          0,2
2033-03-04      Amenthes          11,8          1,7
2033-03-05      Noachis           21,0          6,0
2033-03-06      Coprates          26,3          11,4
2033-03-07      Ismenius Lacus    28,8          0,0
2033-03-08      Mare Boreum       29,2          0,0

Z wykorzystaniem danych zawartych w pliku martianeum.txt oraz dostępnych narzędzi informatycznych wykonaj podane zadania. Wyniki zapisz w pliku tekstowym wyniki6.txt. Odpowiedź do każdego zadania poprzedź numerem tego zadania.

Podpunkt 6.1. (0–2 pkt)

Podaj łączną masę ładunków drona oraz łączną masę martianeum wydobytego przez stację.

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Analiza wymagań dla podpunktu 6.1

    To zadanie wymaga od nas policzenia dwóch sum:

    • Łączna masa ładunków drona: To po prostu suma wszystkich wartości w kolumnie masa [kg].
    • Łączna masa wydobytego martianeum: Musimy wyliczyć dla każdego wiersza masę samego minerału. Pamiętamy o kluczowym warunku: minerał jest wydobywany tylko wtedy, gdy jego zawartość wynosi co najmniej 1%. Jeśli warunek jest spełniony, masa wydobyta to masa_ładunku * (zawartość_w_procentach / 100).

    Ważne: Uważaj na format liczb w pliku! Zarówno masa, jak i procenty zapisane są z przecinkiem (np. 27,8). W Excelu może to zadziałać z automatu (zależnie od ustawień regionalnych), ale w Pythonie konieczna będzie zamiana przecinków na kropki przed konwersją na typ zmiennoprzecinkowy (float).

  • 2

    Krok 2: Rozwiązanie w arkuszu kalkulacyjnym (Excel)

    Zadania tego typu idealnie i bardzo szybko rozwiązuje się w Excelu.

    1. Otwórz plik martianeum.txt w Excelu. Kreator importu automatycznie rozdzieli kolumny po znaku tabulacji.
    2. Pierwsza odpowiedź (łączna masa) to po prostu suma kolumny C. W pustej komórce wpisz:
      =SUMA(C2:C10000).
    3. Aby obliczyć wydobyty minerał, w kolumnie E (np. w komórce E2) stwórz formułę warunkową:
      =JEŻELI(D2>=1; C2*(D2/100); 0)
    4. Przeciągnij formułę z E2 do samego dołu tabeli.
    5. Druga odpowiedź to suma nowo utworzonej kolumny E. Wpisz:
      =SUMA(E2:E10000).
  • 3

    Krok 3: Rozwiązanie w języku Python

    Jeśli wolisz programować, oto prosty skrypt realizujący dokładnie tę samą logikę. Zwróć uwagę na linię z replace(',', '.').

    def solve_6_1():
      total_mass = 0.0
      extracted_martianeum = 0.0
      
      # Pomijamy pierwszy wiersz, bo zawiera nagłówki
      with open('martianeum.txt', 'r') as file:
          next(file) 
          
          for line in file:
              parts = line.strip().split('\t')
              if len(parts) >= 4:
                  # Zamiana polskich przecinków na kropki
                  mass_str = parts[2].replace(',', '.')
                  percent_str = parts[3].replace(',', '.')
                  
                  mass = float(mass_str)
                  percent = float(percent_str)
                  
                  # Dodajemy do całkowitej masy dronów
                  total_mass += mass
                  
                  # Dodajemy wydobyty minerał, tylko gdy zawartość >= 1%
                  if percent >= 1.0:
                      extracted_martianeum += mass * (percent / 100.0)
                      
      # Zaokrąglamy wyniki dla czytelności i uniknięcia błędów float
      print(f"6.1. Łączna masa ładunków: {round(total_mass, 2)} kg")
      print(f"6.1. Wydobyte martianeum: {round(extracted_martianeum, 4)} kg")
    
    solve_6_1()

Matura Rozszerzona Informatyka Maj 2025

1 pkt
Zadanie 6.2.

Podpunkt 6.2. (0–1 pkt)

Podaj nazwę obszaru, dla którego średnia masa przywiezionych ładunków jest najmniejsza.

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Rozwiązanie w arkuszu kalkulacyjnym (Excel)

    To klasyczne zadanie na agregację danych, do którego idealnie nadaje się Tabela przestawna (Pivot Table).

    1. Zaznacz całą tabelę z danymi z pliku martianeum.txt.
    2. Przejdź do zakładki Wstawianie i wybierz Tabela przestawna.
    3. W polu roboczym tabeli przestawnej przeciągnij nazwa_obszaru do okienka Wiersze.
    4. Przeciągnij pole masa [kg] do okienka Wartości.
    5. Domyślnie Excel zsumuje masy. Kliknij na to pole w okienku wartości, wybierz Ustawienia pola wartości i zmień operację z "Suma" na Średnia.
    6. Kliknij prawym przyciskiem myszy na dowolną wyliczoną średnią w tabeli, wybierz Sortuj \rightarrow Sortuj od najmniejszych do największych.

    Odpowiedzią będzie pierwszy obszar od góry (ten z najmniejszą wartością).

  • 2

    Krok 2: Rozwiązanie w języku Python

    Używając Pythona, musimy zliczać łączną masę i liczbę kursów dla każdego obszaru z użyciem słowników (dictionary), a następnie wyliczyć średnią.

    def solve_6_2():
      area_mass = {}
      area_count = {}
      
      with open('martianeum.txt', 'r') as file:
          next(file) # Pominięcie nagłówka
          for line in file:
              parts = line.strip().split('\t')
              if len(parts) >= 4:
                  area = parts[1]
                  mass = float(parts[2].replace(',', '.'))
                  
                  # Agregacja danych
                  area_mass[area] = area_mass.get(area, 0) + mass
                  area_count[area] = area_count.get(area, 0) + 1
                  
      # Szukanie minimum
      min_avg = float('inf')
      min_area = ""
      
      for area in area_mass:
          avg = area_mass[area] / area_count[area]
          if avg < min_avg:
              min_avg = avg
              min_area = area
              
      print(f"6.2. Obszar z najmniejszą średnią masą: {min_area}")
    
    solve_6_2()

Matura Rozszerzona Informatyka Maj 2025

2 pkt
Zadanie 6.3.

Podpunkt 6.3. (0–2 pkt)

Czas pracy stacji dzielimy na kolejne 7-dniowe okresy. Pierwszy okres obejmuje dni od 03.03.2033 do 09.03.2033, drugi – od 10.03.2033 do 16.03.2033 itd.

Podaj największą łączną masę ładunków przywiezionych w ciągu kolejnych 7-dniowych okresów oraz podaj datę początku okresu, w którym przywieziono tę największą masę.

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Strategia grupowania w Excelu

    Z treści głównej wiemy, że "dron codziennie przywozi ładunek". Oznacza to, że każdy wiersz w pliku odpowiada dokładnie jednemu dniowi. Mamy zatem ciągły zbiór dat. Aby pogrupować je w bloki 7-dniowe, stworzymy kolumnę pomocniczą wyliczającą datę początku okresu dla każdego rekordu.

    Użyjemy do tego matematycznej operacji reszty z dzielenia (modulo). Odległość w dniach między dowolną datą a datą startową (2033-03-03) dzielona przez 7 daje nam numer dnia w danym tygodniu (od 0 do 6).

  • 2

    Krok 2: Formuły i Tabela Przestawna

    1. Utwórz nową kolumnę obok danych (np. kolumnę E) i nazwij ją Początek_okresu.
    2. Wpisz poniższą formułę w komórkę E2:


      =A2 - RESZTA(A2 - DATA(2033;3;3); 7)

      Jak to działa? Odejmujemy datę bieżącą (A2) od daty startowej. RESZTA(różnica; 7) mówi nam, ile dni minęło od początku bieżącego 7-dniowego bloku. Odejmując tę resztę od daty w A2, "cofamy się" dokładnie do pierwszego dnia tego konkretnego 7-dniowego okresu.

    3. Przeciągnij formułę do końca tabeli. Koniecznie upewnij się, że format nowej kolumny to "Data krótkie".
    4. Wstaw Tabelę przestawną. W Wierszach umieść nowe pole Początek_okresu, a w okienku Wartości pole masa [kg] (z operacją Suma).
    5. Posortuj wyliczone sumy od największej do najmniejszej – na samej górze znajdziesz szukaną datę początku okresu oraz maksymalną masę.
  • 3

    Krok 3: Rozwiązanie w języku Python

    Wiedząc, że zapisy są w 100% ciągłe (1 dzień = 1 wiersz), możemy po prostu ciąć listę wierszy na paczki po 7 elementów (tzw. chunks). Taki algorytm jest ekstremalnie krótki i odporny na zawiłości kalendarza (lata przestępne, długości miesięcy).

    def solve_6_3():
      with open('martianeum.txt', 'r') as file:
          next(file) # Pomijamy nagłówki
          # Wczytujemy wszystkie linie do listy
          lines = [line.strip().split('\t') for line in file if line.strip()]
          
      max_sum = 0.0
      best_start_date = ""
      
      # Skaczemy co 7 wierszy
      for i in range(0, len(lines), 7):
          # Pobieramy 7-elementowy blok wierszy
          chunk = lines[i:i+7]
          
          # Sumujemy masę z kolumny o indeksie 2 dla całego bloku
          current_sum = sum(float(row[2].replace(',', '.')) for row in chunk)
          
          if current_sum > max_sum:
              max_sum = current_sum
              # Datą początku bloku jest data z jego pierwszego wiersza
              best_start_date = chunk[0][0] 
              
      print(f"6.3. Największa łączna masa: {round(max_sum, 2)} kg")
      print(f"6.3. Data początku okresu:   {best_start_date}")
    
    solve_6_3()

Matura Rozszerzona Informatyka Maj 2025

3 pkt
Zadanie 6.4.

Podpunkt 6.4. (0–3 pkt)

Wykonaj zestawienie, w którym dla każdego obszaru podasz, ile razy dron przewoził ładunek z tego obszaru w poszczególnych latach.

Na podstawie wykonanego zestawienia utwórz wykres skumulowany kolumnowy. Pamiętaj o czytelnym opisie wykresu: na osi X umieść nazwy obszarów, dodaj opisy osi – „nazwy obszarów” dla osi X i „liczba przewozów ładunku” dla osi Y, tytuł oraz legendę zawierającą kolejne lata.

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Przygotowanie danych (wyciągnięcie roku)

    Aby pogrupować dane po latach, musimy wyodrębnić rok z pełnej daty.

    1. Obok głównej tabeli stwórz nową kolumnę i nazwij ją np. Rok.
    2. W drugim wierszu wpisz formułę: =ROK(A2) (zakładając, że daty są w kolumnie A).
    3. Skopiuj formułę do samego dołu tabeli.
  • 2

    Krok 2: Tabela Przestawna

    Użyjemy tabeli przestawnej, aby szybko zliczyć kursy z podziałem na obszary i lata.

    1. Zaznacz całą tabelę (łącznie z nową kolumną Rok) i wstaw Tabelę przestawną.
    2. Przeciągnij pole nazwa_obszaru do okienka Wiersze (to będzie nasza oś X).
    3. Przeciągnij pole Rok do okienka Kolumny (to będzie nasza legenda).
    4. Przeciągnij dowolne pole tekstowe (np. nazwa_obszaru) do okienka Wartości. Excel automatycznie użyje operacji Licznik (Zlicz), co da nam ilość przewozów.
  • 3

    Krok 3: Wykres Skumulowany Kolumnowy

    Mając gotowe zestawienie w tabeli przestawnej, jednym kliknięciem wygenerujemy wykres.

    1. Kliknij w dowolne miejsce wewnątrz tabeli przestawnej.
    2. Z górnego menu wybierz Wstawianie, następnie przejdź do sekcji wykresów kolumnowych i wybierz Skumulowany kolumnowy (drugi od lewej w grupie 2D, to ten, w którym słupki nakładają się na siebie tworząc jedną wieżę).
    3. Formatowanie: Skorzystaj z plusa obok wykresu (lub zakładki Projekt), aby dodać Tytuł osi. Poziomą oś nazwij "nazwy obszarów", a pionową "liczba przewozów ładunku". Dodaj również ogólny Tytuł wykresu (np. "Przewozy ładunków w latach 2033-2038"). Upewnij się, że z boku lub na dole widoczna jest legenda z latami.

Matura Rozszerzona Informatyka Maj 2025

3 pkt
Zadanie 6.5.

Podpunkt 6.5. (0–3 pkt)

Uwzględnij zasady działania stacji opisane na początku zadania i podaj:

  • ile razy stacja wysyłała ładunek na orbitę
  • datę pierwszego transportu ładunku na orbitę
  • datę ostatniego transportu ładunku na orbitę.
💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Zrozumienie mechanizmu (symulacja krok po kroku)

    Musimy śledzić stan "magazynu" na stacji dzień po dniu.

    • Codziennie do magazynu trafia to, co wydobyto (obliczyliśmy to już w zadaniu 6.1).
    • Na koniec dnia sprawdzamy: czy w magazynie jest 100\ge 100 kg?
    • Jeśli tak, to odejmujemy 100 kg (wysyłka) i notujemy ten fakt. Reszta przechodzi na kolejny dzień.
    • Jeśli nie, cała zawartość po prostu przechodzi na kolejny dzień.
  • 2

    Krok 2: Rozwiązanie w Arkuszu Kalkulacyjnym

    Najlepiej stworzyć trzy nowe kolumny pomocnicze, które przeprowadzą tę symulację. Załóżmy, że w kolumnie E mamy dzienne wydobycie (z zadania 6.1).

    1. Kolumna F: Stan przed wysyłką.
      W pierwszym wierszu (F2) wpisz po prostu: =E2.
      W następnym (F3) wpisz: =G2 + E3 (czyli to, co zostało wczoraj + dzisiejsze wydobycie). Przeciągnij F3 w dół.
    2. Kolumna G: Stan po wysyłce (na jutro).
      Jeśli mamy 100 kg lub więcej, wysyłamy 100 kg. Wpisz w G2:
      =JEŻELI(F2>=100; F2-100; F2) i przeciągnij w dół.
    3. Kolumna H: Czy był transport?.
      Wpisz w H2: =JEŻELI(F2>=100; 1; 0) i przeciągnij w dół.

    Aby odpowiedzieć na pytania z zadania:

    • Ile razy? Zsumuj kolumnę H: =SUMA(H2:H10000).
    • Daty: Załóż na całą tabelę filtry. W kolumnie H wyfiltruj tylko "1". Pierwszy wiersz pokaże datę pierwszego transportu, a ostatni wiersz – datę ostatniego.
  • 3

    Krok 3: Rozwiązanie w języku Python

    Napisanie prostej symulacji w pętli jest w tym przypadku bardzo naturalne i szybkie.

    def solve_6_5():
      storage = 0.0
      shipment_count = 0
      shipment_dates = []
      
      with open('martianeum.txt', 'r') as file:
          next(file) # Pomijamy nagłówki
          for line in file:
              parts = line.strip().split('\t')
              if len(parts) >= 4:
                  date = parts[0]
                  mass = float(parts[2].replace(',', '.'))
                  percent = float(parts[3].replace(',', '.'))
                  
                  # Dodajemy do magazynu, jeśli zawartość >= 1%
                  if percent >= 1.0:
                      storage += mass * (percent / 100.0)
                      
                  # Koniec dnia: sprawdzamy czy możemy wysłać
                  if storage >= 100.0:
                      storage -= 100.0
                      shipment_count += 1
                      shipment_dates.append(date)
                      
      print(f"6.5. Liczba wysłanych ładunków: {shipment_count}")
      if shipment_count > 0:
          print(f"6.5. Data pierwszego transportu: {shipment_dates[0]}")
          print(f"6.5. Data ostatniego transportu: {shipment_dates[-1]}")
    
    solve_6_5()

Matura Rozszerzona Informatyka Maj 2025

2 pkt
Zadanie 7.

Poszukiwanie wody na Marsie

W trzech plikach tekstowych o nazwach laziki.txt, obszary.txt, pomiary.txt zapisano informacje zawierające dane o poszukiwaniu wody na Marsie w latach 2050–2080. Łaziki zasilane energią słoneczną poruszają się po różnych obszarach Marsa i wykonują pomiary georadarowe, na podstawie których szacują ilość wody i głębokość, na której się ona znajduje. Pierwszy wiersz każdego z plików jest wierszem nagłówkowym, a dane w wierszach rozdzielono znakami tabulacji.

Struktura plików:

Plik laziki.txt (informacje o łazikach):

  • nr_lazika – co najwyżej trzycyfrowy, unikatowy numer łazika
  • nazwa_lazika – nazwa łazika (tekst do 50 znaków)
  • rok_wyslania – rok startu z Ziemi
  • wsp_ladowania – współrzędne lądowania na Marsie oddzielone znakiem przecinka i spacją

Plik obszary.txt (informacje o obszarach na Marsie):

  • kod_obszaru – pięcioznakowy, unikatowy kod obszaru
  • nazwa_obszaru – nazwa obszaru (tekst do 50 znaków)

Plik pomiary.txt (wyniki badań georadarowych):

  • nr_lazika – co najwyżej trzycyfrowy numer łazika
  • data_pomiaru – data wykonania pomiaru (w formacie rrrr-mm-dd)
  • kod_obszaru – pięcioznakowy kod obszaru, na którym został wykonany pomiar
  • wspolrzedne – współrzędne wykonania pomiaru, oddzielone znakiem przecinka i spacją
  • glebokosc – szacowana głębokość, na której znajduje się woda (w metrach)
  • ilosc – szacowana ilość wody (w m³)

Podpunkt 7.1. (0–2 pkt)

Podaj nazwę obszaru, na którym znaleziono łącznie we wszystkich pomiarach najwięcej m³ wody na głębokości do 100 metrów włącznie. Jest jeden taki obszar.

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Relacyjna Baza Danych (MS Access)

    To zadanie idealnie nadaje się do rozwiązania w programie MS Access poprzez utworzenie prostej relacyjnej bazy danych.

    1. Zaimportuj wszystkie trzy pliki tekstowe do programu Access jako nowe tabele. Pamiętaj o zaznaczeniu opcji "Pierwszy wiersz zawiera nazwy pól".
    2. Przejdź do zakładki Narzędzia bazy danych i otwórz Relacje.
    3. Połącz tabele odpowiednimi kluczami obcymi:

      • Pole nr_lazika z tabeli laziki połącz z polem nr_lazika w tabeli pomiary.
      • Pole kod_obszaru z tabeli obszary połącz z polem kod_obszaru w tabeli pomiary.
  • 2

    Krok 2: Konstrukcja kwerendy

    Przejdź do zakładki Tworzenie i wybierz Projekt kwerendy. Dodaj do widoku tabele pomiary oraz obszary.

    • Ograniczenie do 100 metrów: Dodaj pole glebokosc z tabeli pomiary. Odznacz je (nie musi być widoczne w wyniku), a w wierszu Kryteria wpisz <=100.

    • Nazwa obszaru: Dodaj pole nazwa_obszaru z tabeli obszary. To po tym polu będziemy grupować wyniki.

    • Sumowanie ilości wody: Dodaj pole ilosc z tabeli pomiary. Włącz opcję Sumy w górnym menu (ikona Sigmy Σ\Sigma). W wierszu Suma pod polem ilosc zmień "Grupuj według" na Suma. Sortuj to pole Malejąco.

    Po uruchomieniu kwerendy, pierwszy wiersz wyświetli nazwę obszaru, który spełnił wszystkie warunki zadania.

  • 3

    Krok 3: Alternatywa - Język SQL

    Jeśli wolisz widok SQL, zapytanie generujące prawidłowy wynik wygląda następująco:

    SELECT TOP 1 obszary.nazwa_obszaru, SUM(pomiary.ilosc) AS SumaWody
    FROM obszary INNER JOIN pomiary 
    ON obszary.kod_obszaru = pomiary.kod_obszaru
    WHERE pomiary.glebokosc <= 100
    GROUP BY obszary.nazwa_obszaru
    ORDER BY SUM(pomiary.ilosc) DESC;
  • 4

    Krok 4: Alternatywa - Język Python

    Możesz też rozwiązać to zadanie w języku Python. Kluczem jest stworzenie słownika mapującego kod_obszaru na jego nazwę, a następnie agregacja danych z uwzględnieniem warunku głębokości.

    def solve_7_1():
      # 1. Wczytanie mapowania kod -> nazwa obszaru
      obszary_map = {}
      with open('obszary.txt', 'r') as f:
          next(f) # Pominięcie nagłówka
          for line in f:
              parts = line.strip().split('\t')
              if len(parts) >= 2:
                  obszary_map[parts[0]] = parts[1]
    
      # 2. Agregacja ilości wody na obszarach (głębokość <= 100)
      woda_na_obszarach = {}
      with open('pomiary.txt', 'r') as f:
          next(f)
          for line in f:
              parts = line.strip().split('\t')
              if len(parts) >= 6:
                  kod_obszaru = parts[2]
                  glebokosc = int(parts[4])
                  ilosc = int(parts[5])
                  
                  # Warunek z zadania
                  if glebokosc <= 100:
                      nazwa = obszary_map.get(kod_obszaru, "Nieznany")
                      woda_na_obszarach[nazwa] = woda_na_obszarach.get(nazwa, 0) + ilosc
    
      # 3. Znalezienie obszaru z maksymalną ilością wody
      najlepszy_obszar = max(woda_na_obszarach, key=woda_na_obszarach.get)
      max_wody = woda_na_obszarach[najlepszy_obszar]
      
      print(f"7.1. Obszar: {najlepszy_obszar} (łącznie {max_wody} m3 wody)")
    
    solve_7_1()

Matura Rozszerzona Informatyka Maj 2025

2 pkt
Zadanie 7.2.

Podaj nazwę łazika, który wykonywał pomiary w najdłuższym okresie, licząc od pierwszego (najwcześniejszego) do ostatniego (najpóźniejszego) pomiaru. Podaj datę pierwszego i ostatniego pomiaru wykonanego przez ten łazik.

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Konstrukcja kwerendy w MS Access

    Musimy pogrupować dane po nazwie łazika, znaleźć skrajne daty jego aktywności, a następnie policzyć różnicę (w dniach) między nimi, by ustalić najdłuższy okres.

    1. Przejdź do Projektu kwerendy i dodaj tabele laziki oraz pomiary.
    2. Dodaj pole nazwa_lazika z tabeli laziki.
    3. Dodaj pole data_pomiaru z tabeli pomiary dwukrotnie.
    4. Włącz opcję Sumy (ikona Σ\Sigma).
    5. Dla pierwszego pola data_pomiaru ustaw podsumowanie na Minimum (to data pierwszego pomiaru).
    6. Dla drugiego pola data_pomiaru ustaw podsumowanie na Maksimum (to data ostatniego pomiaru).
    7. W czwartej, pustej kolumnie stwórz własne pole obliczeniowe wpisując:
      Czas_trwania: Max([data_pomiaru]) - Min([data_pomiaru]).
    8. Dla tego pola ustaw sortowanie na Malejące. Pierwszy wiersz wyniku to szukany łazik oraz jego skrajne daty.
  • 2

    Krok 2: Alternatywa - Język SQL

    Kod SQL wykonujący dokładnie tę samą operację:

    SELECT TOP 1 laziki.nazwa_lazika, Min(pomiary.data_pomiaru) AS Pierwszy_pomiar, Max(pomiary.data_pomiaru) AS Ostatni_pomiar
    FROM laziki INNER JOIN pomiary ON laziki.nr_lazika = pomiary.nr_lazika
    GROUP BY laziki.nazwa_lazika
    ORDER BY Max(pomiary.data_pomiaru) - Min(pomiary.data_pomiaru) DESC;
  • 3

    Krok 3: Alternatywa - Język Python

    Aby wyliczyć różnicę czasu w Pythonie, skorzystamy z modułu datetime do przekonwertowania tekstu na faktyczne daty.

    from datetime import datetime
    
    def solve_7_2():
      # 1. Mapowanie numeru łazika na jego nazwę
      laziki_map = {}
      with open('laziki.txt', 'r') as f:
          next(f)
          for line in f:
              parts = line.strip().split('\t')
              if len(parts) >= 2:
                  laziki_map[parts[0]] = parts[1]
    
      # 2. Gromadzenie dat pomiarów dla każdego łazika
      daty_pomiarow = {}
      with open('pomiary.txt', 'r') as f:
          next(f)
          for line in f:
              parts = line.strip().split('\t')
              if len(parts) >= 2:
                  nr_lazika = parts[0]
                  data_str = parts[1]
                  data_obj = datetime.strptime(data_str, "%Y-%m-%d")
                  
                  if nr_lazika not in daty_pomiarow:
                      daty_pomiarow[nr_lazika] = []
                  daty_pomiarow[nr_lazika].append(data_obj)
    
      # 3. Szukanie najdłuższego okresu
      max_roznica = -1
      najlepszy_lazik_nr = ""
      min_data_wynik = None
      max_data_wynik = None
    
      for nr_lazika, daty in daty_pomiarow.items():
          min_data = min(daty)
          max_data = max(daty)
          roznica = (max_data - min_data).days
          
          if roznica > max_roznica:
              max_roznica = roznica
              najlepszy_lazik_nr = nr_lazika
              min_data_wynik = min_data
              max_data_wynik = max_data
    
      nazwa = laziki_map.get(najlepszy_lazik_nr, "Nieznany")
      
      print(f"7.2. Łazik: {nazwa}")
      print(f"7.2. Pierwszy pomiar: {min_data_wynik.strftime('%Y-%m-%d')}")
      print(f"7.2. Ostatni pomiar: {max_data_wynik.strftime('%Y-%m-%d')}")
    
    solve_7_2()

Matura Rozszerzona Informatyka Maj 2025

2 pkt
Zadanie 7.3.

Podaj nazwy obszarów na Marsie, na których żaden z łazików nie wykonał ani jednego pomiaru w tym samym roku, w którym został wysłany z Ziemi.

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Logika bazy danych (Zapytanie wykluczające)

    Aby znaleźć obszary, które nie spełniają jakiegoś warunku, najprościej jest najpierw znaleźć te, które go spełniają, a następnie wybrać wszystkie pozostałe.

    1. Kwerenda 1 (Wykluczająca): Tworzymy kwerendę z tabel laziki oraz pomiary. Wyciągamy z niej pole kod_obszaru. Dodajemy warunek porównujący rok z daty pomiaru z rokiem wysłania: Rok([data_pomiaru]) = [rok_wyslania]. Zapisujemy tę kwerendę jako np. "Obszary_Wykluczone".

    2. Kwerenda 2 (Główna): Wykorzystujemy Kreatora kwerend wyszukujących niepasujące dane (lub tworzymy złączenie typu LEFT JOIN). Łączymy tabelę obszary z naszą kwerendą "Obszary_Wykluczone". Wybieramy obszary z tabeli głównej, dla których połączone pole w kwerendzie wykluczającej Is Null (czyli jest puste).

  • 2

    Krok 2: Alternatywa - Język SQL

    W czystym SQL możemy zastosować bardzo elegancką klauzulę NOT IN (nie znajduje się w).

    SELECT nazwa_obszaru
    FROM obszary
    WHERE kod_obszaru NOT IN (
      SELECT pomiary.kod_obszaru 
      FROM pomiary INNER JOIN laziki ON pomiary.nr_lazika = laziki.nr_lazika 
      WHERE Year(pomiary.data_pomiaru) = laziki.rok_wyslania
    );
  • 3

    Krok 3: Alternatywa - Język Python

    W Pythonie zrealizujemy tę logikę przy użyciu tzw. zbiorów (set), co pozwoli nam na łatwe sprawdzanie przynależności do wykluczonej grupy.

    def solve_7_3():
      # 1. Pobranie roku wysłania dla każdego łazika
      rok_wyslania_map = {}
      with open('laziki.txt', 'r') as f:
          next(f)
          for line in f:
              parts = line.strip().split('\t')
              if len(parts) >= 3:
                  rok_wyslania_map[parts[0]] = parts[2] # jako string, np. "2050"
    
      # 2. Zbudowanie zbioru obszarów "wykluczonych"
      obszary_wykluczone = set()
      with open('pomiary.txt', 'r') as f:
          next(f)
          for line in f:
              parts = line.strip().split('\t')
              if len(parts) >= 3:
                  nr_lazika = parts[0]
                  rok_pomiaru = parts[1][:4] # wycięcie pierwszych 4 znaków (YYYY)
                  kod_obszaru = parts[2]
                  
                  # Jeśli rok pomiaru jest równy rokowi wysłania z Ziemi
                  if rok_pomiaru == rok_wyslania_map.get(nr_lazika):
                      obszary_wykluczone.add(kod_obszaru)
    
      # 3. Wypisanie nazw obszarów, których nie ma w zbiorze wykluczonych
      print("7.3. Obszary spełniające warunek:")
      with open('obszary.txt', 'r') as f:
          next(f)
          for line in f:
              parts = line.strip().split('\t')
              if len(parts) >= 2:
                  kod_obszaru = parts[0]
                  nazwa_obszaru = parts[1]
                  
                  if kod_obszaru not in obszary_wykluczone:
                      print(f"- {nazwa_obszaru}")
    
    solve_7_3()

Matura Rozszerzona Informatyka Maj 2025

2 pkt
Zadanie 7.4.

Podaj nazwy łazików, które wylądowały na półkuli południowej, ale wykonywały pomiary na obu półkulach: północnej (N) i południowej (S).

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Identyfikacja półkuli na podstawie współrzędnych

    Współrzędne w plikach zapisane są w formacie np. 44.90S, 130.80W. Pierwszy człon to szerokość geograficzna, a jej ostatnia litera (N lub S) definiuje półkulę.

    W MS Access (oraz w SQL) możemy filtrować te dane za pomocą operatora LIKE (lub Podobne do w polskim GUI) z użyciem znaków wieloznacznych (gwiazdka *):

    • Półkula południowa: LIKE "*S, *" (kończy się na S przed przecinkiem)
    • Półkula północna: LIKE "*N, *" (kończy się na N przed przecinkiem)
  • 2

    Krok 2: Konstrukcja w MS Access (widok projektowy)

    Ze względu na to, że łazik musiał wykonać przynajmniej jeden pomiar na północy i przynajmniej jeden na południu, najbezpieczniej rozbić to na podkwerendy:

    1. Kwerenda Północ: Wyciągnij z tabeli pomiary pole nr_lazika z kryterium dla współrzędnych LIKE "*N, *". Zgrupuj wyniki, aby uniknąć duplikatów.
    2. Kwerenda Południe: Zrób to samo, ale z kryterium LIKE "*S, *".
    3. Kwerenda Główna: Dodaj tabelę laziki, Kwerendę Północ oraz Kwerendę Południe. Połącz je wszystkie relacjami poprzez pole nr_lazika (INNER JOIN). Dla pola wsp_ladowania z tabeli laziki ustaw kryterium LIKE "*S, *". Wyświetl pole nazwa_lazika.
  • 3

    Krok 3: Rozwiązanie w czystym SQL

    W SQL możemy uzyskać ten sam efekt poprzez wielokrotne dołączenie tabeli pomiary (tzw. self-join) i dodanie słowa kluczowego DISTINCT, które zadba o brak powtórzeń w nazwach łazików.

    SELECT DISTINCT laziki.nazwa_lazika
    FROM (laziki 
    INNER JOIN pomiary AS p1 ON laziki.nr_lazika = p1.nr_lazika)
    INNER JOIN pomiary AS p2 ON laziki.nr_lazika = p2.nr_lazika
    WHERE laziki.wsp_ladowania LIKE '*S,*'
    AND p1.wspolrzedne LIKE '*N,*'
    AND p2.wspolrzedne LIKE '*S,*';
  • 4

    Krok 4: Alternatywa - Język Python

    def solve_7_4():
      # 1. Odczytanie łazików, które wylądowały na południu (S)
      laziki_S = {}
      with open('laziki.txt', 'r') as f:
          next(f)
          for line in f:
              parts = line.strip().split('\t')
              if len(parts) >= 4:
                  nr_lazika = parts[0]
                  nazwa = parts[1]
                  wsp_ladowania = parts[3]
                  
                  # Sprawdzenie czy przed przecinkiem jest litera S
                  if 'S,' in wsp_ladowania:
                      laziki_S[nr_lazika] = nazwa
    
      # 2. Rejestrowanie półkul, na których dany łazik robił pomiary
      pomiary_N = set()
      pomiary_S = set()
      
      with open('pomiary.txt', 'r') as f:
          next(f)
          for line in f:
              parts = line.strip().split('\t')
              if len(parts) >= 4:
                  nr_lazika = parts[0]
                  wspolrzedne = parts[3]
                  
                  if 'N,' in wspolrzedne:
                      pomiary_N.add(nr_lazika)
                  if 'S,' in wspolrzedne:
                      pomiary_S.add(nr_lazika)
    
      # 3. Wypisanie wyniku: przecięcie wszystkich trzech zbiorów warunków
      print("7.4. Łaziki spełniające warunki:")
      for nr, nazwa in laziki_S.items():
          if nr in pomiary_N and nr in pomiary_S:
              print(f"- {nazwa}")
    
    solve_7_4()

Matura Rozszerzona Informatyka Maj 2025

2 pkt
Zadanie 7.5.

Do tabel utworzonych na podstawie opisanych wcześniej plików dołączamy kolejną – o nazwie Producent, w której zapisano informacje o producentach poszczególnych modeli łazików.

Tabela Producent zawiera następujące pola:
  • kod_producenta – unikatowy kod producenta
  • nazwa – nazwa producenta
  • kraj – kraj producenta

Do tabeli Laziki dodano pole kod_producenta.

Napisz w języku SQL zapytanie, w wyniku którego otrzymasz listę nazw producentów, których łaziki badały obszar Marsa o nazwie Arcadia w roku 2060. Nazwy producentów nie mogą się powtarzać.

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Architektura zapytania (Złączenia / JOIN)

    Zadanie polega na połączeniu (INNER JOIN) aż 4 tabel w jeden logiczny łańcuch. Droga od informacji o producencie do nazwy badanego obszaru wygląda następująco:

    1. Producent łączy się z tabelą Laziki kluczem kod_producenta.
    2. Laziki łączą się z tabelą Pomiary kluczem nr_lazika.
    3. Pomiary łączą się z tabelą Obszary kluczem kod_obszaru.
  • 2

    Krok 2: Warunki i unikalność

    • Unikalność: W poleceniu podkreślono, że nazwy producentów nie mogą się powtarzać. To wymusza użycie słowa kluczowego DISTINCT tuż po instrukcji SELECT.

    • Rok 2060: Ekstrakcję roku z pola zawierającego pełną datę najlepiej zrealizować standardową funkcją YEAR(nazwa_pola). Alternatywnie poprawny jest również zapis z ucięciem daty: LIKE '2060-*'.

    • Nazwa obszaru: Warunek tekstowy = 'Arcadia' w klauzuli WHERE.

  • 3

    Krok 3: Gotowy kod SQL

    Poniżej znajduje się kompletne zapytanie SQL, zgodne ze standardem używanym na maturze (oraz w programie MS Access). W Accessie wielokrotne złączenia często wymagają nawiasów, co widać w bloku FROM.

    SELECT DISTINCT Producent.nazwa
    FROM ((Producent
    INNER JOIN laziki ON Producent.kod_producenta = laziki.kod_producenta)
    INNER JOIN pomiary ON laziki.nr_lazika = pomiary.nr_lazika)
    INNER JOIN obszary ON pomiary.kod_obszaru = obszary.kod_obszaru
    WHERE obszary.nazwa_obszaru = 'Arcadia'
    AND YEAR(pomiary.data_pomiaru) = 2060;

Problemy z algorytmem lub Excelem?

Arkusz to nie wszystko. Systematyzuj swoją wiedzę rozwiązując zadania i czytając opracowania maturalne z naszej bazy wiedzy.

Pytania o arkusz z Informatyki

Ile trwa Matura z Informatyki?

Egzamin maturalny z informatyki na poziomie rozszerzonym trwa 210 minut i odbywa się w całości przy stanowisku komputerowym.

Gdzie znaleźć kody źródłowe i rozwiązania do arkusza Matura Rozszerzona Informatyka 2025 Maj?

Pełne rozwiązania krok po kroku (w tym kody źródłowe w Python/C++, kwerendy SQL i formuły Excel) znajdują się na tej stronie powyżej. Każde zadanie jest szczegółowo omówione.

Czy mogę pobrać pliki (Dane.zip) i ten arkusz w formacie PDF?

Tak, linki do oficjalnego arkusza CKE w formacie PDF oraz paczki z plikami tekstowymi najczęściej znajdują się na górze tej strony.

ProKorepetycje © 2026

Wszystkie arkusze CKE