{"id":"informatyka-2015-maj-matura-rozszerzona/zad/4.2","paper_id":"informatyka-2015-maj-matura-rozszerzona","number":"4.2","points":3,"ptype":"open","subject":"informatyka","category":"matura","year":2015,"month":"maj","level":"rozszerzona","text":"Kontekst - patrz zadanie 4.1.\n\nPrzykład: dla zestawu liczb 101011010011001100000, 10001001, 100100, 101010010101011011000, 100011 - trzy liczby są podzielne przez 2 i dwie liczby są podzielne przez 8.\n\nPodaj, ile liczb w pliku liczby.txt jest podzielnych przez 2 oraz ile liczb jest podzielnych przez 8.","answer":null,"answer_text":null,"solution":"## Poprawna odpowiedź\n\n- **podzielne przez 2: 500**\n- **podzielne przez 8: 123**\n\n## Sposób 1 - sprawdzanie końcówki zapisu binarnego\n\n**Kluczowa obserwacja:**\n- Liczba binarna jest **podzielna przez 2** ⟺ kończy się na **0** (ostatni bit = 0).\n- Liczba binarna jest **podzielna przez 4** ⟺ kończy się na **00**.\n- Liczba binarna jest **podzielna przez 8** ⟺ kończy się na **000** (3 ostatnie bity = 0).\n- Ogólnie: podzielna przez 2^k ⟺ kończy się k zerami.\n\n**Python:**\n```python\nlicznik_2 = 0\nlicznik_8 = 0\nwith open('liczby.txt') as f:\nfor linia in f:\ns = linia.strip()\nif s.endswith('0'):\nlicznik_2 += 1\nif s.endswith('000'):\nlicznik_8 += 1\nprint('podzielne przez 2:', licznik_2) # 500\nprint('podzielne przez 8:', licznik_8) # 123\n\n## Sposób 2 - implementacja w C++ i Pascal\n\n**C++:**\n```cpp\n#include <iostream>\n#include <fstream>\n#include <string>\nusing namespace std;\n\nint main() {\nifstream plik(\"liczby.txt\");\nstring s;\nint p2 = 0, p8 = 0;\nwhile (plik >> s) {\nint n = s.length();\nif (s[n-1] == '0') p2++;\nif (n >= 3 && s.substr(n-3) == \"000\") p8++;\n}\ncout << \"przez 2: \" << p2 << endl; // 500\ncout << \"przez 8: \" << p8 << endl; // 123\nreturn 0;\n}\n\n**Pascal:**\n```pascal\nprogram Podzielnosc;\nvar\nf: TextFile;\ns: String;\nn, p2, p8: Integer;\nbegin\nAssignFile(f, 'liczby.txt');\nReset(f);\np2 := 0; p8 := 0;\nwhile not Eof(f) do\nbegin\nReadln(f, s);\nn := Length(s);\nif (n >= 1) and (s[n] = '0') then Inc(p2);\nif (n >= 3) and (s[n] = '0') and (s[n-1] = '0') and (s[n-2] = '0') then Inc(p8);\nend;\nCloseFile(f);\nWriteln('przez 2: ', p2);\nWriteln('przez 8: ', p8);\nend.\n\n## Reference informatyczny - podzielność w systemie binarnym\n\n> Reference - Bity i podzielność:\n> - Bit najmniej znaczący (LSB) decyduje o parzystości: 0 = parzysta, 1 = nieparzysta.\n> - **Podzielność przez 2^k** ⟺ k najmłodszych bitów = 0.\n> - **Podzielność przez 3** w binarnym: brak prostej reguły, trzeba modulo arytmetyką.\n> - **Mod 2^k**: w arytmetyce komputerowej `n & ((1<<k)-1)` to n mod 2^k (operacja AND).\n> - W tym zadaniu działamy na **string** (liczby za duże dla int), więc sprawdzamy ostatnie znaki.\n\n## Schemat oceniania CKE\n\n> Klucz CKE (zadanie 4.2, max 3 pkt):\n> - **3 pkt** - poprawne obie liczby (przez 2: 500, przez 8: 123)\n> - **2 pkt** - poprawna tylko liczba podzielnych przez 8 ALBO tylko 250 wierszy (wynik: 121/27)\n> - **1 pkt** - poprawna tylko liczba podzielnych przez 2\n> - **0 pkt** - niepełna lub błędna albo brak\n\n## Typowe pułapki\n\n- **Podzielność przez 8 = trzy ostatnie zera**, nie tylko ostatnia cyfra (= podzielne przez 2).\n- **Off-by-one w indeksowaniu Pascal**: `s[Length(s)]` to ostatni znak (od 1!), w C++ `s[n-1]` (od 0).\n- **Plik z liczbami < 3 bity** - może spowodować błąd, sprawdź `n >= 3` przed `s[n-3]`.\n- Łatwo pomylić: \"podzielna przez 8\" ⟹ \"podzielna przez 2\" (relacja zawierania) - tutaj liczymy DZIELONE PRZEZ 2 (500) i ODDZIELNIE przez 8 (123).\n- Whitespace na końcu - `s.strip()` usuwa `\\n`, `\\r`, spacje. Bez tego ostatni znak to `\\n`.\n- **Trick połowy**: liczba podzielnych przez 2 = 500 to dokładnie połowa, więc dystrybucja końcówek bitów jest jednorodna.\n\n## Złożoność obliczeniowa\n\n- Sprawdzenie końcówki: O(1) (stała liczba znaków).\n- Przetworzenie pliku: O(N · L), gdzie N = 1000, L = 250. Praktycznie O(N) = O(1000).\n- Pamięć: O(L).","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 4.1.</p>\n<p>Przykład: dla zestawu liczb 101011010011001100000, 10001001, 100100, 101010010101011011000, 100011 - trzy liczby są podzielne przez 2 i dwie liczby są podzielne przez 8.</p>\n<p>Podaj, ile liczb w pliku liczby.txt jest podzielnych przez 2 oraz ile liczb jest podzielnych przez 8.</p>","solutions":[{"source":"maturazai","label":"maturazai.pl (AI)","kind":"text","html":"<h4>Poprawna odpowiedź</h4>\n<ul><li><strong>podzielne przez 2: 500</strong></li><li><strong>podzielne przez 8: 123</strong></li></ul>\n<h4>Sposób 1 - sprawdzanie końcówki zapisu binarnego</h4>\n<p><strong>Kluczowa obserwacja:</strong></p>\n<ul><li>Liczba binarna jest <strong>podzielna przez 2</strong> ⟺ kończy się na <strong>0</strong> (ostatni bit = 0).</li><li>Liczba binarna jest <strong>podzielna przez 4</strong> ⟺ kończy się na <strong>00</strong>.</li><li>Liczba binarna jest <strong>podzielna przez 8</strong> ⟺ kończy się na <strong>000</strong> (3 ostatnie bity = 0).</li><li>Ogólnie: podzielna przez 2^k ⟺ kończy się k zerami.</li></ul>\n<p><strong>Python:</strong><br>```python<br>licznik_2 = 0<br>licznik_8 = 0<br>with open(&#x27;liczby.txt&#x27;) as f:<br>for linia in f:<br>s = linia.strip()<br>if s.endswith(&#x27;0&#x27;):<br>licznik_2 += 1<br>if s.endswith(&#x27;000&#x27;):<br>licznik_8 += 1<br>print(&#x27;podzielne przez 2:&#x27;, licznik_2) # 500<br>print(&#x27;podzielne przez 8:&#x27;, licznik_8) # 123</p>\n<h4>Sposób 2 - implementacja w C++ i Pascal</h4>\n<p><strong>C++:</strong><br>```cpp<br>#include &lt;iostream&gt;<br>#include &lt;fstream&gt;<br>#include &lt;string&gt;<br>using namespace std;</p>\n<p>int main() {<br>ifstream plik(&quot;liczby.txt&quot;);<br>string s;<br>int p2 = 0, p8 = 0;<br>while (plik &gt;&gt; s) {<br>int n = s.length();<br>if (s[n-1] == &#x27;0&#x27;) p2++;<br>if (n &gt;= 3 &amp;&amp; s.substr(n-3) == &quot;000&quot;) p8++;<br>}<br>cout &lt;&lt; &quot;przez 2: &quot; &lt;&lt; p2 &lt;&lt; endl; // 500<br>cout &lt;&lt; &quot;przez 8: &quot; &lt;&lt; p8 &lt;&lt; endl; // 123<br>return 0;<br>}</p>\n<p><strong>Pascal:</strong><br>```pascal<br>program Podzielnosc;<br>var<br>f: TextFile;<br>s: String;<br>n, p2, p8: Integer;<br>begin<br>AssignFile(f, &#x27;liczby.txt&#x27;);<br>Reset(f);<br>p2 := 0; p8 := 0;<br>while not Eof(f) do<br>begin<br>Readln(f, s);<br>n := Length(s);<br>if (n &gt;= 1) and (s[n] = &#x27;0&#x27;) then Inc(p2);<br>if (n &gt;= 3) and (s[n] = &#x27;0&#x27;) and (s[n-1] = &#x27;0&#x27;) and (s[n-2] = &#x27;0&#x27;) then Inc(p8);<br>end;<br>CloseFile(f);<br>Writeln(&#x27;przez 2: &#x27;, p2);<br>Writeln(&#x27;przez 8: &#x27;, p8);<br>end.</p>\n<h4>Reference informatyczny - podzielność w systemie binarnym</h4>\n<blockquote>Reference - Bity i podzielność:<br>- Bit najmniej znaczący (LSB) decyduje o parzystości: 0 = parzysta, 1 = nieparzysta.<br>- <strong>Podzielność przez 2^k</strong> ⟺ k najmłodszych bitów = 0.<br>- <strong>Podzielność przez 3</strong> w binarnym: brak prostej reguły, trzeba modulo arytmetyką.<br>- <strong>Mod 2^k</strong>: w arytmetyce komputerowej <code>n &amp; ((1&lt;&lt;k)-1)</code> to n mod 2^k (operacja AND).<br>- W tym zadaniu działamy na <strong>string</strong> (liczby za duże dla int), więc sprawdzamy ostatnie znaki.</blockquote>\n<h4>Schemat oceniania CKE</h4>\n<blockquote>Klucz CKE (zadanie 4.2, max 3 pkt):<br>- <strong>3 pkt</strong> - poprawne obie liczby (przez 2: 500, przez 8: 123)<br>- <strong>2 pkt</strong> - poprawna tylko liczba podzielnych przez 8 ALBO tylko 250 wierszy (wynik: 121/27)<br>- <strong>1 pkt</strong> - poprawna tylko liczba podzielnych przez 2<br>- <strong>0 pkt</strong> - niepełna lub błędna albo brak</blockquote>\n<h4>Typowe pułapki</h4>\n<ul><li><strong>Podzielność przez 8 = trzy ostatnie zera</strong>, nie tylko ostatnia cyfra (= podzielne przez 2).</li><li><strong>Off-by-one w indeksowaniu Pascal</strong>: <code>s[Length(s)]</code> to ostatni znak (od 1!), w C++ <code>s[n-1]</code> (od 0).</li><li><strong>Plik z liczbami &lt; 3 bity</strong> - może spowodować błąd, sprawdź <code>n &gt;= 3</code> przed <code>s[n-3]</code>.</li><li>Łatwo pomylić: &quot;podzielna przez 8&quot; ⟹ &quot;podzielna przez 2&quot; (relacja zawierania) - tutaj liczymy DZIELONE PRZEZ 2 (500) i ODDZIELNIE przez 8 (123).</li><li>Whitespace na końcu - <code>s.strip()</code> usuwa <code>\\n</code>, <code>\\r</code>, spacje. Bez tego ostatni znak to <code>\\n</code>.</li><li><strong>Trick połowy</strong>: liczba podzielnych przez 2 = 500 to dokładnie połowa, więc dystrybucja końcówek bitów jest jednorodna.</li></ul>\n<h4>Złożoność obliczeniowa</h4>\n<ul><li>Sprawdzenie końcówki: O(1) (stała liczba znaków).</li><li>Przetworzenie pliku: O(N · L), gdzie N = 1000, L = 250. Praktycznie O(N) = O(1000).</li><li>Pamięć: O(L).</li></ul>"}]}