Maj 2023

Matura Rozszerzona Informatyka 2023 Maj
Rozwiązania krok po kroku

Arkusz maturalny z informatyki (poziom rozszerzony) to kompleksowy sprawdzian umiejętności technicznych. Wymaga od maturzysty sprawnego poruszania się w świecie algorytmiki i programowania (m.in. rekurencja, operacje na tablicach i tekstach), a także znajomości budowy komputerów i zasad cyberbezpieczeństwa. Istotną częścią egzaminu jest również praktyczna praca z danymi – ich przetwarzanie w arkuszach kalkulacyjnych oraz zarządzanie nimi za pomocą baz danych i zapytań SQL.

Czas: 210 min
📄 Pobierz Arkusz PDF

Matura Rozszerzona Informatyka Maj 2023

2 pkt
Zadanie 1.

Zadanie 1. Biblioteczka Adama

Adam przechowuje swoje książki w biblioteczce zbudowanej z półek ponumerowanych kolejno 0, 1, 2, ... (zaczynając od półki położonej najwyżej). Półka o numerze ii ma 2i2^i przegródek, w których umieszczane są książki. W jednej przegródce można umieścić tylko jedną książkę. Przegródki na ii-tej półce są ponumerowane od lewej do prawej kolejnymi liczbami 1, 2, 3, ..., 2i2^i.

Jako B[i,j]B[i, j] oznaczamy jj-tą przegródkę na ii-tej półce.

Każda książka ma swój numer identyfikacyjny. Adam ustawia książki na półkach, zawsze zaczynając od przegródki B[0,1]B[0,1]. Stosuje przy tym następującą, rekurencyjną regułę:

Adam sprawdza, czy przegródka B[i,j]B[i, j] (i0i \ge 0 oraz 1j2i1 \le j \le 2^i) jest pusta. Jeśli tak, umieszcza książkę w tej przegródce. W przeciwnym przypadku porównuje numer wstawianej książki z numerem książki w przegródce. Jeśli numer wstawianej książki jest mniejszy od numeru książki stojącej w przegródce, próbuje umieścić książkę na kolejnej półce w przegródce B[i+1,2j1]B[i + 1, 2j - 1]. Jeśli numer wstawianej książki jest większy od numeru książki w przegródce, to próbuje umieścić książkę w przegródce B[i+1,2j]B[i + 1, 2j].

Przykład 1.
Szara komórka to przegródka B[3,4]B[3, 4]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
0
1
2
3
4
Biblioteczka Adama
Przykład 2.

Poniżej przedstawiono zawartość biblioteczki po wstawieniu do niej książek kolejno o numerach: 10, 2, 15, 13, 1, 5, 25 (zakładamy, że przedtem biblioteczka była pusta).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
0
10
1
2
15
2
1
5
13
25
3
4
Przykład 3.

Poniżej przedstawiono zawartość biblioteczki po wstawieniu do niej książek kolejno o numerach: 1, 5, 10, 15, 2, 25, 13 (zakładamy, że przedtem biblioteczka była pusta).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
0
1
1
5
2
2
10
3
15
4
13
25

Zadanie 1.1. (0–2 pkt)

Podaj zawartość biblioteczki po wstawieniu do niej kolejno książek o numerach: 14, 18, 12, 9, 20, 15, 17.

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Zrozumienie struktury (Drzewo BST)

    Zanim zaczniemy wstawiać liczby, warto zauważyć, co dokładnie opisuje algorytm w zadaniu. Jest to klasyczna implementacja Drzewa Poszukiwań Binarnych (BST - Binary Search Tree) przy użyciu tablicy (lub w tym przypadku wizualnych półek).

    • Przegródka B[0,1]B[0, 1] to korzeń drzewa (ang. root).
    • Przejście do B[i+1,2j1]B[i + 1, 2j - 1] w przypadku mniejszej wartości to przejście do lewego syna.
    • Przejście do B[i+1,2j]B[i + 1, 2j] w przypadku większej wartości to przejście do prawego syna.
  • 2

    Krok 2: Symulacja wstawiania książek krok po kroku

    Mamy ciąg: 14, 18, 12, 9, 20, 15, 17. Wstawiamy je po kolei:

    • 14: Półka jest pusta. Wstawiamy do korzenia \rightarrow B[0,1]=14B[0, 1] = 14.

    • 18: Porównujemy z 14. Jest większe, więc idziemy do prawego dziecka: i+1=1i+1=1, 2j=22j=2 \rightarrow B[1,2]=18B[1, 2] = 18.

    • 12: Porównujemy z 14. Mniejsze, idziemy do lewego dziecka: i+1=1i+1=1, 2j1=12j-1=1 \rightarrow B[1,1]=12B[1, 1] = 12.

    • 9: Mniejsze od 14 (idziemy w lewo do B[1,1]B[1, 1]). W B[1,1]B[1, 1] jest 12. 9 jest mniejsze od 12, więc idziemy do lewego dziecka: i+1=2i+1=2, 2(1)1=12(1)-1=1 \rightarrow B[2,1]=9B[2, 1] = 9.

    • 20: Większe od 14 (idziemy do B[1,2]B[1, 2]). W B[1,2]B[1, 2] jest 18. 20 jest większe od 18, więc w prawo: i+1=2i+1=2, 2(2)=42(2)=4 \rightarrow B[2,4]=20B[2, 4] = 20.

    • 15: Większe od 14 (do B[1,2]B[1, 2]). Mniejsze od 18 (w lewo): i+1=2i+1=2, 2(2)1=32(2)-1=3 \rightarrow B[2,3]=15B[2, 3] = 15.

    • 17: Większe od 14 (do B[1,2]B[1, 2]). Mniejsze od 18 (do B[2,3]B[2, 3] gdzie jest 15). Większe od 15 (w prawo z pozycji j=3j=3): i+1=3i+1=3, 2(3)=62(3)=6 \rightarrow B[3,6]=17B[3, 6] = 17.

  • 3

    Krok 3: Końcowy stan biblioteczki

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    0
    14
    1
    12
    18
    2
    9
    15
    20
    3
    17
    4

Matura Rozszerzona Informatyka Maj 2023

3 pkt
Zadanie 1.2.

Zadanie 1.2. (0–3 pkt)

Uzupełnij tabelkę – wpisz, ile minimalnie, a ile maksymalnie musi być półek w biblioteczce, żeby można było umieścić w niej nn książek i żeby na ostatniej półce znalazła się co najmniej jedna książka.

nn – liczba książekMinimalna liczba półekMaksymalna liczba półek
111
323
434
7....................
165..........
31....................
32....................
2k12^k - 1, dla k>0k > 0....................
💡 Pokaż rozwiązanie krok po kroku
  • 1

    Logika wyznaczania liczby półek

    Zadanie sprowadza się do analizy wysokości binarnego drzewa poszukiwań (BST):

    • Maksymalna liczba półek: Otrzymujemy ją w najbardziej niekorzystnym przypadku, gdy drzewo jest "liniowe" (każda książka ma tylko jednego syna). Wtedy każda kolejna książka zajmuje nową półkę. Zatem dla nn książek mamy nn półek.
    • Minimalna liczba półek: Otrzymujemy ją, gdy drzewo jest idealnie zbalansowane (każda półka jest zapełniona przed przejściem do kolejnej). Liczba miejsc na hh półkach (od 0 do h1h-1) to suma ciągu geometrycznego: 20+21+...+2h1=2h12^0 + 2^1 + ... + 2^{h-1} = 2^h - 1.

    Aby wyznaczyć minimalną liczbę półek dla nn książek, szukamy najmniejszego hh, takiego że 2h1n2^h - 1 \ge n.

  • 2

    Rozwiązanie i wypełniona tabela

    nMinMax
    737
    16516
    31531
    32632
    2k12^k - 1kk2k12^k - 1

Matura Rozszerzona Informatyka Maj 2023

2 pkt
Zadanie 1.3.

Zadanie 1.3. (0–2 pkt)

Kolega Adama, oglądający biblioteczkę, stwierdził, że aby wypisać wszystkie numery książek umieszczonych na półkach, można posłużyć się podanym poniżej rekurencyjnym algorytmem AA, którego działanie rozpoczynamy od półki o numerze 0 i od przegródki o numerze 1. Zakładamy przy tym, że w biblioteczce jest co najmniej jedna książka.

A(i, j)
wypisz numer książki z przegródki B[i,j]B[i, j]
jeżeli przegródka B[i+1,2j1]B[i + 1, 2j - 1] nie jest pusta, to
wykonaj A(i + 1, 2j - 1)
jeżeli przegródka B[i+1,2j]B[i + 1, 2j] nie jest pusta, to
wykonaj A(i + 1, 2j)

Dla biblioteczki z siedmioma książkami z przykładu 2. algorytm AA wypisze: 10, 2, 1, 5, 15, 13, 25.

Podaj ciągi liczb wypisane przez algorytm AA dla podanych zawartości biblioteczki.

a)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
0
9
1
2
12
2
10
14
3
13
15
4

Odpowiedź: ........................................................................................

b)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
0
10
1
8
15
2
4
12
3
6
13
4

Odpowiedź: ........................................................................................

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Analiza działania algorytmu A (Przechodzenie Pre-order)

    Algorytm przedstawiony w zadaniu to klasyczne przechodzenie drzewa binarnego w porządku Pre-order (VLR), czyli:
    1. Odwiedź węzeł bieżący (Visit).
    2. Przejdź do lewego poddrzewa (Left).
    3. Przejdź do prawego poddrzewa (Right).

    Zasada jest prosta: zawsze najpierw wypisujesz element, na którym stoisz, potem próbujesz iść maksymalnie w lewo, a gdy już się nie da, cofasz się i sprawdzasz prawe gałęzie.

  • 2

    Krok 1: Rozwiązanie dla podpunktu a)

    • Zaczynamy od korzenia: 9
    • Idziemy w lewo do: 2 (z niego już nie ma dróg w dół, więc się cofamy)
    • Wracamy do 9 i idziemy w prawo do: 12
    • Z 12 idziemy w lewo do: 10 (brak dalszych dróg, cofamy się do 12)
    • Z 12 idziemy w prawo do: 14
    • Z 14 idziemy w lewo do: 13 (brak dróg, cofamy się do 14)
    • Z 14 idziemy w prawo do: 15

    Odpowiedź a): 9, 2, 12, 10, 14, 13, 15

  • 3

    Krok 2: Rozwiązanie dla podpunktu b)

    • Zaczynamy od korzenia: 10
    • Idziemy w lewo do: 8
    • Z 8 w lewo do: 4
    • Z 4 w lewo się nie da, więc idziemy w prawo do: 6 (koniec lewej dużej gałęzi, cofamy się aż do korzenia)
    • Z 10 idziemy w prawo do: 15
    • Z 15 idziemy w lewo do: 12
    • Z 12 w lewo się nie da, idziemy w prawo do: 13

    Odpowiedź b): 10, 8, 4, 6, 15, 12, 13

