{"id":"informatyka-2015-maj-matura-rozszerzona/zad/6.3","paper_id":"informatyka-2015-maj-matura-rozszerzona","number":"6.3","points":3,"ptype":"open","subject":"informatyka","category":"matura","year":2015,"month":"maj","level":"rozszerzona","text":"Kontekst - patrz zadanie 6.1.\n\nKlasyfikacja generalna w danym sezonie jest tworzona na podstawie sumy punktów uzyskanych przez kierowców w wyścigach rozegranych w tym sezonie.\n\nUtwórz zestawienie zawierające nazwiska i imiona kierowców - zwycięzców klasyfikacji generalnej w sezonach 2000, 2006 i 2012 wraz z liczbami punktów przez nich uzyskanymi.","answer":null,"answer_text":null,"solution":"## Poprawna odpowiedź\n\n| Imię | Nazwisko | Sezon | Suma Punktów |\n| **Michael** | **Schumacher** | **2000** | **108** |\n| **Fernando** | **Alonso** | **2006** | **134** |\n| **Sebastian** | **Vettel** | **2012** | **281** |\n\n## Sposób 1 - SQL (GROUP BY z agregacją punktów per kierowca per sezon)\n\nKluczowa idea: sumujemy punkty per kierowca w każdym z trzech sezonów, a następnie wybieramy maksymalny wynik dla każdego sezonu.\n\n```sql\nSELECT k.Imie, k.Nazwisko, w.Rok AS Sezon, SUM(wn.Punkty) AS Suma\nFROM Wyniki wn\nINNER JOIN Wyscigi w ON wn.Id_wyscigu = w.Id_wyscigu\nINNER JOIN Kierowcy k ON wn.Id_kierowcy = k.Id_kierowcy\nWHERE w.Rok IN (2000, 2006, 2012)\nGROUP BY k.Id_kierowcy, w.Rok\nHAVING SUM(wn.Punkty) = (\nSELECT MAX(s.S) FROM (\nSELECT SUM(wn2.Punkty) AS S\nFROM Wyniki wn2 INNER JOIN Wyscigi w2 ON wn2.Id_wyscigu = w2.Id_wyscigu\nWHERE w2.Rok = w.Rok\nGROUP BY wn2.Id_kierowcy\n) s\n)\nORDER BY w.Rok;\n\n**Wynik:**\nMichael Schumacher 2000 108\nFernando Alonso 2006 134\nSebastian Vettel 2012 281\n\n## Sposób 2 - Python (pandas, prostszy zapis)\n\n```python\nimport pandas as pd\n\nkierowcy = pd.read_csv('Kierowcy.txt', sep=';', header=None,\nnames=['Id_k', 'Nazwisko', 'Imie', 'Kraj'])\nwyscigi = pd.read_csv('Wyscigi.txt', sep=';', header=None,\nnames=['Id_w', 'Rok', 'GrandPrix'])\nwyniki = pd.read_csv('Wyniki.txt', sep=';', header=None,\nnames=['Id_k', 'Punkty', 'Id_w'])\n\n# JOIN wszystkie 3 tabele\ndf = wyniki.merge(wyscigi, on='Id_w').merge(kierowcy, on='Id_k')\n\nfor sezon in [2000, 2006, 2012]:\ns = df[df['Rok'] == sezon].groupby(['Imie', 'Nazwisko'])['Punkty'].sum()\nnajlepszy = s.idxmax()\nprint(f\"{najlepszy[0]} {najlepszy[1]} | {sezon} | {s.max()}\")\n\n# Michael Schumacher | 2000 | 108\n# Fernando Alonso | 2006 | 134\n# Sebastian Vettel | 2012 | 281\n\n## Sposób 3 - arkusz kalkulacyjny (tabela przestawna)\n\n**Krok 1:** Wczytaj 3 pliki jako tabele. Połącz JOIN-em (PowerQuery / WYSZUKAJ.PIONOWO) Wyniki + Wyscigi po Id_w, dodaj kolumnę Rok.\n\n**Krok 2:** Dodaj nazwisko i imię kierowcy przez WYSZUKAJ.PIONOWO po Id_k.\n\n**Krok 3:** Tabela przestawna:\n- Filtr: Rok IN {2000, 2006, 2012}\n- Wiersze: Imie + Nazwisko\n- Kolumny: Rok\n- Wartości: SUMA(Punkty)\n\n**Krok 4:** Dla każdej kolumny (sezonu) odczytaj kierowcę z najwyższą sumą.\n\n## Reference informatyczny - agregacja warunkowa\n\n> Reference - SQL GROUP BY + HAVING + podzapytanie skorelowane:\n> - **GROUP BY a, b** - agregacja po dwóch kolumnach (kierowca i sezon).\n> - **SUM(Punkty)** - suma punktów w grupie.\n> - **HAVING SUM = (SELECT MAX )** - filtruje tylko zwycięzców.\n> - **Podzapytanie skorelowane** - `w.Rok = w2.Rok` wiąże podzapytanie z zewnętrznym wierszem.\n> Alternatywa: WINDOW FUNCTION `RANK() OVER (PARTITION BY Rok ORDER BY SUM(Punkty) DESC)`.\n\n## Schemat oceniania CKE\n\n> Klucz CKE (zadanie 6.3, max 3 pkt):\n> - **3 pkt** - poprawne odpowiedzi we wszystkich trzech wersach (3 zwycięzcy z 3 sezonów + sumy punktów).\n> - **2 pkt** - poprawne odpowiedzi tylko w dwóch wersach.\n> - **1 pkt** - poprawna odpowiedź tylko w jednym wersie.\n> - **0 pkt** - odpowiedź niepełna lub błędna albo brak.\n\n## Typowe pułapki\n\n- **Klasyfikacja generalna ≠ jeden wyścig** - to SUMA punktów w danym sezonie, nie max z jednego wyścigu.\n- **Każdy sezon ma swojego zwycięzcę** - trzeba wykonać agregację per (kierowca, sezon), a nie globalnie.\n- **JOIN 3 tabel** - typowa pułapka: zapomnienie o jednym JOIN powoduje iloczyn kartezjański i błędne sumy.\n- **Polskie imiona** - uważaj na pisownię (Michael, Fernando, Sebastian - zachowaj oryginał z pliku).\n- **Liczba punktów dokładna** - klucz CKE wymaga konkretnych wartości 108 / 134 / 281.\n\n## Złożoność obliczeniowa\n\n- 3 JOIN-y po kluczach: O(N log N) z indeksami lub O(N · M · K) bez.\n- GROUP BY z hash: O(N).\n- Podzapytanie skorelowane bez optymalizacji: O(N · G) gdzie G = liczba grup.\n- **Całkowita: O(N log N)** dla rozsądnej implementacji.","image":null,"solution_image":null,"topics":null,"page_from":null,"source":"maturazai","answer_source":null,"answer_text_source":null,"solution_source":"maturazai","text_source":"maturazai","source_label":"Informatyka · Matura · maj 2015 (rozszerzona)","subject_label":"Informatyka","category_label":"Matura","text_html":"<p>Kontekst - patrz zadanie 6.1.</p>\n<p>Klasyfikacja generalna w danym sezonie jest tworzona na podstawie sumy punktów uzyskanych przez kierowców w wyścigach rozegranych w tym sezonie.</p>\n<p>Utwórz zestawienie zawierające nazwiska i imiona kierowców - zwycięzców klasyfikacji generalnej w sezonach 2000, 2006 i 2012 wraz z liczbami punktów przez nich uzyskanymi.</p>","solutions":[{"source":"maturazai","label":"maturazai.pl (AI)","kind":"text","html":"<h4>Poprawna odpowiedź</h4>\n<p>| Imię | Nazwisko | Sezon | Suma Punktów |<br>| <strong>Michael</strong> | <strong>Schumacher</strong> | <strong>2000</strong> | <strong>108</strong> |<br>| <strong>Fernando</strong> | <strong>Alonso</strong> | <strong>2006</strong> | <strong>134</strong> |<br>| <strong>Sebastian</strong> | <strong>Vettel</strong> | <strong>2012</strong> | <strong>281</strong> |</p>\n<h4>Sposób 1 - SQL (GROUP BY z agregacją punktów per kierowca per sezon)</h4>\n<p>Kluczowa idea: sumujemy punkty per kierowca w każdym z trzech sezonów, a następnie wybieramy maksymalny wynik dla każdego sezonu.</p>\n<p>```sql<br>SELECT k.Imie, k.Nazwisko, w.Rok AS Sezon, SUM(wn.Punkty) AS Suma<br>FROM Wyniki wn<br>INNER JOIN Wyscigi w ON wn.Id_wyscigu = w.Id_wyscigu<br>INNER JOIN Kierowcy k ON wn.Id_kierowcy = k.Id_kierowcy<br>WHERE w.Rok IN (2000, 2006, 2012)<br>GROUP BY k.Id_kierowcy, w.Rok<br>HAVING SUM(wn.Punkty) = (<br>SELECT MAX(s.S) FROM (<br>SELECT SUM(wn2.Punkty) AS S<br>FROM Wyniki wn2 INNER JOIN Wyscigi w2 ON wn2.Id_wyscigu = w2.Id_wyscigu<br>WHERE w2.Rok = w.Rok<br>GROUP BY wn2.Id_kierowcy<br>) s<br>)<br>ORDER BY w.Rok;</p>\n<p><strong>Wynik:</strong><br>Michael Schumacher 2000 108<br>Fernando Alonso 2006 134<br>Sebastian Vettel 2012 281</p>\n<h4>Sposób 2 - Python (pandas, prostszy zapis)</h4>\n<p>```python<br>import pandas as pd</p>\n<p>kierowcy = pd.read_csv(&#x27;Kierowcy.txt&#x27;, sep=&#x27;;&#x27;, header=None,<br>names=[&#x27;Id_k&#x27;, &#x27;Nazwisko&#x27;, &#x27;Imie&#x27;, &#x27;Kraj&#x27;])<br>wyscigi = pd.read_csv(&#x27;Wyscigi.txt&#x27;, sep=&#x27;;&#x27;, header=None,<br>names=[&#x27;Id_w&#x27;, &#x27;Rok&#x27;, &#x27;GrandPrix&#x27;])<br>wyniki = pd.read_csv(&#x27;Wyniki.txt&#x27;, sep=&#x27;;&#x27;, header=None,<br>names=[&#x27;Id_k&#x27;, &#x27;Punkty&#x27;, &#x27;Id_w&#x27;])</p>\n<h3>JOIN wszystkie 3 tabele</h3>\n<p>df = wyniki.merge(wyscigi, on=&#x27;Id_w&#x27;).merge(kierowcy, on=&#x27;Id_k&#x27;)</p>\n<p>for sezon in [2000, 2006, 2012]:<br>s = df[df[&#x27;Rok&#x27;] == sezon].groupby([&#x27;Imie&#x27;, &#x27;Nazwisko&#x27;])[&#x27;Punkty&#x27;].sum()<br>najlepszy = s.idxmax()<br>print(f&quot;{najlepszy[0]} {najlepszy[1]} | {sezon} | {s.max()}&quot;)</p>\n<h3>Michael Schumacher | 2000 | 108</h3>\n<h3>Fernando Alonso | 2006 | 134</h3>\n<h3>Sebastian Vettel | 2012 | 281</h3>\n<h4>Sposób 3 - arkusz kalkulacyjny (tabela przestawna)</h4>\n<p><strong>Krok 1:</strong> Wczytaj 3 pliki jako tabele. Połącz JOIN-em (PowerQuery / WYSZUKAJ.PIONOWO) Wyniki + Wyscigi po Id_w, dodaj kolumnę Rok.</p>\n<p><strong>Krok 2:</strong> Dodaj nazwisko i imię kierowcy przez WYSZUKAJ.PIONOWO po Id_k.</p>\n<p><strong>Krok 3:</strong> Tabela przestawna:</p>\n<ul><li>Filtr: Rok IN {2000, 2006, 2012}</li><li>Wiersze: Imie + Nazwisko</li><li>Kolumny: Rok</li><li>Wartości: SUMA(Punkty)</li></ul>\n<p><strong>Krok 4:</strong> Dla każdej kolumny (sezonu) odczytaj kierowcę z najwyższą sumą.</p>\n<h4>Reference informatyczny - agregacja warunkowa</h4>\n<blockquote>Reference - SQL GROUP BY + HAVING + podzapytanie skorelowane:<br>- <strong>GROUP BY a, b</strong> - agregacja po dwóch kolumnach (kierowca i sezon).<br>- <strong>SUM(Punkty)</strong> - suma punktów w grupie.<br>- <strong>HAVING SUM = (SELECT MAX )</strong> - filtruje tylko zwycięzców.<br>- <strong>Podzapytanie skorelowane</strong> - <code>w.Rok = w2.Rok</code> wiąże podzapytanie z zewnętrznym wierszem.<br>Alternatywa: WINDOW FUNCTION <code>RANK() OVER (PARTITION BY Rok ORDER BY SUM(Punkty) DESC)</code>.</blockquote>\n<h4>Schemat oceniania CKE</h4>\n<blockquote>Klucz CKE (zadanie 6.3, max 3 pkt):<br>- <strong>3 pkt</strong> - poprawne odpowiedzi we wszystkich trzech wersach (3 zwycięzcy z 3 sezonów + sumy punktów).<br>- <strong>2 pkt</strong> - poprawne odpowiedzi tylko w dwóch wersach.<br>- <strong>1 pkt</strong> - poprawna odpowiedź tylko w jednym wersie.<br>- <strong>0 pkt</strong> - odpowiedź niepełna lub błędna albo brak.</blockquote>\n<h4>Typowe pułapki</h4>\n<ul><li><strong>Klasyfikacja generalna ≠ jeden wyścig</strong> - to SUMA punktów w danym sezonie, nie max z jednego wyścigu.</li><li><strong>Każdy sezon ma swojego zwycięzcę</strong> - trzeba wykonać agregację per (kierowca, sezon), a nie globalnie.</li><li><strong>JOIN 3 tabel</strong> - typowa pułapka: zapomnienie o jednym JOIN powoduje iloczyn kartezjański i błędne sumy.</li><li><strong>Polskie imiona</strong> - uważaj na pisownię (Michael, Fernando, Sebastian - zachowaj oryginał z pliku).</li><li><strong>Liczba punktów dokładna</strong> - klucz CKE wymaga konkretnych wartości 108 / 134 / 281.</li></ul>\n<h4>Złożoność obliczeniowa</h4>\n<ul><li>3 JOIN-y po kluczach: O(N log N) z indeksami lub O(N · M · K) bez.</li><li>GROUP BY z hash: O(N).</li><li>Podzapytanie skorelowane bez optymalizacji: O(N · G) gdzie G = liczba grup.</li><li><strong>Całkowita: O(N log N)</strong> dla rozsądnej implementacji.</li></ul>"}]}