{"id":"informatyka-2018-maj-matura-rozszerzona/zad/6.4","paper_id":"informatyka-2018-maj-matura-rozszerzona","number":"6.4","points":3,"ptype":"open","subject":"informatyka","category":"matura","year":2018,"month":"maj","level":"rozszerzona","text":"Kontekst - patrz zadanie 6.1.\n\nZnajdź awarię, której usunięcie trwało najdłużej (czas liczymy od wystąpienia awarii do momentu zakończenia ostatniej z napraw, jakiej ta awaria wymagała). Podaj numer zgłoszenia, czas wystąpienia awarii i czas zakończenia ostatniej naprawy.","answer":null,"answer_text":null,"solution":"## Poprawna odpowiedź\n\n**Numer zgłoszenia: 2087**\n\n**Czas wystąpienia awarii: 06-11-2015 12:38:46**\n\n**Czas zakończenia ostatniej naprawy: 13-11-2015 12:38:32**\n\n## Sposób 1 - SQL\n\n**Idea:** dla każdej awarii znajdź MAX(Czas_naprawy) (czas ostatniej naprawy), oblicz różnicę z Czas_awarii, znajdź maksimum.\n\n```sql\nSELECT a.Numer_zgloszenia, a.Czas_awarii, MAX(n.Czas_naprawy) AS ostatnia_naprawa\nFROM awarie a\nJOIN naprawy n ON a.Numer_zgloszenia = n.Numer_zgloszenia\nGROUP BY a.Numer_zgloszenia, a.Czas_awarii\nORDER BY (julianday(MAX(n.Czas_naprawy)) - julianday(a.Czas_awarii)) DESC\nLIMIT 1;\n\n(W SQLite `julianday()` zwraca dzień juliański - pozwala odjąć daty. W innych SQL: `TIMESTAMPDIFF`, `EXTRACT(EPOCH )`.)\n\n## Sposób 2 - Python\n\n```python\nfrom datetime import datetime\nfrom collections import defaultdict\n\n# Wczytaj awarie\nawarie = {}\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, czas, prio = cz[0], cz[1], cz[2], cz[3]\nawarie[zgl] = czas\n\n# Mapuj zgl -> max czas_naprawy\nmax_naprawa = defaultdict(str)\nwith open('naprawy.txt', encoding='utf-8') as f:\nnext(f)\nfor linia in f:\ncz = linia.strip().split('\\t')\nif len(cz) >= 3:\nzgl, czas = cz[0], cz[1]\nif czas > max_naprawa[zgl]:\nmax_naprawa[zgl] = czas\n\n# Oblicz różnice i znajdź max\nnajwieksza_roznica = 0\nnajwiekszy_zgl = None\nfor zgl in awarie:\nif zgl in max_naprawa:\nt1 = datetime.strptime(awarie[zgl], '%Y-%m-%d %H:%M:%S')\nt2 = datetime.strptime(max_naprawa[zgl], '%Y-%m-%d %H:%M:%S')\nroznica = (t2 - t1).total_seconds()\nif roznica > najwieksza_roznica:\nnajwieksza_roznica = roznica\nnajwiekszy_zgl = zgl\n\nprint(f\"Zgłoszenie: {najwiekszy_zgl}\")\nprint(f\"Awaria: {awarie[najwiekszy_zgl]}\")\nprint(f\"Naprawa: {max_naprawa[najwiekszy_zgl]}\")\nprint(f\"Czas: {najwieksza_roznica / 3600:.1f} h\")\n\n**Wynik:**\nZgłoszenie: 2087\nAwaria: 2015-11-06 12:38:46\nNaprawa: 2015-11-13 12:38:32\nCzas: ~167 h (~7 dni)\n\n## Sposób 3 - arkusz kalkulacyjny\n\n1. awarie.txt: kolumna A = nr_zgl, B = nr_kom, C = czas_awarii, D = priorytet.\n2. naprawy.txt: kolumna A = nr_zgl, B = czas_naprawy, C = rodzaj.\n3. W awarie dodaj E = `=MAKS.WARUNKÓW(naprawy!B:B; naprawy!A:A; A2)` (max czas_naprawy dla tego nr_zgl).\n4. F = `=E2 - C2` (czas trwania, jako liczba dni - format \"liczba\" lub \"daty\").\n5. Sortuj F malejąco. Pierwsze wiersz: nr_zgl 2087.\n\n## Reference informatyczny - agregacja MAX z różnicy dat\n\n> Reference - Operacje na czasie (timestamp):\n> - **Format ISO**: `YYYY-MM-DD HH:MM:SS` - sortuje leksykograficznie = chronologicznie.\n> - **Python**: `datetime.strptime()` + `total_seconds()`.\n> - **C++**: `std::chrono` lub konwersja na sekundy od epoki.\n> - **SQL**: `julianday()`, `TIMESTAMPDIFF()`, `EXTRACT(EPOCH FROM )`.\n>\n> Reference - \"Najdłużej trwająca awaria\":\n> - Czas trwania = MAX(czas_naprawy) - czas_awarii.\n> - Awaria może mieć wiele napraw - ostatnia decyduje.\n> - GROUP BY na poziomie awarii (Numer_zgloszenia).\n\n## Schemat oceniania CKE\n\n> Klucz CKE (zadanie 6.4, max 3 pkt):\n> - **1 pkt** za prawidłowy numer zgłoszenia (2087)\n> - **1 pkt** za prawidłowy czas wystąpienia awarii\n> - **1 pkt** za prawidłowy czas zakończenia ostatniej naprawy\n> - **0 pkt** - błędne lub brak\n\n## Typowe pułapki\n\n- **Liczenie czasu do PIERWSZEJ naprawy** zamiast OSTATNIEJ - błędne.\n- **Pominięcie awarii bez naprawy** - niektóre awarie mogą nie mieć wpisu w naprawy.txt; powinny być pominięte.\n- **Format daty** - CKE pokazuje 06-11-2015 (DD-MM-YYYY), ale plik ma ISO (2015-11-06). Konwertuj przy wyświetlaniu.\n- **Porównanie stringami** - działa dla ISO timestampów, NIE dla DD-MM-YYYY (\"06-11-2015\" < \"13-11-2015\" zgodnie z prefiksem, ale \"06-11-2015\" > \"05-12-2015\" mimo że chronologicznie odwrotnie).\n- **MAX bez GROUP BY** - daje tylko globalny max, nie per awaria.\n\n## Złożoność obliczeniowa\n\n- Wczytanie 2 plików: O(A + N).\n- Agregacja: O(N) dla maksimum naprawy per zgłoszenie.\n- Znalezienie max różnicy: O(A).\n- **Łącznie: O(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ź awarię, której usunięcie trwało najdłużej (czas liczymy od wystąpienia awarii do momentu zakończenia ostatniej z napraw, jakiej ta awaria wymagała). Podaj numer zgłoszenia, czas wystąpienia awarii i czas zakończenia ostatniej naprawy.</p>","solutions":[{"source":"maturazai","label":"maturazai.pl (AI)","kind":"text","html":"<h4>Poprawna odpowiedź</h4>\n<p><strong>Numer zgłoszenia: 2087</strong></p>\n<p><strong>Czas wystąpienia awarii: 06-11-2015 12:38:46</strong></p>\n<p><strong>Czas zakończenia ostatniej naprawy: 13-11-2015 12:38:32</strong></p>\n<h4>Sposób 1 - SQL</h4>\n<p><strong>Idea:</strong> dla każdej awarii znajdź MAX(Czas_naprawy) (czas ostatniej naprawy), oblicz różnicę z Czas_awarii, znajdź maksimum.</p>\n<p>```sql<br>SELECT a.Numer_zgloszenia, a.Czas_awarii, MAX(n.Czas_naprawy) AS ostatnia_naprawa<br>FROM awarie a<br>JOIN naprawy n ON a.Numer_zgloszenia = n.Numer_zgloszenia<br>GROUP BY a.Numer_zgloszenia, a.Czas_awarii<br>ORDER BY (julianday(MAX(n.Czas_naprawy)) - julianday(a.Czas_awarii)) DESC<br>LIMIT 1;</p>\n<p>(W SQLite <code>julianday()</code> zwraca dzień juliański - pozwala odjąć daty. W innych SQL: <code>TIMESTAMPDIFF</code>, <code>EXTRACT(EPOCH )</code>.)</p>\n<h4>Sposób 2 - Python</h4>\n<p>```python<br>from datetime import datetime<br>from collections import defaultdict</p>\n<h3>Wczytaj awarie</h3>\n<p>awarie = {}<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, czas, prio = cz[0], cz[1], cz[2], cz[3]<br>awarie[zgl] = czas</p>\n<h3>Mapuj zgl -&gt; max czas_naprawy</h3>\n<p>max_naprawa = defaultdict(str)<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:<br>zgl, czas = cz[0], cz[1]<br>if czas &gt; max_naprawa[zgl]:<br>max_naprawa[zgl] = czas</p>\n<h3>Oblicz różnice i znajdź max</h3>\n<p>najwieksza_roznica = 0<br>najwiekszy_zgl = None<br>for zgl in awarie:<br>if zgl in max_naprawa:<br>t1 = datetime.strptime(awarie[zgl], &#x27;%Y-%m-%d %H:%M:%S&#x27;)<br>t2 = datetime.strptime(max_naprawa[zgl], &#x27;%Y-%m-%d %H:%M:%S&#x27;)<br>roznica = (t2 - t1).total_seconds()<br>if roznica &gt; najwieksza_roznica:<br>najwieksza_roznica = roznica<br>najwiekszy_zgl = zgl</p>\n<p>print(f&quot;Zgłoszenie: {najwiekszy_zgl}&quot;)<br>print(f&quot;Awaria: {awarie[najwiekszy_zgl]}&quot;)<br>print(f&quot;Naprawa: {max_naprawa[najwiekszy_zgl]}&quot;)<br>print(f&quot;Czas: {najwieksza_roznica / 3600:.1f} h&quot;)</p>\n<p><strong>Wynik:</strong><br>Zgłoszenie: 2087<br>Awaria: 2015-11-06 12:38:46<br>Naprawa: 2015-11-13 12:38:32<br>Czas: ~167 h (~7 dni)</p>\n<h4>Sposób 3 - arkusz kalkulacyjny</h4>\n<ol><li>awarie.txt: kolumna A = nr_zgl, B = nr_kom, C = czas_awarii, D = priorytet.</li><li>naprawy.txt: kolumna A = nr_zgl, B = czas_naprawy, C = rodzaj.</li><li>W awarie dodaj E = <code>=MAKS.WARUNKÓW(naprawy!B:B; naprawy!A:A; A2)</code> (max czas_naprawy dla tego nr_zgl).</li><li>F = <code>=E2 - C2</code> (czas trwania, jako liczba dni - format &quot;liczba&quot; lub &quot;daty&quot;).</li><li>Sortuj F malejąco. Pierwsze wiersz: nr_zgl 2087.</li></ol>\n<h4>Reference informatyczny - agregacja MAX z różnicy dat</h4>\n<blockquote>Reference - Operacje na czasie (timestamp):<br>- <strong>Format ISO</strong>: <code>YYYY-MM-DD HH:MM:SS</code> - sortuje leksykograficznie = chronologicznie.<br>- <strong>Python</strong>: <code>datetime.strptime()</code> + <code>total_seconds()</code>.<br>- <strong>C++</strong>: <code>std::chrono</code> lub konwersja na sekundy od epoki.<br>- <strong>SQL</strong>: <code>julianday()</code>, <code>TIMESTAMPDIFF()</code>, <code>EXTRACT(EPOCH FROM )</code>.<br><br>Reference - &quot;Najdłużej trwająca awaria&quot;:<br>- Czas trwania = MAX(czas_naprawy) - czas_awarii.<br>- Awaria może mieć wiele napraw - ostatnia decyduje.<br>- GROUP BY na poziomie awarii (Numer_zgloszenia).</blockquote>\n<h4>Schemat oceniania CKE</h4>\n<blockquote>Klucz CKE (zadanie 6.4, max 3 pkt):<br>- <strong>1 pkt</strong> za prawidłowy numer zgłoszenia (2087)<br>- <strong>1 pkt</strong> za prawidłowy czas wystąpienia awarii<br>- <strong>1 pkt</strong> za prawidłowy czas zakończenia ostatniej naprawy<br>- <strong>0 pkt</strong> - błędne lub brak</blockquote>\n<h4>Typowe pułapki</h4>\n<ul><li><strong>Liczenie czasu do PIERWSZEJ naprawy</strong> zamiast OSTATNIEJ - błędne.</li><li><strong>Pominięcie awarii bez naprawy</strong> - niektóre awarie mogą nie mieć wpisu w naprawy.txt; powinny być pominięte.</li><li><strong>Format daty</strong> - CKE pokazuje 06-11-2015 (DD-MM-YYYY), ale plik ma ISO (2015-11-06). Konwertuj przy wyświetlaniu.</li><li><strong>Porównanie stringami</strong> - działa dla ISO timestampów, NIE dla DD-MM-YYYY (&quot;06-11-2015&quot; &lt; &quot;13-11-2015&quot; zgodnie z prefiksem, ale &quot;06-11-2015&quot; &gt; &quot;05-12-2015&quot; mimo że chronologicznie odwrotnie).</li><li><strong>MAX bez GROUP BY</strong> - daje tylko globalny max, nie per awaria.</li></ul>\n<h4>Złożoność obliczeniowa</h4>\n<ul><li>Wczytanie 2 plików: O(A + N).</li><li>Agregacja: O(N) dla maksimum naprawy per zgłoszenie.</li><li>Znalezienie max różnicy: O(A).</li><li><strong>Łącznie: O(A + N).</strong></li></ul>"}]}