Matura Rozszerzona Informatyka Maj 2023

3 pkt
Zadanie 2.1.

Zadanie 2. Liczby binarne

W tym zadaniu rozważamy binarny zapis liczb całkowitych dodatnich.

Blokiem w zapisie binarnym liczby nazywamy każdy niepusty, maksymalny (nie można go rozszerzyć ani z lewej, ani z prawej strony) ciąg kolejnych takich samych cyfr w tym zapisie.

Przykład:

Liczba binarna 111110000110111 składa się z pięciu bloków – trzech bloków złożonych z jedynek (11111, 11 i 111) i dwóch bloków złożonych z zer (0000 i 0).


Liczba binarna 111111111111111 składa się z jednego bloku złożonego z jedynek.

Zadanie 2.1. (0–3 pkt)

Zapisz w pseudokodzie lub w wybranym języku programowania algorytm, który dla danej dodatniej całkowitej liczby nn obliczy liczbę bloków w jej zapisie binarnym.

Przykład:
  • Dla liczby 67 wynikiem jest 3, ponieważ 67 w zapisie binarnym to 1000011 (dwa bloki jedynek i jeden blok zer).
  • Dla liczby 245 wynikiem jest 5, ponieważ 245 w zapisie binarnym to 11110101 (trzy bloki jedynek i dwa bloki zer).

Uwaga: W zapisie algorytmu możesz korzystać tylko z instrukcji sterujących, operatorów arytmetycznych: dodawania, odejmowania, mnożenia, dzielenia, dzielenia całkowitego i reszty z dzielenia; operatorów logicznych, porównań, instrukcji przypisania lub samodzielnie napisanych funkcji i procedur wykorzystujących powyższe operacje. Zabronione jest używanie funkcji wbudowanych oraz operatorów innych niż wymienione, dostępnych w językach programowania, w tym zwłaszcza funkcji zamiany między systemami pozycyjnymi i konwersji między typami danych.

Specyfikacja:
Dane:
  • nn – dodatnia liczba całkowita
Wynik:
  • bb – liczba bloków w zapisie binarnym liczby nn
Algorytm:
💡 Pokaż rozwiązanie krok po kroku
  • 1

    Analiza problemu i konstrukcja rozwiązania

    Ponieważ nie możemy używać gotowych funkcji zamieniających liczby na tekst (stringi), musimy przetwarzać liczbę nn czysto matematycznie. System binarny ma podstawę 2, więc poszczególne "cyfry" (bity) odczytujemy za pomocą reszty z dzielenia przez 2, a "odcinamy" je dzieleniem całkowitym przez 2.

    • Każda liczba dodatnia ma co najmniej jeden blok. Zaczynamy więc od liczebności bloków b=1b = 1.
    • Wyciągamy ostatni bit (tzw. najmniej znaczący) i traktujemy go jako "poprzedni bit". Będziemy go porównywać z kolejnymi odczytanymi bitami.
    • W pętli dzielimy liczbę przez 2 i odczytujemy następny bit. Jeśli różni się on od naszego "poprzedniego bitu", oznacza to zmianę cyfry (np. z 0 na 1 lub z 1 na 0) – a więc zaczął się nowy blok. Wtedy zwiększamy bb o 1.
    • Zaktualizowany bit staje się teraz "poprzednim" i pętla toczy się dalej, dopóki n>0n > 0.
  • 2

    Rozwiązanie - Pseudokod

    Oto w pełni zgodny ze specyfikacją pseudokod:

    b <- 1
    poprzedni_bit <- n mod 2
    n <- n div 2
    
    dopóki n > 0 wykonuj
      aktualny_bit <- n mod 2
      jeżeli aktualny_bit != poprzedni_bit to
          b <- b + 1
      poprzedni_bit <- aktualny_bit
      n <- n div 2
    
    wypisz b
  • 3

    Alternatywa - Rozwiązanie w języku Python

    Ten sam algorytm przetłumaczony na język programowania z użyciem operatorów % (modulo) oraz // (dzielenie całkowite).

    def policz_bloki(n):
      b = 1
      poprzedni_bit = n % 2
      n = n // 2
      
      while n > 0:
          aktualny_bit = n % 2
          if aktualny_bit != poprzedni_bit:
              b += 1
          poprzedni_bit = aktualny_bit
          n = n // 2
          
      return b

Matura Rozszerzona Informatyka Maj 2023

2 pkt
Zadanie 2.2.

Informacja do zadań 2.2. i 2.3.

W pliku bin.txt znajduje się 100 wierszy. Każdy wiersz zawiera zapis binarny dodatniej liczby całkowitej składający się z co najwyżej dwudziestu cyfr (0 lub 1).

Napisz program(-y), który(-e) da(-dzą) odpowiedzi do poniższych zadań. Odpowiedzi zapisz w pliku wyniki2.txt, a każdą z nich poprzedź numerem odpowiedniego zadania.

Plik bin_przyklad.txt zawiera 100 wierszy przykładowych danych spełniających warunki zadania. Odpowiedzi dla danych z pliku bin_przyklad.txt są podane pod treściami zadań.

Zadanie 2.2. (0–2 pkt)

Podaj, ile liczb w pliku bin.txt składa się z co najwyżej dwóch bloków (zgodnie z definicją bloku podaną wcześniej).

Dla danych z pliku bin_przyklad.txt poprawna odpowiedź to 3.

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Rozwiązanie - Język Python

    Ponieważ liczby w pliku są zapisane jako ciągi znaków (stringi) zer i jedynek, zliczanie bloków jest bardzo proste. Wystarczy przejść pętlą po znakach i sprawdzić, ile razy znak zmienia się na inny. Następnie zliczamy te linie, dla których liczba bloków wynosi 2\le 2.

    def policz_bloki_string(s):
      if not s:
          return 0
      bloki = 1
      for i in range(1, len(s)):
          if s[i] != s[i-1]:
              bloki += 1
      return bloki
    
    def solve_2_2():
      licznik = 0
      with open('bin.txt', 'r') as f:
          for line in f:
              linia = line.strip()
              if policz_bloki_string(linia) <= 2:
                  licznik += 1
                  
      print(f"2.2. Odpowiedź: {licznik}")
    
    solve_2_2()

Matura Rozszerzona Informatyka Maj 2023

2 pkt
Zadanie 2.3.

Zadanie 2.3. (0–2 pkt)

Wypisz największą z liczb zapisanych w pliku bin.txt.

Dla danych z pliku bin_przyklad.txt poprawna odpowiedź to 10001111110111100000.

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Rozwiązanie - Język Python

    Szukamy największej liczby. Ponieważ mamy do czynienia z napisami binarnymi, nie możemy ich po prostu posortować alfabetycznie (wtedy "10" byłoby przed "2", a "111" byłoby mniejsze od "1000" przy złym formatowaniu, chociaż w przypadku samych 0 i 1 oraz różnej długości jest to zgubne).

    Najpewniejszym rozwiązaniem jest zamiana każdego ciągu na prawdziwą liczbę całkowitą (przy pomocy int(x, 2)), znalezienie maksimum i wypisanie oryginalnego ciągu.

    def solve_2_3():
      with open('bin.txt', 'r') as f:
          linie = [line.strip() for line in f.readlines()]
          
      # Funkcja max pozwala na użycie 'key' do wyznaczenia, jak oceniać wielkość elementu.
      # Używamy int(x, 2) do przekonwertowania ciągu binarnego na dziesiętny do celów porównania.
      najwieksza = max(linie, key=lambda x: int(x, 2))
      
      print(f"2.3. Odpowiedź: {najwieksza}")
    
    solve_2_3()

Matura Rozszerzona Informatyka Maj 2023

1 pkt
Zadanie 2.4.

Zadanie 2.4. (0–1 pkt)

Dla nieujemnych liczb całkowitych aa i bb wynikiem operacji a XOR ba \text{ XOR } b jest liczba, której kolejne bity są wyliczane na podstawie poniższej tabelki z odpowiadających sobie bitów w zapisie binarnym liczb aa i bb. Jeśli jeden zapis jest krótszy od drugiego, to uzupełniamy go zerami z lewej strony (na najbardziej znaczących pozycjach).

ppqqp XOR qp \text{ XOR } q
110
101
011
000

np.

410 XOR 710=1002 XOR 1112=0112=3104_{10} \text{ XOR } 7_{10} = 100_2 \text{ XOR } 111_2 = 011_2 = 3_{10}
610 XOR 1110=01102 XOR 10112=11012=13106_{10} \text{ XOR } 11_{10} = 0110_2 \text{ XOR } 1011_2 = 1101_2 = 13_{10}

Oblicz (12310 XOR 1011012) XOR 2D16(123_{10} \text{ XOR } 101101_2) \text{ XOR } 2\text{D}_{16}. Wynik podaj w systemie dziesiętnym.

