{"id":"informatyka-2018-maj-matura-rozszerzona/zad/6.2","paper_id":"informatyka-2018-maj-matura-rozszerzona","number":"6.2","points":2,"ptype":"open","subject":"informatyka","category":"matura","year":2018,"month":"maj","level":"rozszerzona","text":"Kontekst - patrz zadanie 6.1.\n\nZnajdź wszystkie komputery w sekcji A, w których trzeba było przynajmniej dziesięciokrotnie wymieniać podzespoły. Podaj ich numery, a także liczbę wymian podzespołów dla każdego z nich.","answer":null,"answer_text":null,"solution":"## Poprawna odpowiedź\n\n| Komputer | Liczba wymian podzespołów |\n| Komputer 202 | 12 |\n| Komputer 123 | 11 |\n| Komputer 171 | 12 |\n| Komputer 42 | 11 |\n\n## Sposób 1 - SQL z trzema tabelami\n\n**Schemat złączeń:**\n- `komputery` (sekcja = 'A') ← `awarie` (Numer_komputera) ← `naprawy` (Numer_zgloszenia, Rodzaj = 'wymiana').\n\n```sql\nSELECT k.Numer_komputera, COUNT(*) AS liczba_wymian\nFROM komputery k\nJOIN awarie a ON k.Numer_komputera = a.Numer_komputera\nJOIN naprawy n ON a.Numer_zgloszenia = n.Numer_zgloszenia\nWHERE k.Sekcja = 'A' AND n.Rodzaj = 'wymiana'\nGROUP BY k.Numer_komputera\nHAVING COUNT(*) >= 10\nORDER BY k.Numer_komputera;\n\n## Sposób 2 - Python\n\n```python\nfrom collections import Counter\n\n# Wczytaj komputery sekcji A\nsekcja_A = set()\nwith open('komputery.txt', encoding='utf-8') as f:\nnext(f)\nfor linia in f:\ncz = linia.strip().split('\\t')\nif len(cz) >= 3 and cz[1] == 'A':\nsekcja_A.add(cz[0])\n\n# Mapuj zgłoszenie -> komputer (tylko sekcja A)\nzgl_to_kom = {}\nwith open('awarie.txt', encoding='utf-8') as f:\nnext(f)\nfor linia in f:\ncz = linia.strip().split('\\t')\nif len(cz) >= 4:\nzgl, kom = cz[0], cz[1]\nif kom in sekcja_A:\nzgl_to_kom[zgl] = kom\n\n# Licz wymiany\nwymiany = Counter()\nwith open('naprawy.txt', encoding='utf-8') as f:\nnext(f)\nfor linia in f:\ncz = linia.strip().split('\\t')\nif len(cz) >= 3 and cz[2] == 'wymiana':\nzgl = cz[0]\nif zgl in zgl_to_kom:\nwymiany[zgl_to_kom[zgl]] += 1\n\n# Filtruj >= 10\nwynik = [(k, c) for k, c in wymiany.items() if c >= 10]\nfor k, c in sorted(wynik):\nprint(f\"Komputer {k}: {c}\")\n\n**Wynik:**\nKomputer 42: 11\nKomputer 123: 11\nKomputer 171: 12\nKomputer 202: 12\n\n## Reference informatyczny - JOIN i agregacja z filtrem\n\n> Reference - Łańcuch JOIN:\n> - 3-tablicowy JOIN: `A JOIN B ON JOIN C ON `.\n> - Klucze: A.id = B.foreign_id, B.id = C.foreign_id.\n> - Sekwencyjne JOINy są bardzo wydajne z indeksami.\n>\n> Reference - HAVING vs WHERE:\n> - `WHERE` filtruje WIERSZE PRZED agregacją (przed GROUP BY).\n> - `HAVING` filtruje GRUPY PO agregacji (po GROUP BY).\n> - `HAVING COUNT(*) >= 10` to NIE może być w `WHERE`, bo COUNT to wynik agregacji.\n>\n> Reference - \"Wymiana\" jako Rodzaj:\n> - Dane mają 2 wartości: 'restart' i 'wymiana'.\n> - Filtr `WHERE Rodzaj = 'wymiana'` ogranicza do wymian podzespołów.\n\n## Schemat oceniania CKE\n\n> Klucz CKE (zadanie 6.2, max 2 pkt):\n> - **2 pkt** - wszystkie 4 wyniki (komputer + liczba) prawidłowe\n> - **1 pkt** - tylko numery komputerów bez liczb wymian ALBO bez warunku `>= 10` (czyli wszystkie komputery sekcji A z liczbą wymian)\n> - **0 pkt** - błędne lub brak\n\n## Typowe pułapki\n\n- **Pominięcie filtra Rodzaj = 'wymiana'** - wtedy liczymy restartów + wymian.\n- **Pominięcie warunku Sekcja = 'A'** - wyniki dla wszystkich sekcji.\n- **Mylenie awarii z naprawami** - awaria = zgłoszenie (zdarzenie), naprawa = działanie (rodzaj: restart/wymiana). JEDEN komputer może mieć WIELE awarii, każda awaria może mieć WIELE napraw.\n- **WHERE COUNT(*) >= 10** - błąd składni. Musi być HAVING.\n- **Liczenie awarii zamiast wymian** - wymiana to jeden Rodzaj naprawy; nie wszystkie naprawy są wymianami.\n- **DISTINCT na Numer_komputera** - nieprawidłowe; wtedy każdy komputer liczy się tylko raz.\n\n## Złożoność obliczeniowa\n\n- Wczytanie 3 plików: O(K + A + N) gdzie K = ~500 komputerów, A = liczba awarii, N = liczba napraw.\n- Filtrowanie i agregacja: O(K + A + N).\n- **Łącznie: O(K + A + N).**","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 2018 (rozszerzona)","subject_label":"Informatyka","category_label":"Matura","text_html":"<p>Kontekst - patrz zadanie 6.1.</p>\n<p>Znajdź wszystkie komputery w sekcji A, w których trzeba było przynajmniej dziesięciokrotnie wymieniać podzespoły. Podaj ich numery, a także liczbę wymian podzespołów dla każdego z nich.</p>","solutions":[{"source":"maturazai","label":"maturazai.pl (AI)","kind":"text","html":"<h4>Poprawna odpowiedź</h4>\n<p>| Komputer | Liczba wymian podzespołów |<br>| Komputer 202 | 12 |<br>| Komputer 123 | 11 |<br>| Komputer 171 | 12 |<br>| Komputer 42 | 11 |</p>\n<h4>Sposób 1 - SQL z trzema tabelami</h4>\n<p><strong>Schemat złączeń:</strong></p>\n<ul><li><code>komputery</code> (sekcja = &#x27;A&#x27;) ← <code>awarie</code> (Numer_komputera) ← <code>naprawy</code> (Numer_zgloszenia, Rodzaj = &#x27;wymiana&#x27;).</li></ul>\n<p>```sql<br>SELECT k.Numer_komputera, COUNT(*) AS liczba_wymian<br>FROM komputery k<br>JOIN awarie a ON k.Numer_komputera = a.Numer_komputera<br>JOIN naprawy n ON a.Numer_zgloszenia = n.Numer_zgloszenia<br>WHERE k.Sekcja = &#x27;A&#x27; AND n.Rodzaj = &#x27;wymiana&#x27;<br>GROUP BY k.Numer_komputera<br>HAVING COUNT(*) &gt;= 10<br>ORDER BY k.Numer_komputera;</p>\n<h4>Sposób 2 - Python</h4>\n<p>```python<br>from collections import Counter</p>\n<h3>Wczytaj komputery sekcji A</h3>\n<p>sekcja_A = set()<br>with open(&#x27;komputery.txt&#x27;, encoding=&#x27;utf-8&#x27;) as f:<br>next(f)<br>for linia in f:<br>cz = linia.strip().split(&#x27;\\t&#x27;)<br>if len(cz) &gt;= 3 and cz[1] == &#x27;A&#x27;:<br>sekcja_A.add(cz[0])</p>\n<h3>Mapuj zgłoszenie -&gt; komputer (tylko sekcja A)</h3>\n<p>zgl_to_kom = {}<br>with open(&#x27;awarie.txt&#x27;, encoding=&#x27;utf-8&#x27;) as f:<br>next(f)<br>for linia in f:<br>cz = linia.strip().split(&#x27;\\t&#x27;)<br>if len(cz) &gt;= 4:<br>zgl, kom = cz[0], cz[1]<br>if kom in sekcja_A:<br>zgl_to_kom[zgl] = kom</p>\n<h3>Licz wymiany</h3>\n<p>wymiany = Counter()<br>with open(&#x27;naprawy.txt&#x27;, encoding=&#x27;utf-8&#x27;) as f:<br>next(f)<br>for linia in f:<br>cz = linia.strip().split(&#x27;\\t&#x27;)<br>if len(cz) &gt;= 3 and cz[2] == &#x27;wymiana&#x27;:<br>zgl = cz[0]<br>if zgl in zgl_to_kom:<br>wymiany[zgl_to_kom[zgl]] += 1</p>\n<h3>Filtruj &gt;= 10</h3>\n<p>wynik = [(k, c) for k, c in wymiany.items() if c &gt;= 10]<br>for k, c in sorted(wynik):<br>print(f&quot;Komputer {k}: {c}&quot;)</p>\n<p><strong>Wynik:</strong><br>Komputer 42: 11<br>Komputer 123: 11<br>Komputer 171: 12<br>Komputer 202: 12</p>\n<h4>Reference informatyczny - JOIN i agregacja z filtrem</h4>\n<blockquote>Reference - Łańcuch JOIN:<br>- 3-tablicowy JOIN: <code>A JOIN B ON JOIN C ON </code>.<br>- Klucze: A.id = B.foreign_id, B.id = C.foreign_id.<br>- Sekwencyjne JOINy są bardzo wydajne z indeksami.<br><br>Reference - HAVING vs WHERE:<br>- <code>WHERE</code> filtruje WIERSZE PRZED agregacją (przed GROUP BY).<br>- <code>HAVING</code> filtruje GRUPY PO agregacji (po GROUP BY).<br>- <code>HAVING COUNT(*) &gt;= 10</code> to NIE może być w <code>WHERE</code>, bo COUNT to wynik agregacji.<br><br>Reference - &quot;Wymiana&quot; jako Rodzaj:<br>- Dane mają 2 wartości: &#x27;restart&#x27; i &#x27;wymiana&#x27;.<br>- Filtr <code>WHERE Rodzaj = &#x27;wymiana&#x27;</code> ogranicza do wymian podzespołów.</blockquote>\n<h4>Schemat oceniania CKE</h4>\n<blockquote>Klucz CKE (zadanie 6.2, max 2 pkt):<br>- <strong>2 pkt</strong> - wszystkie 4 wyniki (komputer + liczba) prawidłowe<br>- <strong>1 pkt</strong> - tylko numery komputerów bez liczb wymian ALBO bez warunku <code>&gt;= 10</code> (czyli wszystkie komputery sekcji A z liczbą wymian)<br>- <strong>0 pkt</strong> - błędne lub brak</blockquote>\n<h4>Typowe pułapki</h4>\n<ul><li><strong>Pominięcie filtra Rodzaj = &#x27;wymiana&#x27;</strong> - wtedy liczymy restartów + wymian.</li><li><strong>Pominięcie warunku Sekcja = &#x27;A&#x27;</strong> - wyniki dla wszystkich sekcji.</li><li><strong>Mylenie awarii z naprawami</strong> - awaria = zgłoszenie (zdarzenie), naprawa = działanie (rodzaj: restart/wymiana). JEDEN komputer może mieć WIELE awarii, każda awaria może mieć WIELE napraw.</li><li><strong>WHERE COUNT(*) &gt;= 10</strong> - błąd składni. Musi być HAVING.</li><li><strong>Liczenie awarii zamiast wymian</strong> - wymiana to jeden Rodzaj naprawy; nie wszystkie naprawy są wymianami.</li><li><strong>DISTINCT na Numer_komputera</strong> - nieprawidłowe; wtedy każdy komputer liczy się tylko raz.</li></ul>\n<h4>Złożoność obliczeniowa</h4>\n<ul><li>Wczytanie 3 plików: O(K + A + N) gdzie K = ~500 komputerów, A = liczba awarii, N = liczba napraw.</li><li>Filtrowanie i agregacja: O(K + A + N).</li><li><strong>Łącznie: O(K + A + N).</strong></li></ul>"}]}