{"id":"informatyka-2016-maj-matura-rozszerzona/zad/6.3","paper_id":"informatyka-2016-maj-matura-rozszerzona","number":"6.3","points":5,"ptype":"open","subject":"informatyka","category":"matura","year":2016,"month":"maj","level":"rozszerzona","text":"Kontekst - patrz zadanie 6.1.\n\nW pliku dane_6_3.txt zapisano 3 000 par słów. Drugie słowo w każdej parze jest szyfrogramem pierwszego z nieznanym kluczem. Niektóre szyfrogramy są błędne (niektóre litery zakodowano z różnymi przesunięciami). Słowo ma zawsze tę samą długość co odpowiadający mu szyfrogram.\n\nFragment:\nZAWISLAK EFBNXQFP\nKRASZEWSKI XENFMRJFXV\n\nUwaga: Pierwsze słowo w pliku wynikowym to SMIGIELSKI.\n\nNapisz program, który wyszuka i wypisze te słowa z pliku dane_6_3.txt, które błędnie zaszyfrowano. Wynik zapisz w pliku wyniki_6_3.txt: każde słowo w osobnym wierszu, w porządku odpowiadającym kolejności tych słów z pliku z danymi.","answer":null,"answer_text":null,"solution":"## Poprawna odpowiedź\n\n**Pierwsze słowa w pliku wynikowym:**\n\nSMIGIELSKI\nJANEK\nJANUSZEWSKI\nWOLAK\nGAJEK\nMROCZKOWSKI\nSZCZESNIAK\nCIESLINSKI\n(i więcej, w kolejności występowania)\n\n## Sposób 1 - wykrywanie błędu szyfrowania\n\n**Idea:** prawidłowy szyfr Cezara to **stałe przesunięcie** dla całego słowa. Dla każdej pary (jawne, szyfr) liczymy przesunięcie każdej litery `delta_i = (szyfr[i] - jawne[i]) mod 26`. Jeśli **wszystkie delta_i są równe** → szyfrowanie prawidłowe. Jeśli różnią się → BŁĘDNE.\n\n**Weryfikacja KRASZEWSKI → XENFMRJFXV:**\n- K(10) → X(23): delta = (23-10) mod 26 = 13\n- R(17) → E(4): delta = (4-17) mod 26 = -13 mod 26 = 13 ✓\n- A(0) → N(13): delta = 13 ✓\n- S(18) → F(5): delta = (5-18) mod 26 = -13 mod 26 = 13 ✓\n- Z(25) → M(12): delta = (12-25) mod 26 = -13 mod 26 = 13 ✓\n- E(4) → R(17): delta = 13 ✓\n- W(22) → J(9): delta = (9-22) mod 26 = -13 mod 26 = 13 ✓\n- S(18) → F(5): 13 ✓\n- K(10) → X(23): 13 ✓\n- I(8) → V(21): delta = 13 ✓\n\nWszystkie delta = 13 → szyfr **prawidłowy**, NIE dodajemy KRASZEWSKI do wyniku.\n\n## Sposób 2 - implementacja Python\n\n```python\ndef przesuniecie(jawny, szyfr):\n\"\"\"Zwraca delta = (szyfr - jawne) mod 26 dla pierwszej litery.\"\"\"\nreturn (ord(szyfr) - ord(jawny)) % 26\n\ndef czy_blednie_zaszyfrowane(jawne, szyfr):\nif len(jawne) != len(szyfr):\nreturn True # różna długość = błąd\ndelty = [(ord(s) - ord(j)) % 26 for j, s in zip(jawne, szyfr)]\nreturn len(set(delty)) > 1 # więcej niż jedno przesunięcie\n\nwynik = []\nwith open('dane_6_3.txt', encoding='utf-8') as fin:\nfor linia in fin:\ncz = linia.strip().split()\nif len(cz) != 2:\ncontinue\njawne, szyfr = cz\nif czy_blednie_zaszyfrowane(jawne, szyfr):\nwynik.append(jawne)\n\nwith open('wyniki_6_3.txt', 'w', encoding='utf-8') as fout:\nfor s in wynik:\nfout.write(s + '\\n')\n\nprint(\"Pierwsze 10:\")\nfor s in wynik[:10]:\nprint(s)\n\n**Spodziewany początek wyniku:**\nSMIGIELSKI\nJANEK\nJANUSZEWSKI\nWOLAK\nGAJEK\nMROCZKOWSKI\nSZCZESNIAK\nCIESLINSKI\n\n## Sposób 3 - C++\n\n```cpp\n#include <iostream>\n#include <fstream>\n#include <string>\n#include <set>\nusing namespace std;\n\nbool blednyszyfr(const string& jawny, const string& szyfr) {\nif (jawny.size() != szyfr.size()) return true;\nset<int> delty;\nfor (size_t i = 0; i < jawny.size(); i++) {\nint d = ((szyfr[i] - jawny[i]) % 26 + 26) % 26;\ndelty.insert(d);\n}\nreturn delty.size() > 1;\n}\n\nint main() {\nifstream fin(\"dane_6_3.txt\");\nofstream fout(\"wyniki_6_3.txt\");\nstring jawny, szyfr;\nwhile (fin >> jawny >> szyfr) {\nif (blednyszyfr(jawny, szyfr)) fout << jawny << \"\\n\";\n}\nreturn 0;\n}\n\n## Sposób 4 - Pascal\n\n```pascal\nprogram Cezar63;\nvar fin, fout: TextFile; jawny, szyfr: String;\ni, d, d0: Integer; blad: Boolean;\nbegin\nAssignFile(fin, 'dane_6_3.txt'); Reset(fin);\nAssignFile(fout, 'wyniki_6_3.txt'); Rewrite(fout);\nwhile not Eof(fin) do begin\nReadln(fin, jawny, ' ', szyfr); // lub Read + Read\nblad := False;\nif Length(jawny) <> Length(szyfr) then blad := True\nelse begin\nd0 := ((Ord(szyfr[1]) - Ord(jawny[1])) mod 26 + 26) mod 26;\nfor i := 2 to Length(jawny) do begin\nd := ((Ord(szyfr[i]) - Ord(jawny[i])) mod 26 + 26) mod 26;\nif d <> d0 then begin blad := True; Break; end;\nend;\nend;\nif blad then Writeln(fout, jawny);\nend;\nCloseFile(fin); CloseFile(fout);\nend.\n\n## Reference informatyczny - kryptoanaliza szyfru Cezara\n\n> Reference - Wykrywanie błędu szyfru Cezara:\n> - **Cecha charakterystyczna**: prawidłowy szyfr Cezara ma **stałe przesunięcie** dla całego słowa.\n> - Algorytm wykrywania: oblicz przesunięcie dla każdej pozycji; jeśli przynajmniej dwa różne → BŁĘDNE.\n> - **Złożoność**: O(L) na słowo, gdzie L = długość słowa.\n>\n> Reference - Modulo z ujemnymi:\n> - `(szyfr - jawne) mod 26` może dać wartość ujemną w C++/Pascal.\n> - Zabezpieczenie: `((x % 26) + 26) % 26`.\n> - W Pythonie `(szyfr - jawne) % 26` zwraca zawsze 0 25 - bez problemu.\n>\n> Reference - Set zamiast porównania:\n> - Jeśli wszystkie elementy listy są takie same, `set(lista)` ma rozmiar 1.\n> - Bardzo elegancka kontrola jednorodności.\n\n## Schemat oceniania CKE\n\n> Klucz CKE (zadanie 6.3, max 5 pkt):\n> - **5 pkt** - poprawny plik wynikowy\n> - **3 pkt** - program odwrotny (przepisuje POPRAWNIE szyfrowane)\n> - **2 pkt** - wynik bez uwzględnienia zawijania (modulo 26)\n> - **0 pkt** - błędna albo brak\n>\n> **Uwaga: NIE PRZYZNAJE SIĘ 4 ani 1 PUNKTU.**\n\n## Typowe pułapki\n\n- **Odwrotny program** - wypisuje TYLKO poprawnie zaszyfrowane zamiast BŁĘDNE - strata 2 pkt.\n- **Modulo ujemne nieprawidłowe** - `(B - Z)` w C++ daje -24 (zamiast 2). Konieczne `((x % 26) + 26) % 26`.\n- **Brak modulo 26** - przesunięcia mogą wyjść spoza zakresu 0-25, ale wciąż być stałe; bez modulo program zwraca BŁĘDNE dla wszystkich.\n- **Porównanie pierwszej z drugą tylko** - błąd: trzeba sprawdzić, czy WSZYSTKIE delta są równe.\n- **Pominięcie pierwszego przesunięcia** - niektóre implementacje porównują delta[i] z delta[i-1]; trzeba pamiętać, żeby zacząć od i=1 lub i=2 (Pascal).\n- **Pomylenie kolejności** - w pliku jest \"JAWNE SZYFR\", nie odwrotnie.\n\n## Złożoność obliczeniowa\n\n- 3000 słów × max 30 znaków: O(N·L) = **O(90 000) operacji**.\n- Set/porównanie delta: O(L) na słowo.","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 2016 (rozszerzona)","subject_label":"Informatyka","category_label":"Matura","text_html":"<p>Kontekst - patrz zadanie 6.1.</p>\n<p>W pliku dane_6_3.txt zapisano 3 000 par słów. Drugie słowo w każdej parze jest szyfrogramem pierwszego z nieznanym kluczem. Niektóre szyfrogramy są błędne (niektóre litery zakodowano z różnymi przesunięciami). Słowo ma zawsze tę samą długość co odpowiadający mu szyfrogram.</p>\n<p>Fragment:<br>ZAWISLAK EFBNXQFP<br>KRASZEWSKI XENFMRJFXV</p>\n<p>Uwaga: Pierwsze słowo w pliku wynikowym to SMIGIELSKI.</p>\n<p>Napisz program, który wyszuka i wypisze te słowa z pliku dane_6_3.txt, które błędnie zaszyfrowano. Wynik zapisz w pliku wyniki_6_3.txt: każde słowo w osobnym wierszu, w porządku odpowiadającym kolejności tych słów z pliku z danymi.</p>","solutions":[{"source":"maturazai","label":"maturazai.pl (AI)","kind":"text","html":"<h4>Poprawna odpowiedź</h4>\n<p><strong>Pierwsze słowa w pliku wynikowym:</strong></p>\n<p>SMIGIELSKI<br>JANEK<br>JANUSZEWSKI<br>WOLAK<br>GAJEK<br>MROCZKOWSKI<br>SZCZESNIAK<br>CIESLINSKI<br>(i więcej, w kolejności występowania)</p>\n<h4>Sposób 1 - wykrywanie błędu szyfrowania</h4>\n<p><strong>Idea:</strong> prawidłowy szyfr Cezara to <strong>stałe przesunięcie</strong> dla całego słowa. Dla każdej pary (jawne, szyfr) liczymy przesunięcie każdej litery <code>delta_i = (szyfr[i] - jawne[i]) mod 26</code>. Jeśli <strong>wszystkie delta_i są równe</strong> → szyfrowanie prawidłowe. Jeśli różnią się → BŁĘDNE.</p>\n<p><strong>Weryfikacja KRASZEWSKI → XENFMRJFXV:</strong></p>\n<ul><li>K(10) → X(23): delta = (23-10) mod 26 = 13</li><li>R(17) → E(4): delta = (4-17) mod 26 = -13 mod 26 = 13 ✓</li><li>A(0) → N(13): delta = 13 ✓</li><li>S(18) → F(5): delta = (5-18) mod 26 = -13 mod 26 = 13 ✓</li><li>Z(25) → M(12): delta = (12-25) mod 26 = -13 mod 26 = 13 ✓</li><li>E(4) → R(17): delta = 13 ✓</li><li>W(22) → J(9): delta = (9-22) mod 26 = -13 mod 26 = 13 ✓</li><li>S(18) → F(5): 13 ✓</li><li>K(10) → X(23): 13 ✓</li><li>I(8) → V(21): delta = 13 ✓</li></ul>\n<p>Wszystkie delta = 13 → szyfr <strong>prawidłowy</strong>, NIE dodajemy KRASZEWSKI do wyniku.</p>\n<h4>Sposób 2 - implementacja Python</h4>\n<p>```python<br>def przesuniecie(jawny, szyfr):<br>&quot;&quot;&quot;Zwraca delta = (szyfr - jawne) mod 26 dla pierwszej litery.&quot;&quot;&quot;<br>return (ord(szyfr) - ord(jawny)) % 26</p>\n<p>def czy_blednie_zaszyfrowane(jawne, szyfr):<br>if len(jawne) != len(szyfr):<br>return True # różna długość = błąd<br>delty = [(ord(s) - ord(j)) % 26 for j, s in zip(jawne, szyfr)]<br>return len(set(delty)) &gt; 1 # więcej niż jedno przesunięcie</p>\n<p>wynik = []<br>with open(&#x27;dane_6_3.txt&#x27;, encoding=&#x27;utf-8&#x27;) as fin:<br>for linia in fin:<br>cz = linia.strip().split()<br>if len(cz) != 2:<br>continue<br>jawne, szyfr = cz<br>if czy_blednie_zaszyfrowane(jawne, szyfr):<br>wynik.append(jawne)</p>\n<p>with open(&#x27;wyniki_6_3.txt&#x27;, &#x27;w&#x27;, encoding=&#x27;utf-8&#x27;) as fout:<br>for s in wynik:<br>fout.write(s + &#x27;\\n&#x27;)</p>\n<p>print(&quot;Pierwsze 10:&quot;)<br>for s in wynik[:10]:<br>print(s)</p>\n<p><strong>Spodziewany początek wyniku:</strong><br>SMIGIELSKI<br>JANEK<br>JANUSZEWSKI<br>WOLAK<br>GAJEK<br>MROCZKOWSKI<br>SZCZESNIAK<br>CIESLINSKI</p>\n<h4>Sposób 3 - C++</h4>\n<p>```cpp<br>#include &lt;iostream&gt;<br>#include &lt;fstream&gt;<br>#include &lt;string&gt;<br>#include &lt;set&gt;<br>using namespace std;</p>\n<p>bool blednyszyfr(const string&amp; jawny, const string&amp; szyfr) {<br>if (jawny.size() != szyfr.size()) return true;<br>set&lt;int&gt; delty;<br>for (size_t i = 0; i &lt; jawny.size(); i++) {<br>int d = ((szyfr[i] - jawny[i]) % 26 + 26) % 26;<br>delty.insert(d);<br>}<br>return delty.size() &gt; 1;<br>}</p>\n<p>int main() {<br>ifstream fin(&quot;dane_6_3.txt&quot;);<br>ofstream fout(&quot;wyniki_6_3.txt&quot;);<br>string jawny, szyfr;<br>while (fin &gt;&gt; jawny &gt;&gt; szyfr) {<br>if (blednyszyfr(jawny, szyfr)) fout &lt;&lt; jawny &lt;&lt; &quot;\\n&quot;;<br>}<br>return 0;<br>}</p>\n<h4>Sposób 4 - Pascal</h4>\n<p>```pascal<br>program Cezar63;<br>var fin, fout: TextFile; jawny, szyfr: String;<br>i, d, d0: Integer; blad: Boolean;<br>begin<br>AssignFile(fin, &#x27;dane_6_3.txt&#x27;); Reset(fin);<br>AssignFile(fout, &#x27;wyniki_6_3.txt&#x27;); Rewrite(fout);<br>while not Eof(fin) do begin<br>Readln(fin, jawny, &#x27; &#x27;, szyfr); // lub Read + Read<br>blad := False;<br>if Length(jawny) &lt;&gt; Length(szyfr) then blad := True<br>else begin<br>d0 := ((Ord(szyfr[1]) - Ord(jawny[1])) mod 26 + 26) mod 26;<br>for i := 2 to Length(jawny) do begin<br>d := ((Ord(szyfr[i]) - Ord(jawny[i])) mod 26 + 26) mod 26;<br>if d &lt;&gt; d0 then begin blad := True; Break; end;<br>end;<br>end;<br>if blad then Writeln(fout, jawny);<br>end;<br>CloseFile(fin); CloseFile(fout);<br>end.</p>\n<h4>Reference informatyczny - kryptoanaliza szyfru Cezara</h4>\n<blockquote>Reference - Wykrywanie błędu szyfru Cezara:<br>- <strong>Cecha charakterystyczna</strong>: prawidłowy szyfr Cezara ma <strong>stałe przesunięcie</strong> dla całego słowa.<br>- Algorytm wykrywania: oblicz przesunięcie dla każdej pozycji; jeśli przynajmniej dwa różne → BŁĘDNE.<br>- <strong>Złożoność</strong>: O(L) na słowo, gdzie L = długość słowa.<br><br>Reference - Modulo z ujemnymi:<br>- <code>(szyfr - jawne) mod 26</code> może dać wartość ujemną w C++/Pascal.<br>- Zabezpieczenie: <code>((x % 26) + 26) % 26</code>.<br>- W Pythonie <code>(szyfr - jawne) % 26</code> zwraca zawsze 0 25 - bez problemu.<br><br>Reference - Set zamiast porównania:<br>- Jeśli wszystkie elementy listy są takie same, <code>set(lista)</code> ma rozmiar 1.<br>- Bardzo elegancka kontrola jednorodności.</blockquote>\n<h4>Schemat oceniania CKE</h4>\n<blockquote>Klucz CKE (zadanie 6.3, max 5 pkt):<br>- <strong>5 pkt</strong> - poprawny plik wynikowy<br>- <strong>3 pkt</strong> - program odwrotny (przepisuje POPRAWNIE szyfrowane)<br>- <strong>2 pkt</strong> - wynik bez uwzględnienia zawijania (modulo 26)<br>- <strong>0 pkt</strong> - błędna albo brak<br><br><strong>Uwaga: NIE PRZYZNAJE SIĘ 4 ani 1 PUNKTU.</strong></blockquote>\n<h4>Typowe pułapki</h4>\n<ul><li><strong>Odwrotny program</strong> - wypisuje TYLKO poprawnie zaszyfrowane zamiast BŁĘDNE - strata 2 pkt.</li><li><strong>Modulo ujemne nieprawidłowe</strong> - <code>(B - Z)</code> w C++ daje -24 (zamiast 2). Konieczne <code>((x % 26) + 26) % 26</code>.</li><li><strong>Brak modulo 26</strong> - przesunięcia mogą wyjść spoza zakresu 0-25, ale wciąż być stałe; bez modulo program zwraca BŁĘDNE dla wszystkich.</li><li><strong>Porównanie pierwszej z drugą tylko</strong> - błąd: trzeba sprawdzić, czy WSZYSTKIE delta są równe.</li><li><strong>Pominięcie pierwszego przesunięcia</strong> - niektóre implementacje porównują delta[i] z delta[i-1]; trzeba pamiętać, żeby zacząć od i=1 lub i=2 (Pascal).</li><li><strong>Pomylenie kolejności</strong> - w pliku jest &quot;JAWNE SZYFR&quot;, nie odwrotnie.</li></ul>\n<h4>Złożoność obliczeniowa</h4>\n<ul><li>3000 słów × max 30 znaków: O(N·L) = <strong>O(90 000) operacji</strong>.</li><li>Set/porównanie delta: O(L) na słowo.</li></ul>"}]}