Odpowiedź: ........................................................................................

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Analiza matematyczna (Sposób sprytny)

    Warto najpierw przyjrzeć się liczbom, które mamy "XORować", sprowadzając je wszystkie do wspólnego systemu (np. dziesiętnego).

    • Pierwsza liczba: 12310123_{10}
    • Druga liczba (binarna): 1011012=132+016+18+14+02+11=32+8+4+1=4510101101_2 = 1 \cdot 32 + 0 \cdot 16 + 1 \cdot 8 + 1 \cdot 4 + 0 \cdot 2 + 1 \cdot 1 = 32 + 8 + 4 + 1 = 45_{10}
    • Trzecia liczba (szesnastkowa): 2D16=216+13=32+13=45102\text{D}_{16} = 2 \cdot 16 + 13 = 32 + 13 = 45_{10}

    Nasze wyrażenie to tak naprawdę: (12310 XOR 4510) XOR 4510(123_{10} \text{ XOR } 45_{10}) \text{ XOR } 45_{10}.

    Operacja XOR jest łączna oraz posiada niezwykłą właściwość polegającą na tym, że "XORowanie" tej samej wartości dwa razy ją neutralizuje (działa jak włącznik/wyłącznik). Algebraicznie zapisujemy to jako: A XOR B XOR B=AA \text{ XOR } B \text{ XOR } B = A.

    W związku z tym (123 XOR 45) XOR 45=123(123 \text{ XOR } 45) \text{ XOR } 45 = 123. Całe skomplikowane przeliczanie na bity można pominąć, jeśli zauważy się tę własność!

  • 2

    Analiza klasyczna (Obliczenia bitowe)

    Nawet jeśli nie zauważymy sprytnego skrótu, rozwiązanie klasyczne również zadziała:

    1. 12310123_{10} na system binarny to 111101121111011_2.

    2. 1011012101101_2 wyrównujemy zerami z lewej do 7 bitów: 010110120101101_2.

    3. Wykonujemy 12310 XOR 1011012123_{10} \text{ XOR } 101101_2:

        1111011 (123)
      ^ 0101101 (45)
      ---------
      1010110 (86)
    4. 2D162\text{D}_{16} zamieniamy na system binarny (2=00102 = 0010, extD=1101 ext{D} = 1101): 00101101200101101_2.

    5. Wykonujemy drugi XOR (wynik z kroku 3 i liczba z kroku 4):

        1010110 (86)
      ^ 0101101 (45)
      ---------
      1111011 (123)
    6. Wynik 111101121111011_2 zamieniamy z powrotem na dziesiętny: 64+32+16+8+2+1=1231064+32+16+8+2+1 = 123_{10}.

    Odpowiedź: 123

Matura Rozszerzona Informatyka Maj 2023

3 pkt
Zadanie 2.5.

Zadanie 2.5. (0–3 pkt)

Napisz program, który dla każdej binarnej liczby pp zapisanej w pliku bin.txt obliczy wynik działania

p XOR (p div 2)p \text{ XOR } (p \text{ div } 2)

gdzie XOR to operacja bitowa opisana wcześniej, a p div 2p \text{ div } 2 oznacza połowę liczby pp, zaokrągloną w dół do liczby całkowitej.

Otrzymane wyniki podaj w systemie binarnym. Zapisz je do pliku wyniki2_5.txt w kolejności występowania liczb w pliku bin.txt, każdy wynik w oddzielnym wierszu.

