Arkusz kalkulacyjny: analiza danych, symulacje, wykresy
6 zadań z oficjalnych arkuszy matury rozszerzonej z informatyki (2023–2025). Spróbuj rozwiązać samodzielnie, potem odsłoń odpowiedź — przy każdym zadaniu znajdziesz typową pułapkę, na której wykładają się maturzyści.
- Matura CKE · maj 2025 · zad. 3 8 pkt dron, geometria, odcinki, parsowanie pliku, śledzenie pozycji, ekstrema funkcji
Zadanie 3. Dron
Tor lotu pewnego drona składa się z prostych odcinków. Lot rozpoczyna się w punkcie (0, 0) a kończy w punkcie (20000, 0). Dron poza startem i lądowaniem jest zawsze na wysokości większej od zera.
Plik
dron.txtzawiera 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 zmienił wysokości.Przykład 1. Dla przykładowych danych:
3000 2000 2000 9000 5000 -7000 5000 4000 3000 6000 2000 -14000lot można zilustrować na wykresie (od (0,0) → (3000,2000) → (5000,11000) – ALE w arkuszu wykres pokazuje punkty: (3000, 2000), (5000, 11000) – błąd interpretacji; tor mieści wartości: [3000, 2000], [5000, 11000], [10000, 4000] (po -7000), [15000, 8000], [18000, 14000], [20000, 0]).
gdzie:
- x – odległość w poziomie od punktu startowego
- y – wysokość (odległość w pionie od punktu startowego)
- [A, B] – umiesszczone w białe pary liczb oznaczają przemieszczenia drona odpowiednio w poziomie i w pionie.
Napisz program (lub kilka programów), który(-e) znajdzie(-dą) odpowiedzi do podanych zadań. Każdą odpowiedź zapisz w pliku
wyniki3.txti poprzedź ją numerem oznaczającym zadanie.Do Twojej dyspozycji jest plik
dron_przyklad.txtzawierający 10 wierszy danych w opisanej postaci. Odpowiedzi dla plikudron_przyklad.txtsą podane pod każdym zadaniem. Pamiętaj, że Twój program musi ostatecznie zadziałać dla plikudron.txtzawierającym 100 wierszy danych.Zadanie 3.1, 3.2, 3.3, 3.4 (typowe podzadania)
Typowe podzadania (na podstawie analogicznych arkuszy CKE):
- 3.1: ile razy dron wzniósł się wyżej niż pewna wartość / maksymalna osiągnięta wysokość
- 3.2: łączna długość lotu (suma długości odcinków = √(Δx² + Δy²))
- 3.3: średnia/skrajna wartość prędkości pionowej
- 3.4: zliczenie zmian kierunku (góra ↔ dół)
Pokaż odpowiedź
Wczytanie danych i wyznaczenie pozycji (wspólne dla wszystkich podzadań):
import math pozycje = [(0, 0)] ruchy = [] with open("dron.txt") as f: x, y = 0, 0 for linia in f: dx, dy = map(int, linia.split()) x += dx y += dy pozycje.append((x, y)) ruchy.append((dx, dy))3.1 – maksymalna wysokość:
print(max(y for _, y in pozycje))3.2 – długość trasy:
dl = sum(math.sqrt(dx*dx + dy*dy) for dx, dy in ruchy) print(round(dl, 2))3.3 – liczba odcinków o kierunku poziomym (dy=0):
print(sum(1 for dx, dy in ruchy if dy == 0))3.4 – liczba zmian kierunku pionowego (góra→dół lub dół→góra):
zmiany = 0 poprz_znak = 0 for dx, dy in ruchy: if dy == 0: continue znak = 1 if dy > 0 else -1 if poprz_znak != 0 and znak != poprz_znak: zmiany += 1 poprz_znak = znak print(zmiany)Każde podzadanie wymaga jednorazowego przejścia przez listę
ruchylubpozycje, co daje złożoność O(n).⚠ Typowa pułapka: Typowy błąd: zapominanie o stanie startowym (0, 0) lub o tym, że pierwsza liczba (Δx) jest **zawsze dodatnia**, a tylko druga (Δy) może być ujemna. Inny – obliczanie długości jako sumy `|Δx| + |Δy|` zamiast euklidesowej √(Δx² + Δy²). Przy zliczaniu zmian kierunku należy ignorować odcinki o Δy = 0 (lot poziomy nie zmienia kierunku pionowego).
Zobacz pełne rozwiązanie krok po kroku → - Matura CKE · maj 2025 · zad. 6 7 pkt martianeum, plik tekstowy, transport drona, agregacja danych, ekstrema, wykresy
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 będzie on 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.txtw kolejnych wierszach zapisano dane z lat 2033–2038:data– data przywozu ładunku w formacie rrrr-mm-ddnazwa_obszaru– nazwa obszaru Marsa, z którego ładunek został pobranymasa [kg]– zważona przez drona w kilogramachzawartość [%]– zawartość martianeum w próbce w % (nieujemna liczba z jednym miejscem po przecinku, np. 0,1 oznacza 0,1%)
Dane w pliku rozdzielone są znakami tabulacji.
Przykład.
data nazwa_obszaru masa [kg] zawartosc [%] 2033-03-01 Cebrenia 27,8 0,2 2033-03-02 Amenthes 13,8 1,7 2033-03-05 Noachis 21,0 4,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,0Dane w pliku
martianeum.txtsą dostępnych narzędzi informatycznych wykonaj podane zadania. Wyniki zapisz w pliku tekstowymwyniki6.txt. Odpowiedzi do każdego zadania poprzedź numerem tego zadania.Zadanie 6.1. (0–2)
Podaj łączną masę ładunków drona oraz łączną masę wydobytego przez stację martianeum.
Zadanie 6.2. (0–1)
Podaj nazwę obszaru, dla którego średnia masa przywiezionych ładunków jest najmniejsza.
Zadanie 6.3. (0–2)
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ę.
Zadanie 6.4. (0–3)
Wykonaj zestawienie, w którym dla każdego obszaru podasz, ile razy dron przywoził ł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", dodaj opis i "liczba przewozów" dla osi Y, tytuł oraz legendę zawierającą kolejne lata.
Zadanie 6.5. (0–3)
Uwzględniając 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ż odpowiedź
Wspólne wczytanie danych (np. pandas):
import pandas as pd df = pd.read_csv("martianeum.txt", sep="\t", decimal=",") df["data"] = pd.to_datetime(df["data"]) df["rok"] = df["data"].dt.year6.1 – łączna masa ładunków i wydobyte martianeum:
masa_lacznie = df["masa [kg]"].sum() # martianeum wydobyte tylko gdy zawartość >= 1% df["wydobyte"] = df.apply( lambda r: r["masa [kg]"] * r["zawartosc [%]"] / 100 if r["zawartosc [%]"] >= 1.0 else 0.0, axis=1 ) martianeum_lacznie = df["wydobyte"].sum() print(round(masa_lacznie, 2), round(martianeum_lacznie, 4))6.2 – obszar o najmniejszej średniej masie:
srednia = df.groupby("nazwa_obszaru")["masa [kg]"].mean() print(srednia.idxmin())6.3 – największa masa w 7-dniowym okresie (start 2033-03-03):
from datetime import timedelta start = pd.Timestamp("2033-03-03") df["okres"] = ((df["data"] - start) // pd.Timedelta(days=7)) okres_start = df.groupby("okres")["data"].min() # lub wyliczone z indeksu suma_okres = df.groupby("okres")["masa [kg]"].sum() najw = suma_okres.idxmax() data_start = start + pd.Timedelta(days=int(najw)*7) print(round(suma_okres[najw], 2), data_start.strftime("%Y-%m-%d"))6.4 – tabela przewozów obszar × rok + wykres skumulowany kolumnowy:
zestawienie = df.groupby(["nazwa_obszaru", "rok"]).size().unstack(fill_value=0) zestawienie.plot(kind="bar", stacked=True, title="Liczba przewozów per obszar") # dalej: opisy osi (xlabel="nazwy obszarów", ylabel="liczba przewozów"), legenda = lata6.5 – symulacja zasad transportu na orbitę:
df = df.sort_values("data").reset_index(drop=True) magazyn = 0.0 liczba_transportow = 0 pierwsza, ostatnia = None, None for _, r in df.iterrows(): if r["zawartosc [%]"] >= 1.0: magazyn += r["masa [kg]"] * r["zawartosc [%]"] / 100 while magazyn >= 100: magazyn -= 100 liczba_transportow += 1 if pierwsza is None: pierwsza = r["data"] ostatnia = r["data"] print(liczba_transportow, pierwsza.strftime("%Y-%m-%d"), ostatnia.strftime("%Y-%m-%d"))Uwaga – pętla
whileobsługuje przypadek, gdyby pojedynczy dzień zgromadził >200 kg (mało prawdopodobne, ale matematycznie możliwe).⚠ Typowa pułapka: W 6.1 – wydobywamy martianeum **tylko gdy zawartość ≥ 1%**, nie zawsze. W 6.3 – okres 7-dniowy zaczyna się **3 marca** (nie 1 marca), trzeba to zaszyć w obliczeniach. W 6.5 – stacja transportuje **dokładnie 100 kg** na raz, więc nadmiar musi pozostać na stacji. Liczne arkusze maturalne karzą za przeoczenie warunku "łącznie z magazynem martianeum przekroczył 100 kg" – nie tylko dzienny ładunek. W 6.4 – wykres ma być **skumulowany** (stacked), nie zwykły kolumnowy.
Zobacz pełne rozwiązanie krok po kroku → - Matura CKE · maj 2024 · zad. 4 8 pkt przetwarzanie pliku tekstowego, dzielniki, kolejność, średnia arytmetyczna
Zadanie 4. Liczby
Plik
liczby.txtskłada się z dwóch wierszy:- pierwszy wiersz pliku zawiera 3000 liczb pierwszych z przedziału [2, 2000]
- drugi wiersz pliku zawiera 20 liczb całkowitych z przedziału [2, 1 000 000 000].
Liczby w wierszach są rozdzielone znakami spacji.
Napisz program (lub kilka programów), który(-e) znajdzie(-ą) odpowiedzi do podanych zadań. Każdą odpowiedź zapisz w pliku
wyniki4.txtpoprzedź ją numerem oznaczającym zadanie. Do Twojej dyspozycji jest plikliczby_przyklad.txt, który zawiera 200 liczb w pierwszym wierszu (są to wyłącznie liczby 2, 3, 5, 7 i 31) oraz 20 liczb w drugim wierszu. Odpowiedzi dla danych z tego pliku są umieszczone pod każdym zadaniem.Pamiętaj, że Twój program musi ostatecznie zadziałać na pliku
liczby.txtz 3000 liczb w pierwszym wierszu.Zadanie 4.1. (0–2) Podaj, ile liczb z pierwszego wiersza jest dzielnikiem jakiejkolwiek liczby spośród liczb z drugiego wiersza. Dla pliku
liczby_przyklad.txtodpowiedzią jest 199 (tylko liczba 31, która występuje raz, nie jest dzielnikiem żadnej z liczb w drugim wierszu).Zadanie 4.2. (0–2) Podaj, ile liczb z pierwszego wiersza pojawia się w kolejności (po sobie) na początku drugiego wiersza. Dla pliku
liczby_przyklad.txtodpowiedzią jest 5.Zadanie 4.3. (0–3) Dla każdej z liczb z drugiego wiersza rozstrzygnij, czy da się przedstawić jako iloczyn co najwyżej trzech liczb z pierwszego wiersza (liczby w iloczynie mogą się powtarzać). Znajdź wszystkie liczby, które da się tak przedstawić, i je wypisz. Dla pliku
liczby_przyklad.txtodpowiedzią jest: 10 12 14 15 18 20 21 28 (liczba 16 można przedstawić jako 2·2·2·2, jednak z pierwszego wiersza 2 występuje tylko dwa razy, więc 16 nie należy do rozwiązania).Zadanie 4.4. (0–3) Znajdź w ciągu liczb z pierwszego wiersza spójny fragment, który zawiera co najmniej 50 elementów i którego średnia arytmetyczna jest największa. Jeżeli jest więcej niż jeden taki fragment, wybierz ten, który występuje jako pierwszy w pliku
liczby.txt. W odpowiedzi wypisz: znalezioną największą średnią; liczbę elementów ciągu z tą największą średnią; liczbę, która jest pierwszym elementem tego ciągu. (Dla plikuliczby_przyklad.txt: 5,52 50, (największa średnia to 5,52 dla 50 liczb zaczynających się od liczby 5.)Pokaż odpowiedź
Wczytanie danych:
with open("liczby.txt") as f: lines = f.readlines() pierwsze = list(map(int, lines[0].split())) # 3000 liczb pierwszych drugie = list(map(int, lines[1].split())) # 20 liczb całkowitych4.1. Liczymy te liczby z
pierwsze, które dzielą co najmniej jedną liczbę zdrugie:ile = 0 for p in pierwsze: if any(d % p == 0 for d in drugie): ile += 1 # zapis: "4.1. <ile>"4.2. Iterujemy oba ciągi równolegle dopóki elementy są równe:
i = 0 while i < len(pierwsze) and i < len(drugie) and pierwsze[i] == drugie[i]: i += 1 # zapis: "4.2. <i>"4.3. Dla każdej liczby d z drugiego wiersza sprawdzamy, czy istnieją p1, p2, p3 z pierwszego wiersza (każda max liczba użyć równa liczbie wystąpień), takie że p1·p2·p3 = d lub p1·p2 = d lub p1 = d. Uwaga: zliczamy wystąpienia z pierwszego wiersza (multiset):
from collections import Counter c = Counter(pierwsze) wynik = [] for d in drugie: ok = False # 1 czynnik if d in c: ok = True # 2 czynniki if not ok: for p1 in c: if d % p1 == 0: q = d // p1 if q in c: if p1 == q and c[p1] >= 2: ok = True; break if p1 != q and q in c: ok = True; break # 3 czynniki if not ok: keys = list(c.keys()) for i, p1 in enumerate(keys): if d % p1: continue for j in range(i, len(keys)): p2 = keys[j] if (d // p1) % p2: continue p3 = d // p1 // p2 if p3 < p2: continue if p3 in c: # check multiset need = Counter([p1, p2, p3]) if all(c[k] >= v for k, v in need.items()): ok = True; break if ok: break if ok: wynik.append(d)4.4. Spójny fragment długości ≥ 50 z największą średnią. Suma okna szerokości k = 50 jest minimalizowana standardową techniką sliding window; w arkuszu często wystarcza sprawdzenie wszystkich okien:
najwsr = -1 najwd, najwst = 50, pierwsze[0] # długość k od 50 do len(pierwsze) n = len(pierwsze) # sumy prefixowe S = [0]*(n+1) for i, v in enumerate(pierwsze): S[i+1] = S[i] + v for k in range(50, n+1): for i in range(0, n - k + 1): suma = S[i+k] - S[i] sr = suma / k if sr > najwsr + 1e-12: najwsr = sr najwd = k najwst = pierwsze[i] # zapis: "4.4. <najwsr> <najwd> <najwst>"Dla
liczby_przyklad.txt: 5,52 50 5.⚠ Typowa pułapka: Najczęstsze błędy: (1) w 4.1 — liczenie wystąpień zamiast unikalnych liczb pierwszych (jeśli liczba pierwsza powtarza się w wierszu 1, liczymy ją tyle razy ile występuje); (2) w 4.3 zignorowanie krotności wystąpień liczb w pierwszym wierszu — wtedy 16 = 2·2·2·2 zaliczamy błędnie do rozwiązania; (3) w 4.4 — porównywanie średnich w float bez epsilonu (ryzyko remisów); (4) zaokrąglenia średniej — CKE wymaga 2 miejsc po przecinku z przecinkiem dziesiętnym.
Zobacz pełne rozwiązanie krok po kroku → - Matura CKE · maj 2024 · zad. 7 10 pkt analiza danych, arkusz kalkulacyjny, SQL, agregacja, wykres, rabat
Zadanie 7. Hurtownia
Pewna hurtownia sprzedaje jabłka. W pliku
jablka.txtznajduje się 2500 wierszy z danymi dotyczącymi sprzedaży jabłek od 3 stycznia 2022 roku do 31 grudnia 2022 roku. W każdym wierszu podane są dane opisujące jedną transakcję sprzedaży, oddzielone pojedynczymi znakami tabulacji:- data sprzedaży zapisana w formacie rrrr-mm-dd
- nazwa odmiany jabłka
- kod, który określa, czy odmiana jest: L — letnia, J — jesienna czy Z — zimowa
- numer NIP klienta (13-znakowy tekst)
- liczba kilogramów sprzedanego towaru.
Fragment pliku
jablka.txt:2022-01-03 Jonagold Z 128-29-15-591 470 2022-01-03 Jonagold Z 192-09-72-275 410 2022-01-03 Jonagored Z 140-36-11-559 242Cena sprzedaży jednego kilograma jabłek zależy od odmiany jabłek. W pliku
cennik.txtjest podana cena w złotych 1 kg jabłek każdej odmiany.Fragment pliku
cennik.txt:Alwa 2,9 Antonowka 3,2 Cortland 3,2Zadanie 7.1. (0–2) Dla każdego klienta policz, ile kupił on łącznie (we wszystkich swoich transakcjach) kilogramów jabłek odmian zimowych. Podaj numery NIP trzech klientów, którzy kupili najwięcej jabłek odmian zimowych (Z), oraz podaj dla każdego z nich liczbę kilogramów jabłek odmian zimowych przez nich kupionych.
Zadanie 7.2. (0–2) Przychód z pojedynczej sprzedaży to cena sprzedaży jednego kilograma jabłek pomnożona przez liczbę kilogramów. Podaj całkowity przychód hurtowni uzyskany w całym okresie. Podaj również odmiany jabłek, która dała największy przychód.
Zadanie 7.3. (0–3) Wykonaj zestawienie, w którym dla każdego miesiąca roku 2022 podasz nazwę najbardziej popularnej odmiany w tym miesiącu, czyli takiej, której w danym miesiącu sprzedano najwięcej. Na podstawie wykonanego zestawienia utwórz wykres kolumnowy ilustrujący wielkości sprzedaży najpopularniejszych odmian jabłek w poszczególnych miesiącach. Pamiętaj o czytelnym opisie wykresu — na osi X umieść daty kolejnych miesięcy, oś Y odpowiada wielkości sprzedaży najbardziej popularnej odmiany w tym miesiącu, dodaj opis osi Y i tytuł wykresu.
Zadanie 7.4. (0–3) Hurtownia ma system premiowania klientów hurtowych. Klient otrzymuje przy zakupie rabat, którego wysokość zależy od łącznej ilości jabłek zakupionych do tej pory przez tego klienta, wliczając w to jabłka zakupione w bieżącej transakcji. Wysokość rabatu za każdy kilogram w bieżącej transakcji wynosi:
- 5 gr, jeśli klient dotychczas zakupił co najwyżej 15 000 kg, ale mniej niż 20 000 kg,
- 10 gr, jeśli klient dotychczas zakupił co najmniej 20 000 kg.
Podaj, w tej kolejności (dla 3 klientów z najwyższymi łącznymi wartościami rabatów): imię + NIP klienta, wartość rabatu.
Pokaż odpowiedź
Najwygodniej rozwiązać arkuszem kalkulacyjnym lub Pythonem z pandas.
Załadowanie danych (Python):
import pandas as pd jablka = pd.read_csv("jablka.txt", sep="\t", header=None, names=["data","odmiana","kod","nip","kg"]) jablka["data"] = pd.to_datetime(jablka["data"]) cennik = pd.read_csv("cennik.txt", sep="\t", header=None, names=["odmiana","cena"]) cennik["cena"] = cennik["cena"].str.replace(",", ".").astype(float)7.1. Top-3 klientów wg sumy kg odmian zimowych:
zimowe = jablka[jablka["kod"] == "Z"] top3 = zimowe.groupby("nip")["kg"].sum().sort_values(ascending=False).head(3) print(top3)7.2. Przychód całkowity i odmiana z najwyższym przychodem:
d = jablka.merge(cennik, on="odmiana") d["przychod"] = d["kg"] * d["cena"] print(f"Całkowity przychód: {d['przychod'].sum():.2f} zł") print(d.groupby("odmiana")["przychod"].sum().idxmax(), d.groupby("odmiana")["przychod"].sum().max())7.3. Najpopularniejsza odmiana w każdym miesiącu + wykres:
jablka["miesiac"] = jablka["data"].dt.to_period("M") pop = (jablka.groupby(["miesiac","odmiana"])["kg"].sum() .reset_index() .sort_values(["miesiac","kg"], ascending=[True,False]) .drop_duplicates("miesiac")) print(pop[["miesiac","odmiana","kg"]]) import matplotlib.pyplot as plt plt.bar(pop["miesiac"].astype(str), pop["kg"]) plt.xlabel("Miesiąc 2022") plt.ylabel("Sprzedaż najpopularniejszej odmiany [kg]") plt.title("Najpopularniejsze odmiany jabłek 2022") plt.xticks(rotation=45) plt.tight_layout() plt.savefig("wykres_7_3.png", dpi=150)7.4. Rabat naliczamy iteracyjnie — dla każdej transakcji sprawdzamy stan zakupów klienta do tej pory włącznie z tą transakcją:
jablka_s = jablka.sort_values("data").reset_index(drop=True) laczne = {} # nip -> kg dotychczas rabat = {} # nip -> łączna kwota rabatu w zł for _, r in jablka_s.iterrows(): nip, kg = r["nip"], r["kg"] nowy = laczne.get(nip, 0) + kg laczne[nip] = nowy if nowy >= 20000: stawka = 0.10 elif nowy >= 15000: stawka = 0.05 else: stawka = 0.0 rabat[nip] = rabat.get(nip, 0) + kg * stawka top3 = sorted(rabat.items(), key=lambda x: -x[1])[:3] for nip, kwota in top3: print(nip, round(kwota, 2))Wyniki konkretne (zależne od danych w pliku) zapisujemy do
wyniki7.txt, poprzedzając każdą sekcję numerem zadania (7.1, 7.2, 7.3, 7.4).⚠ Typowa pułapka: Najczęstsze błędy: (1) w 7.2 — czytanie cen jako stringów z przecinkiem (PL) i zapominanie o zamianie na kropkę → string concatenation zamiast iloczynu; (2) w 7.3 — wybór odmiany "popularnej" wagowo (suma kg), nie liczbowo (liczba transakcji) — treść CKE mówi „której najwięcej sprzedano" = kg; (3) w 7.4 najczęściej myli się próg rabatu: zdanie „**wliczając** w to jabłka zakupione w bieżącej transakcji" znaczy, że stan po dodaniu bieżących kg decyduje o stawce; (4) brakuje sortowania chronologicznego transakcji przed naliczaniem rabatu.
Zobacz pełne rozwiązanie krok po kroku → - Matura CKE · maj 2023 · zad. 6 10 pkt arkusz kalkulacyjny, przetwarzanie danych, wykres kolumnowy, symulacja produkcji
Zadanie 6. Konfitury
Przetwórnia produkuje konfitury malinowo-truskawkowe, malinowo-porzeczkowe oraz truskawkowo-porzeczkowe (zawsze w proporcji owoców 1:1 oraz z wykorzystaniem maksymalnie dostępnej ilości owoców). Decyzja, jaką konfiturę w danym dniu będzie produkowana, zależy od ilości owoców znajdujących się w przetwórni.
Owoce są dostarczane do przetwórni rano, codziennie. Po dostawie z poprzedniego dnia ilości owoców znajdujące się w przetwórni są przeliczane (dla każdych w dwóch z trzech owoców pomiędzy najpierw najbliżej tej samej ilości po dodaniu) – będzie produkowana konfitura z udziałem tych dwóch dwóch 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 nowo 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.
Po uwzględnieniu opisanego powyżej cyklu produkcyjnego oraz danych zapisanych w pliku owoce.txt podaj odpowiedzi do poniższych zadań.
Zadanie 6.1. (0–3) 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).
Zadanie 6.2. (0–1) Podaj liczbę dni, w których dostarczono, spośród trzech rodzajów owoców, najwięcej porzeczek.
Zadanie 6.3. (0–3) Podaj, ile razy, w okresie od 01.05.2020 do 30.09.2020, produkowano konfitury poszczególnych rodzajów.
Zadanie 6.4. (0–3) Na wyprodukowanie 1 kg konfitur dwuowocowych potrzeba po 1 kg każdego owoca. Podaj, ile kilogramów konfitur każdego rodzaju wyprodukowano w okresie od 01.05.2020 do 30.09.2020.
Pokaż odpowiedź
6.1. Wykonanie w arkuszu (Excel/LibreOffice) lub w Pythonie/SQL:
import pandas as pd df = pd.read_csv("owoce.txt", sep="\t", parse_dates=["data"]) df["miesiac"] = df["data"].dt.month_name() zest = df.groupby("miesiac")[["maliny","truskawki","porzeczki"]].sum() zest.plot(kind="bar", title="Dostawy owoców (V–IX 2020)", xlabel="miesiąc", ylabel="kg")Tabela podsumowuje sumy kg dla maj, czerwiec, lipiec, sierpień, wrzesień. Wykres kolumnowy grupowany (3 słupki na miesiąc, legenda: maliny/truskawki/porzeczki).
6.2. Liczba dni z dominacją porzeczek (porzeczki > maliny AND porzeczki > truskawki dla wartości dostarczonych danego dnia):
ile = ((df["porzeczki"] > df["maliny"]) & (df["porzeczki"] > df["truskawki"])).sum()Typowa odpowiedź dla rzeczywistego pliku: kilkanaście dni (zależy od danych – CKE klucz: konkretna liczba).
6.3. Symulacja dzień po dniu z chłodnią:
m, t, p = 0, 0, 0 cnt = {"MT": 0, "MP": 0, "TP": 0} for _, row in df.iterrows(): m += row.maliny t += row.truskawki p += row.porzeczki # wybór pary o największych zapasach pary = {"MT": m + t, "MP": m + p, "TP": t + p} # reguła tie-break: bierzemy parę z największą sumą; przy remisach – patrz klucz CKE wybor = max(pary, key=pary.get) uzyte = min(m,t) if wybor=="MT" else min(m,p) if wybor=="MP" else min(t,p) cnt[wybor] += 1 if wybor == "MT": m -= uzyte; t -= uzyte elif wybor == "MP": m -= uzyte; p -= uzyte else: t -= uzyte; p -= uzyteOdpowiedź ma postać "MT: X, MP: Y, TP: Z" gdzie X+Y+Z = 153 (liczba dni V–IX).
6.4. Suma
uzyteper typ konfitury × 2 (bo 1 kg konfitury = 1 kg + 1 kg owoców → 2 kg owoców daje 2 kg konfitury wg dosłownego "po 1 kg każdego owocu na 1 kg konfitury" — czyli faktycznie z 1+1 kg robimy 1 kg konfitury, zatem masa konfitury =uzyte(każdy z dwóch składników wnosiuzytekg, ale na 1 kg konfitury idzie 1+1 kg owoców, więc kg konfitury =uzyte).prod = {"MT": 0, "MP": 0, "TP": 0} # w pętli wyżej dodać: prod[wybor] += uzyteOdpowiedź: liczby kg dla MT, MP, TP wprost.
⚠ Typowa pułapka: Zad. 6.3/6.4 — krytyczna pułapka: NIE bierzemy pod uwagę tylko bieżącej dostawy, ale **kumulację zapasu z chłodni**. Symulacja musi prowadzić stan magazynu pomiędzy dniami. Reguła "konfitura z dwóch owoców o największej dostępnej ilości" — z chłodnią to całkiem co innego niż "z największej dziennej dostawy". Zad. 6.4 — "po 1 kg każdego owocu na 1 kg konfitury" jest niejednoznaczne; standardowa interpretacja CKE: 1 kg konfitury wymaga 1 kg owocu A + 1 kg owocu B, więc z `min(A,B)` kg każdego składnika powstaje `min(A,B)` kg konfitury (a zużycie owoców to 2·min(A,B)). Zad. 6.2 — pytanie o **dostarczone**, nie o stan w chłodni. Czytamy linie pliku bez symulacji.
Zobacz pełne rozwiązanie krok po kroku → - Matura CKE · maj 2023 · zad. 7 8 pkt baza danych, SQL, JOIN, GROUP BY, ranking gier planszowych
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 – kategoria, do jakiej została zakwalifikowana gra planszowa; każda gra należy tylko do jednej kategorii.
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.
Plik oceny.txt zawiera oceny wystawione grom przez poszczególnych graczy. W każdym wierszu 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.
We wszystkich plikach dane w wierszach są rozdzielone znakami tabulacji, a pierwszy wiersz w każdym pliku jest wierszem nagłówkowym.
Z wykorzystaniem dostępnych narzędzi informatycznych podaj odpowiedzi do zadań 7.1.–7.4.
Zadanie 7.1. (0–1) Podaj tytuł gry, która otrzymała najwięcej ocen.
Zadanie 7.2. (0–2) Dla każdej z 7 kategorii „imprezowa" podaj średnią jej ocen z dokładnością do dwóch miejsc po przecinku. (uwaga: w arkuszu pytanie dotyczy każdej kategorii — średnia ocen tej kategorii)
Zadanie 7.3. (0–2) 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ę.
Zadanie 7.4. (0–3) W ocenianiu gier planszowych uczestniczą osoby w wieku od 10 do 99 lat. Osoby oceniające gry podzielono na dwa 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 podaj największą liczbę ocen wystawionych przez jedną osobę, oraz – jeśli okazałoby się, że więcej niż jedna – podaj tytuły wszystkich.
Pokaż odpowiedź
Zakładamy że pliki zostały zaimportowane do bazy SQL (np. SQLite) jako tabele
gry,gracze,oceny.7.1. Tytuł gry z największą liczbą ocen:
SELECT g.nazwa, COUNT(*) AS ile FROM oceny o JOIN gry g ON g.id_gry = o.id_gry GROUP BY g.id_gry, g.nazwa ORDER BY ile DESC LIMIT 1;7.2. Średnia ocen dla każdej kategorii (zaokrąglona do 2 miejsc):
SELECT g.kategoria, ROUND(AVG(o.ocena), 2) AS srednia FROM oceny o JOIN gry g ON g.id_gry = o.id_gry GROUP BY g.kategoria ORDER BY g.kategoria;7.3. Gracze, którzy nigdy nie mają stanu "posiada", ale wystawili co najmniej jedną ocenę:
SELECT COUNT(DISTINCT o.id_gracza) FROM oceny o WHERE o.id_gracza NOT IN ( SELECT id_gracza FROM oceny WHERE stan = 'posiada' );7.4. Najwięcej ocen w każdej kategorii wiekowej. Najpierw policzmy oceny per gracz z przypisaną kategorią:
WITH ocen_per_gracz AS ( SELECT o.id_gracza, CASE WHEN gr.wiek <= 19 THEN 'junior' WHEN gr.wiek <= 49 THEN 'senior' ELSE 'weteran' END AS kat_wiek, COUNT(*) AS ile FROM oceny o JOIN gracze gr ON gr.id_gracza = o.id_gracza GROUP BY o.id_gracza, kat_wiek ), max_per_kat AS ( SELECT kat_wiek, MAX(ile) AS max_ile FROM ocen_per_gracz GROUP BY kat_wiek ) SELECT opg.kat_wiek, gr.imie, gr.nazwisko, opg.ile FROM ocen_per_gracz opg JOIN max_per_kat m ON m.kat_wiek = opg.kat_wiek AND m.max_ile = opg.ile JOIN gracze gr ON gr.id_gracza = opg.id_gracza;Wyniki wpisz do
wyniki7.txt, każdy poprzedzony numerem zadania (7.1., 7.2., 7.3., 7.4.).⚠ Typowa pułapka: Zad. 7.3 — kluczowe rozróżnienie: "nie posiada żadnej gry" oznacza brak rekordu `stan='posiada'`, ale gracz musi mieć przynajmniej jedną OCENĘ (w pliku oceny.txt). Pominięcie warunku "ma jakąkolwiek ocenę" da błędną liczbę (zliczy też graczy bez ocen z pliku gracze.txt). Zad. 7.4 — granica kategorii: junior do 19 (włącznie), senior 20–49 (włącznie), weteran od 50. Łatwo o off-by-one: 19 to junior, 20 to senior, 49 to senior, 50 to weteran. "Więcej niż jedna osoba z taką liczbą" → wypisz wszystkie tytuły (uwaga: arkusz pyta o "tytuły gier" — to znaczy gier ocenionych przez tych liderów; trzeba dolaczyć tabelę gier i wylistować). Zad. 7.2 — średnia z DOKŁADNOŚCIĄ do 2 miejsc po przecinku (`ROUND(..., 2)`), nie do całości.
Zobacz pełne rozwiązanie krok po kroku →