Odpowiedź dla danych z pliku bin_przyklad.txt znajduje się w pliku odp_bin_przyklad.txt.

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Analiza problemu

    Zadanie wydaje się skomplikowane, ale w rzeczywistości programowanie ułatwia sprawę. Zauważmy, że operacja p div 2p \text{ div } 2 (dzielenie całkowite przez 2) w systemie binarnym jest równoważna przesunięciu bitowemu w prawo o 1 pozycję (ang. bit shift right). Oznacza to po prostu "odcięcie" ostatniej cyfry z prawej strony.

    W języku Python możemy to zadanie rozwiązać bardzo szybko, korzystając z wbudowanych funkcji konwersji, które w tym wypadku (w przeciwieństwie do tworzenia pseudokodu w zadaniu 2.1) są w pełni dozwolone.

    • Wczytujemy liczbę jako ciąg znaków (np. z pliku).
    • Konwertujemy ją na typ całkowity, podając podstawę 2: int(p, 2).
    • Wykonujemy operację bitowego XOR (w Pythonie jest to znak ^) na tej liczbie oraz jej połowie (p // 2).
    • Formatujemy wynik z powrotem do postaci binarnej za pomocą funkcji bin() i usuwamy z niego techniczny przedrostek 0b.
  • 2

    Rozwiązanie - Język Python

    def solve_2_5():
      # Otwieramy strumienie odczytu i zapisu jednocześnie
      with open('bin.txt', 'r') as file_in, open('wyniki2_5.txt', 'w') as file_out:
          for line in file_in:
              p_str = line.strip()
              if not p_str:
                  continue
                  
              # 1. Konwersja z systemu binarnego (string) na dziesiętny (int)
              p = int(p_str, 2)
              
              # 2. Wykonanie wymaganej operacji bitowej i arytmetycznej
              wynik_dziesietny = p ^ (p // 2)
              
              # 3. Konwersja z powrotem na system binarny
              # Funkcja bin() zwraca string w formacie '0b101...', 
              # więc odcinamy znaki '0b' ucinając pierwsze dwa znaki [2:]
              wynik_binarny = bin(wynik_dziesietny)[2:]
              
              # Zapis do pliku wynikowego z dodaniem znaku nowej linii
              file_out.write(wynik_binarny + "\n")
    
    solve_2_5()

Matura Rozszerzona Informatyka Maj 2023

2 pkt
Zadanie 3.1.

Zadanie 3. Liczba Pi

Pewien matematyk jest zafascynowany liczbą π3,14159265\pi \approx 3,14159265\dots do tego stopnia, że zapisał jej rozwinięcie dziesiętne z dokładnością do 10 000 cyfr po przecinku. Wszystkie cyfry po przecinku zapisał w pliku tekstowym pi.txt.

Plik pi.txt zawiera 10 000 wierszy, każdy wiersz zawiera jedną cyfrę. W pierwszych 10 wierszach pliku zapisano zatem cyfry:
1
4
1
5
9
2
6
5
3
5

Matematyk zastanawia się, jakiego rodzaju regularności można zaobserwować w zebranych danych.

Napisz program(y), który(-e) da(-dzą) odpowiedzi do poniższych zadań. Odpowiedzi do zadań zapisz w pliku wyniki3.txt, a każdą z nich poprzedź numerem odpowiedniego zadania.

Plik pi_przyklad.txt zawiera 100 pierwszych wierszy pliku pi.txt. Odpowiedzi dla danych z tego pliku są podane pod treściami zadań.

Zadanie 3.1. (0–2 pkt)

Fragmentem 2-cyfrowym nazywamy dwie następujące po sobie cyfry w pliku pi.txt. Wszystkich fragmentów 2-cyfrowych zapisanych w tym pliku jest 9 999. Ostatni rozpoczyna się w wierszu nr 9 999.

Przykładowe fragmenty 2-cyfrowe podano w poniższej tabeli.
iiFragment 2-cyfrowy złożony z cyfr na pozycjach ii, i+1i+1
114
241
315
935

Znajdź liczbę wszystkich fragmentów 2-cyfrowych, które są zapisami dziesiętnymi liczb o wartościach większych od 90.

Dla danych zapisanych w pliku pi_przyklad.txt poprawna odpowiedź to 13.

Odpowiedź: ........................................................................................

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Analiza problemu

    Zadanie polega na iterowaniu po pliku, pobieraniu cyfry z bieżącej linii oraz z linii następnej, a następnie łączeniu ich w jedną liczbę dwucyfrową.

    • Najprościej wczytać wszystkie wiersze z pliku do jednej tablicy/listy. Pamiętamy o usunięciu białych znaków (np. znaków nowej linii) za pomocą strip().
    • Następnie tworzymy pętlę, która przechodzi od pierwszego elementu (indeks 0) do przedostatniego (indeks n2n-2), aby nie wyjść poza zakres tablicy podczas odwoływania się do elementu i+1i+1.
    • Liczbę 2-cyfrową możemy stworzyć poprzez konkatenację (łączenie) stringów: cyfra1 + cyfra2 i rzutowanie wyniku na int (int()), albo matematycznie: cyfra1 * 10 + cyfra2 (jeśli operujemy już na liczbach).
    • Sprawdzamy warunek > 90 i jeśli jest spełniony, zwiększamy nasz licznik.
  • 2

    Rozwiązanie - Język Python

    def solve_3_1():
      # 1. Wczytanie danych do listy, z oczyszczeniem ze znaków nowej linii
      with open('pi.txt', 'r') as f:
          cyfry = [line.strip() for line in f.readlines() if line.strip()]
    
      licznik = 0
      
      # 2. Iteracja do przedostatniego elementu
      for i in range(len(cyfry) - 1):
          # Konkatenacja stringów (np. "9" + "2" = "92")
          fragment_str = cyfry[i] + cyfry[i+1]
          
          # Rzutowanie na int i sprawdzenie warunku
          if int(fragment_str) > 90:
              licznik += 1
    
      print(f"3.1. Odpowiedź: {licznik}")
    
    solve_3_1()

Matura Rozszerzona Informatyka Maj 2023

3 pkt
Zadanie 3.2.

Zadanie 3.2. (0–3 pkt)

Wszystkich możliwych różnych fragmentów 2-cyfrowych jest dokładnie 100. Są nimi fragmenty 00, 01, 02, ..., 99. Można sprawdzić, że np. 2-cyfrowy fragment równy 27 występuje w pliku pi.txt dokładnie 101 razy.

Znajdź fragmenty 2-cyfrowe, których liczba wystąpień w pliku pi.txt jest najmniejsza, oraz fragmenty 2-cyfrowe, których liczba wystąpień w pliku pi.txt jest największa. W wyniku podaj znalezione fragmenty 2-cyfrowe oraz liczby ich wystąpień.

W przypadku, gdy więcej niż jeden fragment występuje tyle samo razy, wypisz ten o mniejszej wartości liczbowej.

Dla danych w pliku pi_przyklad.txt poprawna odpowiedź to
00 0
62 4
(minimalna liczba wystąpień: fragment 00, liczba wystąpień 0; maksymalna liczba wystąpień: fragment 62, liczba wystąpień 4)

Odpowiedź (minimum): ....................................................................

Odpowiedź (maksimum): ....................................................................

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Analiza problemu

    Zadanie jest logiczną kontynuacją poprzedniego. Tym razem musimy policzyć wystąpienia każdego z 100 możliwych fragmentów (od "00" do "99").

    • Najlepiej przygotować słownik (lub listę 100-elementową wyzerowaną na starcie), gdzie kluczem będzie nasz fragment (np. "05"), a wartością liczba jego wystąpień. Koniecznie generujemy bazę wszystkich stu fragmentów, ponieważ niektóre mogą w ogóle nie wystąpić w pliku (ich liczba wystąpień to 0).

    • Ponownie przechodzimy pętlą po wczytanych cyfrach i sklejamy je parami, zwiększając odpowiedni licznik w słowniku.

    • Kluczowym wymogiem jest: "wypisz ten o mniejszej wartości liczbowej". Aby to zagwarantować, wystarczy przeglądać nasz słownik w kolejności od "00" do "99" i aktualizować zmienne trzymające minimum/maksimum tylko wtedy, gdy znajdziemy wartość ostro mniejszą/większą (używając operatorów < i > zamiast <= czy >=).

  • 2

    Rozwiązanie - Język Python

    def solve_3_2():
      with open('pi.txt', 'r') as f:
          cyfry = [line.strip() for line in f.readlines() if line.strip()]
    
      # Generujemy wszystkie kombinacje od "00" do "99" i ustawiamy ich licznik na 0
      wystapienia = {}
      for i in range(100):
          # zfill(2) dodaje wiodące zera, np. 5 -> "05"
          wystapienia[str(i).zfill(2)] = 0
    
      # Zliczamy fragmenty 2-cyfrowe
      for i in range(len(cyfry) - 1):
          fragment = cyfry[i] + cyfry[i+1]
          wystapienia[fragment] += 1
    
      # Inicjalizujemy min/max skrajnymi wartościami
      min_wystapien = float('inf')
      max_wystapien = -1
      najmniejszy_frag = ""
      najwiekszy_frag = ""
    
      # Przechodzimy po posortowanych kluczach (od "00" do "99")
      for frag in sorted(wystapienia.keys()):
          ile = wystapienia[frag]
          
          # Ostre < gwarantuje, że przy remisie zostawimy pierwszy 
          # znaleziony fragment (czyli ten o mniejszej wartości)
          if ile < min_wystapien:
              min_wystapien = ile
              najmniejszy_frag = frag
              
          if ile > max_wystapien:
              max_wystapien = ile
              najwiekszy_frag = frag
    
      print(f"3.2. Minimum: {najmniejszy_frag} {min_wystapien}")
      print(f"3.2. Maksimum: {najwiekszy_frag} {max_wystapien}")
    
    solve_3_2()

Matura Rozszerzona Informatyka Maj 2023

3 pkt
Zadanie 3.3.

Informacja do zadań 3.3. i 3.4.

Skończony co najmniej 4-elementowy ciąg liczb (a1,a2,,an)(a_1, a_2, \dots, a_n) jest rosnąco-malejący, jeśli można podzielić go na dwa ciągi, z których pierwszy jest rosnący, a drugi – malejący, tzn. jeśli istnieje takie k{2,3,,n2}k \in \{2, 3, \dots, n - 2\}, że a1<a2<<aka_1 < a_2 < \dots < a_k oraz ak+1>ak+2>>ana_{k+1} > a_{k+2} > \dots > a_n.

Przykład:

Ciąg (2, 5, 7, 9, 8, 3, 1) jest rosnąco-malejący, bo można go podzielić na dwa ciągi: rosnący (2, 5, 7) i malejący (9, 8, 3, 1) lub – odpowiednio – (2, 5, 7, 9) i (8, 3, 1). Ciąg (5, 9, 9, 4, 1) także jest rosnąco-malejący.
Przykłady ciągów, które nie są rosnąco-malejące, to: (2, 5, 8, 4, 3, 4, 5), (1, 2, 3, 4), (5, 5, 3, 2, 1).

Zadanie 3.3. (0–3 pkt)

Podaj, ile jest wszystkich rosnąco-malejących ciągów złożonych z dokładnie sześciu kolejnych cyfr zapisanych w pliku pi.txt.

Dla pliku pi_przyklad.txt poprawna odpowiedź to 3.
(w pliku pi_przyklad.txt są trzy ciągi rosnąco-malejące złożone z dokładnie sześciu cyfr: 028841, 089986, 899862)

Odpowiedź: ........................................................................................

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Analiza definicji ciągu "rosnąco-malejącego"

    Zrozumienie definicji to 90% sukcesu w tym zadaniu. Zauważmy kluczową rzecz: matematyczny zapis aka_k oraz ak+1a_{k+1} wskazuje, że ciąg jest dzielony na dwie niezależne części. Ostatni element części rosnącej nie musi być w żaden sposób większy/mniejszy od pierwszego elementu części malejącej. One po prostu stoją obok siebie!

    Dla ciągu o długości n=6n = 6, parametr podziału kk może przyjmować wartości ze zbioru {2,3,4}\{2, 3, 4\}. Oznacza to, że 6-elementowy ciąg (np. o indeksach 0, 1, 2, 3, 4, 5) możemy "przeciąć" w trzech miejscach:

    • k = 2: elementy [0, 1] rosną, a elementy [2, 3, 4, 5] maleją.
    • k = 3: elementy [0, 1, 2] rosną, a elementy [3, 4, 5] maleją.
    • k = 4: elementy [0, 1, 2, 3] rosną, a elementy [4, 5] maleją.

    Wystarczy, że chociaż jeden z tych podziałów jest poprawny, aby cały 6-cyfrowy ciąg uznać za rosnąco-malejący.

  • 2

    Rozwiązanie - Język Python

    Napiszemy dwie proste funkcje pomocnicze sprawdzające, czy podana lista cyfr jest ściśle rosnąca i ściśle malejąca. Następnie wyodrębnimy okno 6-elementowe i sprawdzimy podziały.

    def czy_rosnacy(fragment):
      for i in range(len(fragment) - 1):
          if fragment[i] >= fragment[i+1]:
              return False
      return True
    
    def czy_malejacy(fragment):
      for i in range(len(fragment) - 1):
          if fragment[i] <= fragment[i+1]:
              return False
      return True
    
    def czy_rosnaco_malejacy(fragment):
      # fragment ma zawsze długość 6.
      # Sprawdzamy możliwe punkty podziału k = 2, 3, 4
      for k in [2, 3, 4]:
          czesc_rosnaca = fragment[:k]
          czesc_malejaca = fragment[k:]
          
          if czy_rosnacy(czesc_rosnaca) and czy_malejacy(czesc_malejaca):
              return True
      return False
    
    def solve_3_3():
      with open('pi.txt', 'r') as f:
          # Od razu konwertujemy wczytane znaki na liczby całkowite (int)
          cyfry = [int(line.strip()) for line in f.readlines() if line.strip()]
    
      licznik = 0
      
      # Przesuwamy "okno" o szerokości 6 po całej tablicy
      for i in range(len(cyfry) - 5):
          okno = cyfry[i : i+6]
          if czy_rosnaco_malejacy(okno):
              licznik += 1
    
      print(f"3.3. Odpowiedź: {licznik}")
    
    solve_3_3()

Matura Rozszerzona Informatyka Maj 2023

2 pkt
Zadanie 3.4.

Zadanie 3.4. (0–2 pkt)

Znajdź najdłuższy ciąg kolejnych cyfr z pliku pi.txt, który jest rosnąco-malejący, oraz pozycję, na której on się rozpoczyna. W pliku pi.txt jest tylko jeden taki ciąg o największej długości.

Wynik zapisz w dwóch wierszach: w pierwszym wierszu zapisz pozycję, od której zaczyna się znaleziony ciąg, a w drugim wypisz znaleziony ciąg. Cyfry ciągu zapisz jedną po drugiej, bez znaku odstępu.

Dla danych w pliku pi_przyklad.txt poprawna odpowiedź to
77
0899862
(najdłuższy ciąg rosnąco-malejący w pliku pi_przyklad.txt to ciąg 0899862 o długości 7 rozpoczynający się w 77 wierszu pliku).

Odpowiedź (pozycja): ....................................................................

Odpowiedź (ciąg): .......................................................................

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Analiza problemu i optymalne podejście

    Szukamy najdłuższego ciągu rosnąco-malejącego. Z zadania 3.3. wiemy, że punkt podziału to takie miejsce, gdzie po lewej stronie mamy ciąg ściśle rosnący, a po prawej ściśle malejący. Zamiast sprawdzać każdą możliwą podtablicę w sposób brutalny (co przy 10 000 elementach zajęłoby dużo czasu), możemy użyć sprytnego algorytmu programowania dynamicznego w czasie O(N)O(N).

    • Krok 1: Tworzymy tablicę inc, w której inc[i] to długość najdłuższego ciągu rosnącego kończącego się na indeksie i. Wypełniamy ją idąc od lewej do prawej.

    • Krok 2: Tworzymy tablicę dec, w której dec[i] to długość najdłuższego ciągu malejącego zaczynającego się na indeksie i. Wypełniamy ją idąc od prawej do lewej.

    • Krok 3: Przeszukujemy tablicę, traktując każdy indeks k jako potencjalny koniec części rosnącej. Część malejąca będzie się wtedy zaczynać od indeksu k + 1.

    • Krok 4: Jeśli inc[k] ≥ 2 (część rosnąca ma min. 2 elementy) oraz dec[k+1] ≥ 2 (część malejąca ma min. 2 elementy), to całkowita długość takiego połączonego ciągu wynosi inc[k] + dec[k+1].

    Wybieramy takie k, dla którego suma ta jest największa, a pozycję startową odzyskamy odejmując od k długość części rosnącej.

  • 2

    Rozwiązanie - Język Python

    def solve_3_4():
      with open('pi.txt', 'r') as f:
          cyfry = [int(line.strip()) for line in f.readlines() if line.strip()]
    
      n = len(cyfry)
      if n == 0:
          return
    
      # inc[i] - długość najdłuższego ciągu rosnącego kończącego się na i
      inc = [1] * n
      for i in range(1, n):
          if cyfry[i] > cyfry[i-1]:
              inc[i] = inc[i-1] + 1
    
      # dec[i] - długość najdłuższego ciągu malejącego zaczynającego się na i
      dec = [1] * n
      for i in range(n-2, -1, -1):
          if cyfry[i] > cyfry[i+1]:
              dec[i] = dec[i+1] + 1
    
      max_len = 0
      best_start = -1
      best_seq = ""
    
      # Szukamy optymalnego punktu podziału k
      for k in range(0, n - 1):
          # Część rosnąca (do k) i malejąca (od k+1) muszą mieć co najmniej po 2 elementy
          if inc[k] >= 2 and dec[k+1] >= 2:
              current_len = inc[k] + dec[k+1]
              
              if current_len > max_len:
                  max_len = current_len
                  # Obliczamy indeks początkowy (0-based)
                  start_idx = k - inc[k] + 1
                  
                  # Dodajemy 1, bo numery wierszy są od 1
                  best_start = start_idx + 1 
                  best_seq = "".join(map(str, cyfry[start_idx : start_idx + current_len]))
    
      print("3.4. Odpowiedź:")
      print(best_start)
      print(best_seq)
    
    solve_3_4()

Matura Rozszerzona Informatyka Maj 2023

1 pkt
Zadanie 4.

Zadanie 4. (0–1 pkt)

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

W komunikacji między dwoma osobami A i B z wykorzystaniem szyfrowania asymetrycznego klucz prywatny osoby A stosuje się do:

Lp.ZdaniePF
1.odszyfrowania wiadomości wysłanej do osoby A przez osobę B.
2.uwierzytelnienia osoby B przez osobę A.
💡 Pokaż rozwiązanie krok po kroku
  • 1

    Analiza i rozwiązanie:

    W kryptografii asymetrycznej każdy użytkownik posiada parę kluczy: publiczny (udostępniany każdemu) oraz prywatny (znany tylko właścicielowi).

    1. odszyfrowania wiadomości wysłanej do osoby A przez osobę B.
      PRAWDA (P). Kiedy osoba B chce wysłać tajną wiadomość do osoby A, szyfruje ją za pomocą klucza publicznego osoby A. Jedynym kluczem, który może odszyfrować tę wiadomość, jest klucz prywatny osoby A.

    2. uwierzytelnienia osoby B przez osobę A.
      FAŁSZ (F). Aby uwierzytelnić osobę B (czyli upewnić się, że to na pewno ona nadała wiadomość), B musi podpisać wiadomość swoim własnym kluczem prywatnym. Następnie osoba A do weryfikacji tego podpisu używa klucza publicznego osoby B. Klucz prywatny osoby A nie bierze udziału w uwierzytelnianiu innych osób.

Matura Rozszerzona Informatyka Maj 2023

1 pkt
Zadanie 5.

Zadanie 5. (0–1 pkt)

Dane są liczby zapisane w systemach pozycyjnych o podstawach 3, 5 i 6. Wstaw w miejsce kropek odpowiedni znak spośród: <, >, =, tak aby wyrażenie było poprawne.

(2011)3(2011)_3
=
(134)6(134)_6
(134)5(134)_5
................
(134)6(134)_6
(2222)3(2222)_3
................
(1111)6(1111)_6
💡 Pokaż rozwiązanie krok po kroku
  • 1

    Analiza 1. przypadku: (134)5(134)6(134)_5 \dots (134)_6

    To wyrażenie można rozwiązać bez żadnych obliczeń za pomocą dedukcji. Obie liczby mają dokładnie taki sam zapis cyfrowy (1, 3, 4), ale są w różnych systemach liczbowych.

    Im wyższa podstawa systemu, tym większą "wagę" mają poszczególne pozycje. W systemie szóstkowym wagi to 1,6,361, 6, 36, a w systemie piątkowym to 1,5,251, 5, 25. Skoro mnożymy te same cyfry przez wyższe wagi, wartość całkowita musi być większa.

    Odpowiedź: << (ponieważ 4410<581044_{10} < 58_{10})

  • 2

    Analiza 2. przypadku: (2222)3(1111)6(2222)_3 \dots (1111)_6

    Tutaj najlepiej zamienić obie liczby na znany nam system dziesiętny:

    • Rozwijamy pierwszą liczbę (podstawa 3):

      (2222)3=233+232+231+230(2222)_3 = 2 \cdot 3^3 + 2 \cdot 3^2 + 2 \cdot 3^1 + 2 \cdot 3^0
      =227+29+23+21= 2 \cdot 27 + 2 \cdot 9 + 2 \cdot 3 + 2 \cdot 1
      =54+18+6+2=8010= 54 + 18 + 6 + 2 = 80_{10}
    • Rozwijamy drugą liczbę (podstawa 6):

      (1111)6=163+162+161+160(1111)_6 = 1 \cdot 6^3 + 1 \cdot 6^2 + 1 \cdot 6^1 + 1 \cdot 6^0
      =216+36+6+1=25910= 216 + 36 + 6 + 1 = 259_{10}

    Porównujemy wyniki: 80<25980 < 259.

    Odpowiedź:<<

Matura Rozszerzona Informatyka Maj 2023

3 pkt
Zadanie 6.1.

Zadanie 6. Konfitury owocowe

W pliku owoce.txt zapisano informacje o dostawach owoców do przetwórni w okresie od 01.05.2020 do 30.09.2020.

W każdym wierszu podane są: data dostawy (dd.mm.rrrr), liczba kilogramów dostarczonych malin, liczba kilogramów dostarczonych truskawek i liczba kilogramów dostarczonych porzeczek, oddzielone znakiem tabulacji.

Dostawy odbywały się każdego dnia w wymienionym okresie.

Przykład:
data          dostawa_malin  dostawa_truskawek  dostawa_porzeczek
01.05.2020    211            281                88
02.05.2020    393            313                83
03.05.2020    389            315                104
04.05.2020    308            221                119

Z wykorzystaniem dostępnych narzędzi informatycznych podaj odpowiedzi do poniższych zadań. Odpowiedzi zapisz w pliku wyniki6.txt, a każdą z nich poprzedź numerem odpowiedniego zadania.

Zadanie 6.1. (0–3 pkt)

Dla każdego miesiąca pracy przetwórni (od maja do września) wykonaj zestawienie liczby dostarczonych kilogramów malin, liczby dostarczonych kilogramów truskawek i liczby dostarczonych kilogramów porzeczek.

Na podstawie wykonanego zestawienia utwórz wykres kolumnowy. Pamiętaj o czytelnym opisie wykresu (tytuł, legenda, opisy osi: na osi X – nazwy miesięcy, na osi Y – liczba kilogramów).

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Arkusz kalkulacyjny (Excel) - Przygotowanie danych

    1. Zaimportuj plik owoce.txt do Excela. Upewnij się, że separator to tabulacja, a kolumna z datą została poprawnie rozpoznana (jako Data, a nie Tekst).

    2. Aby móc grupować po miesiącach, dodaj nową kolumnę (np. w kolumnie E) o nazwie Miesiąc.

    3. Wpisz w niej formułę: =MIESIĄC(A2) i przeciągnij ją w dół. Otrzymasz numery od 5 do 9 (maj - wrzesień).
      *Jeśli Excel nie rozpoznał formatu daty, wyciągnij miesiąc tekstowo formułą: =FRAGMENT.TEKSTU(A2; 4; 2).

  • 2

    Krok 2: Tabela przestawna i Wykres

    1. Zaznacz całą tabelę z danymi i z zakładki Wstawianie wybierz Tabela przestawna.

    2. W polach tabeli przestawnej przeciągnij:

      • Miesiąc do obszaru Wiersze.
      • dostawa_malin, dostawa_truskawek oraz dostawa_porzeczek do obszaru Wartości. Upewnij się, że domyślną funkcją jest "Suma" (a nie np. "Licznik").
    3. Dla czytelności wykresu możesz zamienić numery miesięcy w wierszach na ich nazwy (5 -> Maj, 6 -> Czerwiec itd.).

    4. Kliknij wewnątrz Tabeli Przestawnej, przejdź do zakładki Wstawianie i wybierz Wykres kolumnowy (standardowy, grupowy).

    5. Dodaj wymagane elementy wykresu (przez kliknięcie "+" obok wykresu):

      • Tytuł wykresu: np. "Zestawienie dostaw owoców (maj-wrzesień 2020)".
      • Tytuły osi: oś pozioma (X) -> "Miesiąc", oś pionowa (Y) -> "Liczba kilogramów".
      • Legenda: powinna wygenerować się automatycznie i opisywać poszczególne owoce.
  • 3

    Alternatywa: Zestawienie w języku Python

    Jeśli wolisz wygenerować zestawienie programistycznie (aby potem tylko skopiować tabelkę do Excela pod sam wykres), możesz użyć tego skryptu:

    def solve_6_1():
      # Słownik trzymający sumy: miesiac -> [maliny, truskawki, porzeczki]
      miesieczne_dostawy = {
          '05': [0, 0, 0], '06': [0, 0, 0], 
          '07': [0, 0, 0], '08': [0, 0, 0], '09': [0, 0, 0]
      }
      
      with open('owoce.txt', 'r') as f:
          # Pomiń nagłówek, jeśli plik go posiada
          lines = f.readlines()
          if "data" in lines[0]:
              lines = lines[1:]
              
          for line in lines:
              parts = line.strip().split('\t')
              if len(parts) >= 4:
                  data = parts[0]
                  miesiac = data[3:5] # Pobieramy mm z dd.mm.rrrr
                  
                  maliny = int(parts[1])
                  truskawki = int(parts[2])
                  porzeczki = int(parts[3])
                  
                  if miesiac in miesieczne_dostawy:
                      miesieczne_dostawy[miesiac][0] += maliny
                      miesieczne_dostawy[miesiac][1] += truskawki
                      miesieczne_dostawy[miesiac][2] += porzeczki
    
      # Wypisywanie wyników (gotowe do wklejenia)
      print("Miesiąc\tMaliny\tTruskawki\tPorzeczki")
      nazwy = {'05': 'Maj', '06': 'Czerwiec', '07': 'Lipiec', '08': 'Sierpień', '09': 'Wrzesień'}
      
      for m in sorted(miesieczne_dostawy.keys()):
          dane = miesieczne_dostawy[m]
          print(f"{nazwy[m]}\t{dane[0]}\t{dane[1]}\t{dane[2]}")
    
    solve_6_1()

Matura Rozszerzona Informatyka Maj 2023

1 pkt
Zadanie 6.2.

Zadanie 6.2. (0–1 pkt)

Podaj liczbę dni, w których dostarczono, spośród trzech rodzajów owoców, najwięcej porzeczek.

Odpowiedź: ........................................................................................

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Rozwiązanie - Arkusz kalkulacyjny

    1. W tabeli z danymi stwórz nową kolumnę (np. kolumnę F).

    2. Interesują nas dni, w których waga porzeczek (kolumna D) jest ostro większa od wagi malin (kolumna B) oraz od wagi truskawek (kolumna C).

    3. W komórce F2 wpisz formułę używającą funkcji logicznej ORAZ:

      =JEŻELI(ORAZ(D2 > B2; D2 > C2); 1; 0)

    4. Przeciągnij formułę na sam dół tabeli.

    5. Zsumuj wartości z kolumny F (np. formułą =SUMA(F:F)). Wynik to szukana odpowiedź.

  • 2

    Rozwiązanie - Język Python

    Rozwiązanie za pomocą prostego skryptu filtrującego:

    def solve_6_2():
      licznik = 0
      with open('owoce.txt', 'r') as f:
          lines = f.readlines()
          if "data" in lines[0]:
              lines = lines[1:]
              
          for line in lines:
              parts = line.strip().split('\t')
              if len(parts) >= 4:
                  maliny = int(parts[1])
                  truskawki = int(parts[2])
                  porzeczki = int(parts[3])
                  
                  # Porzeczki muszą dominować nad obiema pozostałymi wartościami
                  if porzeczki > maliny and porzeczki > truskawki:
                      licznik += 1
                      
      print(f"6.2. Odpowiedź: {licznik}")
    
    solve_6_2()

Matura Rozszerzona Informatyka Maj 2023

3 pkt
Zadanie 6.3.

Informacja do zadań 6.3. i 6.4.

Przetwórnia produkuje konfitury: malinowo-truskawkowe, malinowo-porzeczkowe oraz truskawkowo-porzeczkowe (zawsze w proporcji owoców 1:1 oraz z wykorzystaniem maksymalnej dostępnej ilości owoców). Decyzja, jaka konfitura w danym dniu będzie produkowana, zależy od ilości owoców w przetwórni.

Owoce są dostarczane do przetwórni rano, przed rozpoczęciem produkcji. W danym dniu jest produkowany tylko jeden rodzaj konfitur. Do produkcji są brane owoce, których jest najwięcej w przetwórni (dla danych w pliku owoce.txt nie występuje przypadek, gdy ilość różnych owoców jest taka sama). Owoce niewykorzystane do produkcji są przechowywane w chłodni do następnego dnia. W następnym dniu podejmuje się decyzję o produkcji na ten dzień na podstawie łącznej ilości owoców pozostałych z poprzedniego dnia oraz dostarczonych rano.

Przykład:

Jeżeli 01.05.2020 dostarczono 211 kg malin, 281 kg truskawek i 88 kg porzeczek, to w tym dniu będzie produkowana konfitura malinowo-truskawkowa. Do produkcji wykorzystane zostanie 211 kg malin i 211 kg truskawek. Reszta truskawek i wszystkie porzeczki będą przechowywane w chłodni do następnego dnia.



Po dostawie z 02.05.2020 (393 kg malin, 313 kg truskawek i 83 kg porzeczek) w przetwórni będzie 393 kg malin, 383 kg truskawek i 171 kg porzeczek, czyli znowu będzie produkowana konfitura malinowo-truskawkowa.

Zadanie 6.3. (0–3 pkt)

Po uwzględnieniu opisanego powyżej cyklu produkcyjnego oraz danych zapisanych w pliku owoce.txt podaj odpowiedzi do poniższych zadań.

Podaj, ile razy, w okresie od 01.05.2020 do 30.09.2020, produkowano konfitury poszczególnych rodzajów.

Malinowo-truskawkowe: ....................................................................

Malinowo-porzeczkowe: ....................................................................

Truskawkowo-porzeczkowe: .................................................................

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Analiza logiczna - Matematyka produkcji

    Zanim przejdziemy do narzędzi, zróbmy szybką analizę matematyczną tego, co się tu dzieje w każdym dniu. Mamy w magazynie 3 rodzaje owoców. Ponieważ wartości są zawsze unikalne, możemy je posortować: Minimum, Mediana, Maksimum.

    • Do produkcji bierzemy dwa owoce, których jest najwięcej – czyli te o ilości równej Maksimum oraz Medianie. Owoc o ilości równej Minimum nie jest używany.

    • Proporcja to 1:1, a wykorzystujemy "maksymalną dostępną ilość". Oznacza to, że użyjemy całości owocu, którego z tej wybranej dwójki jest mniej. Tym owocem jest oczywiście ten odpowiadający Medianie. Z obu rodzajów wybranych owoców pobierzemy dokładnie tyle, ile wynosi Mediana.

    • Stany po produkcji (reszta):
      • Owoc "Najmniejszy": nic z niego nie wzięliśmy, więc zostaje tyle, ile było.
      • Owoc "Średni" (Mediana): wzięliśmy z niego wszystko, więc jego stan wynosi dokładnie 0.
      • Owoc "Największy": pobraliśmy z niego ilość równą Medianie. Zostaje (Maksimum - Mediana).

    To genialne ułatwienie dla Excela! Ilość pobierana do produkcji to zawsze MEDIANA(Maliny; Truskawki; Porzeczki). Nie musimy pisać wielokrotnie zagnieżdżonych instrukcji JEŻELI(), by to wyliczyć.

  • 2

    Krok 1: Rozwiązanie - Arkusz kalkulacyjny

    Zakładamy, że kolumny to: A (Data), B (Dostawa Malin), C (Dostawa Truskawek), D (Dostawa Porzeczek).

    1. Stan rano (Dostawa + Reszta): W kolumnach E, F, G wyliczymy całkowitą ilość owoców.

      • Dzień pierwszy (wiersz 2): E2 = B2, F2 = C2, G2 = D2.
      • Kolejne dni (wiersz 3): E3 = B3 + K2, F3 = C3 + L2, G3 = D3 + M2 (gdzie K, L, M to reszty z poprzedniego dnia - wyliczymy je w kroku 4).
    2. Co produkujemy? W kolumnie H sprawdzamy, jakiego owocu jest najmniej (zatem pozostałe dwa idą do produkcji). Używamy funkcji MIN.


      Formuła w H2: =JEŻELI(E2=MIN(E2:G2); "Trusk-Porz"; JEŻELI(F2=MIN(E2:G2); "Mal-Porz"; "Mal-Trusk"))

    3. Zużycie (Mediana): W kolumnie I wpisujemy po prostu ilość pobieranych owoców.


      Formuła w I2: =MEDIANA(E2:G2)

    4. Reszta na koniec dnia: W kolumnach K (Maliny), L (Truskawki), M (Porzeczki) odejmujemy zużycie, ale tylko jeśli dany owoc brał udział w produkcji.

      • K2 = E2 - JEŻELI(E2=MIN($E2:$G2); 0; $I2)
      • L2 = F2 - JEŻELI(F2=MIN($E2:$G2); 0; $I2)
      • M2 = G2 - JEŻELI(G2=MIN($E2:$G2); 0; $I2)
    5. Przeciągnij formuły z wiersza 3 w dół. Odpowiedzią na zadanie jest zliczenie wartości w kolumnie H za pomocą funkcji LICZ.JEŻELI().

  • 3

    Alternatywa: Rozwiązanie w języku Python

    Jeśli sprytne formuły w arkuszu wydają się zbyt skomplikowane, ten sam proces możemy "zasymulować" krok po kroku w programie:

    def solve_6_3():
      # Stan magazynu
      magazyn = {'M': 0, 'T': 0, 'P': 0}
      
      # Liczniki konfitur
      konfitury = {'M-T': 0, 'M-P': 0, 'T-P': 0}
      
      with open('owoce.txt', 'r') as f:
          lines = f.readlines()
          if "data" in lines[0]:
              lines = lines[1:]
              
          for line in lines:
              parts = line.strip().split('\t')
              if len(parts) >= 4:
                  # 1. Dodanie dostawy porannej do magazynu
                  magazyn['M'] += int(parts[1])
                  magazyn['T'] += int(parts[2])
                  magazyn['P'] += int(parts[3])
                  
                  # 2. Sortowanie owoców po ilości, żeby znaleźć min, mid, max
                  posortowane = sorted(magazyn.items(), key=lambda x: x[1])
                  min_owoc = posortowane[0][0]  # np. 'P'
                  mid_owoc = posortowane[1][0]  # np. 'M'
                  max_owoc = posortowane[2][0]  # np. 'T'
                  
                  # 3. Decyzja o konfiturze (te, których NIE ma najmniej)
                  if min_owoc == 'P':
                      konfitury['M-T'] += 1
                  elif min_owoc == 'T':
                      konfitury['M-P'] += 1
                  elif min_owoc == 'M':
                      konfitury['T-P'] += 1
                      
                  # 4. Produkcja i aktualizacja stanów
                  zuzycie = magazyn[mid_owoc]  # Pobieramy ilość równą medianie
                  
                  if min_owoc != 'M': magazyn['M'] -= zuzycie
                  if min_owoc != 'T': magazyn['T'] -= zuzycie
                  if min_owoc != 'P': magazyn['P'] -= zuzycie
    
      print("6.3. Odpowiedzi:")
      print(f"Malinowo-truskawkowe: {konfitury['M-T']}")
      print(f"Malinowo-porzeczkowe: {konfitury['M-P']}")
      print(f"Truskawkowo-porzeczkowe: {konfitury['T-P']}")
    
    solve_6_3()

Matura Rozszerzona Informatyka Maj 2023

3 pkt
Zadanie 6.4.

Zadanie 6.4. (0–3 pkt)

Na wyprodukowanie 1 kg konfitur dwuowocowych potrzeba po 1 kg każdego owocu.

Podaj, ile kilogramów konfitur każdego rodzaju wyprodukowano w okresie od 01.05.2020 do 30.09.2020.

Malinowo-truskawkowe: ....................................................................

Malinowo-porzeczkowe: ....................................................................

Truskawkowo-porzeczkowe: .................................................................

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Analiza logiczna - Przelicznik produkcji

    Kluczowe w tym zadaniu jest zdanie: "Na wyprodukowanie 1 kg konfitur (...) potrzeba po 1 kg każdego owocu."

    Oznacza to, że biorąc 1 kg owocu A oraz 1 kg owocu B, otrzymujemy łącznie 1 kg gotowej konfitury (część masy najwyraźniej odparowuje/stanowi odpad w procesie). Z zadania 6.3. wiemy, że każdego dnia zużywamy dokładnie taką samą masę obu owoców, równą Medianie stanów magazynowych. Zatem waga wyprodukowanej danego dnia konfitury jest po prostu równa naszej dziennej Medianie!

  • 2

    Krok 1: Rozwiązanie - Arkusz kalkulacyjny

    Wykorzystamy tabelę przygotowaną w zadaniu 6.3. Posiadamy już w niej:

    • Kolumnę H: Rodzaj produkowanej konfitury (np. "Mal-Trusk").
    • Kolumnę I: Ilość zużywanego owocu (nasza wyliczona funkcja MEDIANA), która odpowiada wadze gotowej konfitury.

    Aby podsumować produkcję dla poszczególnych smaków, użyjemy funkcji SUMA.JEŻELI(). Przykładowo, w dowolnej pustej komórce wpisujemy:

    • Dla malinowo-truskawkowych: =SUMA.JEŻELI(H:H; "Mal-Trusk"; I:I)
    • Dla malinowo-porzeczkowych: =SUMA.JEŻELI(H:H; "Mal-Porz"; I:I)
    • Dla truskawkowo-porzeczkowych: =SUMA.JEŻELI(H:H; "Trusk-Porz"; I:I)
  • 3

    Alternatywa: Rozwiązanie w języku Python

    Skrypt jest niemal identyczny z tym z zadania 6.3. Zamiast jednak zwiększać licznik dni o 1, dodajemy do odpowiedniego smaku wagę wyprodukowanej konfitury (czyli wartość zuzycie).

    def solve_6_4():
      magazyn = {'M': 0, 'T': 0, 'P': 0}
      
      # Tym razem zliczamy wagę [kg], a nie liczbę dni
      produkcja = {'M-T': 0, 'M-P': 0, 'T-P': 0}
      
      with open('owoce.txt', 'r') as f:
          lines = f.readlines()
          if "data" in lines[0]:
              lines = lines[1:]
              
          for line in lines:
              parts = line.strip().split('\t')
              if len(parts) >= 4:
                  magazyn['M'] += int(parts[1])
                  magazyn['T'] += int(parts[2])
                  magazyn['P'] += int(parts[3])
                  
                  posortowane = sorted(magazyn.items(), key=lambda x: x[1])
                  min_owoc = posortowane[0][0]
                  mid_owoc = posortowane[1][0]
                  
                  zuzycie = magazyn[mid_owoc]
                  
                  # Dodajemy wagę wyprodukowanej konfitury do odpowiedniego smaku
                  if min_owoc == 'P':
                      produkcja['M-T'] += zuzycie
                  elif min_owoc == 'T':
                      produkcja['M-P'] += zuzycie
                  elif min_owoc == 'M':
                      produkcja['T-P'] += zuzycie
                      
                  if min_owoc != 'M': magazyn['M'] -= zuzycie
                  if min_owoc != 'T': magazyn['T'] -= zuzycie
                  if min_owoc != 'P': magazyn['P'] -= zuzycie
    
      print("6.4. Odpowiedzi [kg]:")
      print(f"Malinowo-truskawkowe: {produkcja['M-T']}")
      print(f"Malinowo-porzeczkowe: {produkcja['M-P']}")
      print(f"Truskawkowo-porzeczkowe: {produkcja['T-P']}")
    
    solve_6_4()

Matura Rozszerzona Informatyka Maj 2023

1 pkt
Zadanie 7.1.

Zadanie 7. Gry planszowe

Pewien serwis internetowy prowadzi ranking gier planszowych. Baza serwisu została zapisana w trzech plikach.

Plik gry.txt zawiera informacje o grach planszowych. W każdym wierszu zapisano:

  • id_gry – unikatowy numer gry planszowej
  • nazwa – tytuł gry planszowej
  • kategoria – kategorię, do jakiej została zakwalifikowana gra planszowa; każda gra należy tylko do jednej kategorii.
Przykład (gry.txt):
id_gry    nazwa                       kategoria
1         Wsiasc do Pociagu: Europa   familijna
2         Pandemia                    kooperacyjna
3         Splendor                    familijna
4         Dixit                       familijna
5         Dobble                      familijna

Plik gracze.txt zawiera informacje o graczach. W każdym wierszu zapisano:

  • id_gracza – unikatowy numer gracza
  • imie – imię gracza
  • nazwisko – nazwisko gracza
  • wiek – wiek gracza.
Przykład (gracze.txt):
id_gracza imie          nazwisko      wiek
1         Jozef         Gorecki       29
2         Przemyslaw    Mazurek       68
3         Cezary        Kaczmarczyk   41
4         Kornel        Wysocki       72
5         Eustachy      Gorecki       74

Plik oceny.txt zawiera oceny wystawione grom przez poszczególnych graczy. W każdym wierszu pliku zapisano:

  • id_gry – numer gry planszowej
  • id_gracza – numer gracza
  • stan – zawiera jedną z możliwych wartości: posiada, chce kupic, sprzedal, opisującą, czy użytkownik posiada daną grę, czy ją sprzedał lub czy zamierza ją zakupić
  • ocena – zawiera ocenę gry przez gracza, wyrażoną liczbą całkowitą w zakresie od 0 do 10.
Przykład (oceny.txt):
id_gry    id_gracza   stan          ocena
66        1           posiada       8
72        1           chce kupic    3
79        1           sprzedal      8
43        2           posiada       9

We wszystkich plikach dane w wierszach są rozdzielone znakami tabulacji, a pierwszy wiersz w każdym pliku jest wierszem nagłówkowym. Z wykorzystaniem danych zawartych w podanych plikach oraz dostępnych narzędzi informatycznych, podaj odpowiedzi do zadań. Odpowiedzi zapisz w pliku wyniki7.txt.

Zadanie 7.1. (0–1 pkt)

Podaj tytuł gry, która otrzymała najwięcej ocen.

Odpowiedź: ........................................................................................

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Rozwiązanie w języku SQL (MS Access)

    Aby podać tytuł gry, musimy połączyć tabelę gry z tabelą oceny po polu id_gry.

    Następnie grupujemy dane według tytułu gry (pola nazwa), zliczamy wystąpienia ocen funkcją COUNT(), sortujemy je malejąco i wybieramy pierwszy rekord klauzulą TOP 1.

    SELECT TOP 1 gry.nazwa, COUNT(oceny.id_gry) AS LiczbaOcen
    FROM gry 
    INNER JOIN oceny ON gry.id_gry = oceny.id_gry
    GROUP BY gry.nazwa
    ORDER BY COUNT(oceny.id_gry) DESC;
  • 2

    Krok 2: Alternatywa - Język Python

    W Pythonie najpierw wczytujemy plik oceny.txt i zliczamy za pomocą słownika wystąpienia poszczególnych id_gry. Następnie znajdujemy id_gry z maksymalną liczbą, a na sam koniec wyciągamy nazwę tej gry z pliku gry.txt. To podejście jest szybkie i nie wymaga łączenia dużych struktur w pamięci.

    def solve_7_1():
      liczba_ocen = {}
      
      # Krok 1: Zliczenie ocen dla każdego id_gry
      with open('oceny.txt', 'r') as f:
          next(f) # pomijamy nagłówek
          for line in f:
              parts = line.strip().split('\t')
              if len(parts) >= 4:
                  id_gry = parts[0]
                  liczba_ocen[id_gry] = liczba_ocen.get(id_gry, 0) + 1
                  
      # Krok 2: Znalezienie id_gry z największą liczbą ocen
      najpopularniejsze_id = max(liczba_ocen, key=liczba_ocen.get)
      max_ocen = liczba_ocen[najpopularniejsze_id]
      
      # Krok 3: Odszukanie nazwy gry
      with open('gry.txt', 'r') as f:
          next(f)
          for line in f:
              parts = line.strip().split('\t')
              if parts[0] == najpopularniejsze_id:
                  nazwa_gry = parts[1]
                  print(f"7.1. Tytuł: {nazwa_gry} (Ocen: {max_ocen})")
                  break
    
    solve_7_1()

Matura Rozszerzona Informatyka Maj 2023

2 pkt
Zadanie 7.2.

Zadanie 7.2. (0–2 pkt)

Dla każdej gry z kategorii „imprezowa” podaj średnią jej ocen z dokładnością do dwóch miejsc po przecinku.

Odpowiedź: ........................................................................................

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Rozwiązanie w języku SQL (MS Access)

    Zadanie wymaga połączenia dwóch tabel: gry oraz oceny. Musimy odfiltrować gry imprezowe, zgrupować je po nazwie i wyliczyć średnią (funkcja AVG).

    Zwróć uwagę na wymóg zaokrąglenia! W czystym SQL stosuje się funkcję ROUND(), choć w MS Access można też ustawić formatowanie pola na "Stało-przecinkowy" z 2 miejscami w widoku projektu.

    SELECT gry.nazwa, ROUND(AVG(oceny.ocena), 2) AS SredniaOcen
    FROM gry INNER JOIN oceny ON gry.id_gry = oceny.id_gry
    WHERE gry.kategoria = 'imprezowa'
    GROUP BY gry.nazwa;
  • 2

    Krok 2: Alternatywa - Język Python

    W Pythonie najpierw wczytujemy słownik gier (tylko imprezowych), a następnie agregujemy oceny. Przy wypisywaniu użyjemy formatowania :.2f.

    def solve_7_2():
      # Słownik gier imprezowych: id_gry -> nazwa
      gry_imprezowe = {}
      with open('gry.txt', 'r') as f:
          next(f)
          for line in f:
              parts = line.strip().split('\t')
              if len(parts) >= 3 and parts[2] == 'imprezowa':
                  gry_imprezowe[parts[0]] = parts[1]
                  
      # Słownik do liczenia średniej: id_gry -> [suma_ocen, liczba_ocen]
      statystyki_ocen = {id_gry: [0, 0] for id_gry in gry_imprezowe}
      
      with open('oceny.txt', 'r') as f:
          next(f)
          for line in f:
              parts = line.strip().split('\t')
              if len(parts) >= 4:
                  id_gry = parts[0]
                  ocena = int(parts[3])
                  
                  if id_gry in statystyki_ocen:
                      statystyki_ocen[id_gry][0] += ocena
                      statystyki_ocen[id_gry][1] += 1
                      
      print("7.2. Średnie ocen gier imprezowych:")
      for id_gry, staty in statystyki_ocen.items():
          if staty[1] > 0:
              srednia = staty[0] / staty[1]
              nazwa = gry_imprezowe[id_gry]
              # Formatowanie z kropką zamieniamy na polski przecinek
              srednia_str = f"{srednia:.2f}".replace('.', ',')
              print(f"{nazwa}: {srednia_str}")
    
    solve_7_2()

Matura Rozszerzona Informatyka Maj 2023

2 pkt
Zadanie 7.3.

Zadanie 7.3. (0–2 pkt)

Podaj liczbę graczy, którzy nie posiadają żadnej z ocenianych przez siebie gier (nie mają żadnej gry ze stanem „posiada”), a wystawili co najmniej jedną ocenę.

Odpowiedź: ........................................................................................

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Rozwiązanie w języku SQL (MS Access)

    Zadanie polega na znalezieniu "czystych" graczy w tabeli oceny. Warunek "wystawili co najmniej jedną ocenę" jest spełniony domyślnie, jeśli szukamy id_gracza bezpośrednio w tabeli oceny (bo gracze bez ocen tam nie figurują).

    Musimy wybrać zbiór wszystkich oceniających i odjąć od niego zbiór tych, którzy chociaż raz oznaczyli stan jako "posiada". Robimy to podzapytaniem.

    SELECT COUNT(*) AS Liczba_Graczy
    FROM (
      SELECT DISTINCT id_gracza 
      FROM oceny 
      WHERE id_gracza NOT IN (
          SELECT id_gracza FROM oceny WHERE stan = 'posiada'
      )
    );
  • 2

    Krok 2: Alternatywa - Język Python (Zbiory matematyczne)

    Python pozwala rozwiązać ten problem niezwykle elegancko przy użyciu zbiorów (set). Zbieramy identyfikatory wszystkich graczy, którzy coś ocenili, i wrzucamy do jednego worka. Do drugiego worka wrzucamy tych, którzy użyli statusu "posiada". Następnie wykonujemy operację różnicy zbiorów.

    def solve_7_3():
      wszyscy_oceniajacy = set()
      posiadajacy_gre = set()
      
      with open('oceny.txt', 'r') as f:
          next(f)
          for line in f:
              parts = line.strip().split('\t')
              if len(parts) >= 3:
                  id_gracza = parts[1]
                  stan = parts[2]
                  
                  wszyscy_oceniajacy.add(id_gracza)
                  if stan == 'posiada':
                      posiadajacy_gre.add(id_gracza)
                      
      # Różnica zbiorów: oceniający MINUS posiadający
      wynik_zbior = wszyscy_oceniajacy - posiadajacy_gre
      
      print(f"7.3. Wynik: {len(wynik_zbior)}")
    
    solve_7_3()

Matura Rozszerzona Informatyka Maj 2023

3 pkt
Zadanie 7.4.

Zadanie 7.4. (0–3 pkt)

W ocenianiu gier planszowych uczestniczą osoby w wieku od 10 do 99 lat. Osoby oceniające gry podzielono na trzy kategorie wiekowe: juniorzy (do 19 lat), seniorzy (od 20 do 49 lat) oraz weterani (od 50 lat).

Wykonaj zestawienie, w którym dla każdej kategorii wiekowej podasz największą liczbę ocen wystawionych jednej grze przez użytkowników z tej kategorii wiekowej oraz nazwy gier z tą liczbą ocen.

Jeżeli gier, które otrzymały taką samą największą liczbę ocen od użytkowników z danej kategorii wiekowej, jest więcej niż jedna – podaj tytuły ich wszystkich.

Juniorzy: ........................................................................................

Seniorzy: ........................................................................................

Weterani: ........................................................................................

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Krok 1: Logika zapytania SQL w MS Access (Rozwiązanie w 3 krokach)

    Zrobienie tego zadania w jednym zapytaniu SQL w MS Access byłoby bardzo skomplikowane i nieczytelne. Na maturze najlepiej rozbić to na 3 odrębne, połączone kwerendy.

    • Kwerenda 1 (Grupowanie i zliczanie): Łączymy wszystkie 3 tabele i dodajemy wirtualną kolumnę KategoriaWiekowa (przy użyciu instrukcji IIF). Zliczamy oceny dla każdej gry w każdej kategorii.
      SELECT gry.nazwa, IIf(gracze.wiek<=19, "juniorzy", IIf(gracze.wiek<=49, "seniorzy", "weterani")) AS KatWiekowa, COUNT(oceny.id_gry) AS LiczbaOcen FROM (gry INNER JOIN oceny ON gry.id_gry = oceny.id_gry) INNER JOIN gracze ON oceny.id_gracza = gracze.id_gracza GROUP BY gry.nazwa, IIf(gracze.wiek<=19, "juniorzy", IIf(gracze.wiek<=49, "seniorzy", "weterani"));
      Zapisz tę kwerendę pod nazwą np. Q1_Podsumowanie.

    • Kwerenda 2 (Szukanie maksimum): Z kwerendy Q1_Podsumowanie wybieramy maksymalną wartość LiczbaOcen dla każdej kategorii wiekowej.
      SELECT KatWiekowa, MAX(LiczbaOcen) AS MaxOcen FROM Q1_Podsumowanie GROUP BY KatWiekowa;
      Zapisz tę kwerendę pod nazwą np. Q2_Maksima.

    • Kwerenda 3 (Wynik finałowy): Łączymy Q1_Podsumowanie z Q2_Maksima, aby wyświetlić ostateczne nazwy gier (odrzucamy te, które nie są na szczycie w swojej kategorii).
      SELECT Q1.KatWiekowa, Q1.MaxOcen, Q1.nazwa FROM Q1_Podsumowanie AS Q1 INNER JOIN Q2_Maksima AS Q2 ON Q1.KatWiekowa = Q2.KatWiekowa AND Q1.LiczbaOcen = Q2.MaxOcen;

  • 2

    Krok 2: Alternatywa - Język Python

    Algorytm w języku Python wydaje się tu dużo bardziej "krok po kroku" i bezpieczniejszy do zaprogramowania, jeśli mamy wątpliwości do zaawansowanego SQL.

    def solve_7_4():
      # 1. Przypisanie graczy do kategorii
      kategorie_graczy = {}
      with open('gracze.txt', 'r') as f:
          next(f)
          for line in f:
              parts = line.strip().split('\t')
              if len(parts) >= 4:
                  id_g = parts[0]
                  wiek = int(parts[3])
                  if wiek <= 19: kat = 'juniorzy'
                  elif wiek <= 49: kat = 'seniorzy'
                  else: kat = 'weterani'
                  kategorie_graczy[id_g] = kat
                  
      # 2. Nazwy gier
      nazwy_gier = {}
      with open('gry.txt', 'r') as f:
          next(f)
          for line in f:
              parts = line.strip().split('\t')
              if len(parts) >= 2:
                  nazwy_gier[parts[0]] = parts[1]
                  
      # 3. Zliczanie ocen w kategoriach
      # Słownik zagnieżdżony: kategoria -> {id_gry -> liczba_ocen}
      zliczenia = {'juniorzy': {}, 'seniorzy': {}, 'weterani': {}}
      
      with open('oceny.txt', 'r') as f:
          next(f)
          for line in f:
              parts = line.strip().split('\t')
              if len(parts) >= 2:
                  id_gry = parts[0]
                  id_gracza = parts[1]
                  
                  kat = kategorie_graczy.get(id_gracza)
                  if kat:
                      zliczenia[kat][id_gry] = zliczenia[kat].get(id_gry, 0) + 1
                      
      # 4. Znalezienie i wypisanie maksimów
      print("7.4. Najwyżej oceniane gry w kategoriach wiekowych:")
      for kat in ['juniorzy', 'seniorzy', 'weterani']:
          if not zliczenia[kat]: continue
          
          max_ocen = max(zliczenia[kat].values())
          
          # Wyłapanie wszystkich gier, które mają to maksimum (remisy)
          najlepsze_id = [id_g for id_g, ilosc in zliczenia[kat].items() if ilosc == max_ocen]
          
          tytuly = [nazwy_gier[id_g] for id_g in najlepsze_id]
          print(f"[{kat}] Max ocen: {max_ocen} | Gry: {', '.join(tytuly)}")
    
    solve_7_4()

Matura Rozszerzona Informatyka Maj 2023

2 pkt
Zadanie 7.5.

Zadanie 7.5. (0–2 pkt)

Do wcześniej opisanych tabel bazy danych dołączamy kolejną o nazwie sklep, w której zapisano cennik gier sprzedawanych w pewnym sklepie. Tabela zawiera następujące pola:

  • id_gry – identyfikator gry
  • cena – cena gry
  • promocja – informacja, czy cena jest ceną promocyjną (wartość true – jeśli cena jest promocyjna albo false – kiedy nie jest promocyjna)

Tabele gry i sklep są połączone relacją jeden do wielu.

Sklep
id_gry
cena
promocja
∞ ————— 1
Gry
🔑 id_gry
nazwa
kategoria
Uwaga:
  • gra może mieć dwie ceny (cena w promocji i cena bez promocji), tj. może występować w tabeli sklep dwa razy
  • tabela sklep zawiera tylko identyfikatory gier, które są w ofercie sklepu (nie musi zawierać wszystkich identyfikatorów z tabeli gry).

Zapisz zapytanie SQL, w wyniku którego uzyskamy informację, ile należałoby zapłacić za zakup w tym sklepie po jednej sztuce ze wszystkich gier logicznych (kategoria „logiczna”) dostępnych w cenach promocyjnych.

Miejsce na zapis zapytania:

💡 Pokaż rozwiązanie krok po kroku
  • 1

    Analiza i budowa zapytania SQL

    Zadanie polega na napisaniu jednego, zwięzłego zapytania SQL, które obliczy sumę cen gier spełniających określone kryteria. Rozłóżmy polecenie na czynniki pierwsze:

    • "ile należałoby zapłacić [...] po jednej sztuce": Obliczamy łączny koszt, więc użyjemy funkcji agregującej SUM(cena). Wiemy z uwagi, że gra w promocji występuje w tabeli sklep dokładnie jeden raz z wartością true, więc nie musimy się martwić o duplikaty.

    • Tabele: Potrzebujemy informacji o kategorii (tabela gry) oraz o cenie i promocji (tabela sklep). Łączymy je klauzulą INNER JOIN po kluczu id_gry.

    • "gier logicznych": Dodajemy warunek kategoria = 'logiczna'.

    • "dostępnych w cenach promocyjnych": Dodajemy warunek promocja = true (lub w niektórych dialektach SQL promocja = 1).

  • 2

    Rozwiązanie - Zapytanie SQL

    Zapisujemy wszystkie warunki w jednym bloku:

    SELECT SUM(sklep.cena) AS CalkowityKoszt
    FROM gry INNER JOIN sklep ON gry.id_gry = sklep.id_gry
    WHERE gry.kategoria = 'logiczna' 
    AND sklep.promocja = true;

    *Uwaga: Na maturze dopuszczalny jest również zapis ze złączeniem uwikłanym w sekcji WHERE (tzw. stary standard SQL):

    SELECT SUM(cena)
    FROM gry, sklep
    WHERE gry.id_gry = sklep.id_gry 
    AND kategoria = 'logiczna' 
    AND promocja = true;

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 2023 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