C Zbior Zadan Z Rozwiazaniami Tomasz Jasniewski Helion

Download as pdf or txt
Download as pdf or txt
You are on page 1of 126

Wszelkie prawa zastrzeżone.

Nieautoryzowane rozpowszechnianie całości


lub fragmentu niniejszej publikacji w jakiejkolwiek postaci jest zabronione.
Wykonywanie kopii metodą kserograficzną, fotograficzną, a także kopiowanie
książki na nośniku filmowym, magnetycznym lub innym powoduje naruszenie
praw autorskich niniejszej publikacji.

Wszystkie znaki występujące w tekście są zastrzeżonymi znakami firmowymi


bądź towarowymi ich właścicieli.

Autor oraz wydawca dołożyli wszelkich starań, by zawarte w tej książce


informacje były kompletne i rzetelne. Nie biorą jednak żadnej odpowiedzialności
ani za ich wykorzystanie, ani za związane z tym ewentualne naruszenie praw
patentowych lub autorskich. Autor oraz wydawca nie ponoszą również żadnej
odpowiedzialności za ewentualne szkody wynikłe z wykorzystania
informacji zawartych w książce.

Redaktor prowadzący: Szymon Szwajger


Projekt okładki: Studio Gravite / Olsztyn Obarek,
Pokoński, Pazdrijowski, Zaprucki

Helion S.A.
ul. Kościuszki 1c, 44-100 Gliwice
tel. 32 231 22 19, 32 230 98 63
e-mail: [email protected]
WWW: http://helion.pl (księgarnia internetowa, katalog książek)

Drogi Czytelniku!
Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres
http://helion.pl/user/opinie/cppzbz_ebook
Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję.

Materiały do książki znaleźć można pod adresem:


https://ftp.helion.pl/przyklady/cppzbz.zip

ISBN: 978-83-8322-803-7

Copyright © Tomasz Jaśniewski 2023

26589ec988c76404b19a97e88c6609a5
2
Spis treści

O autorze… i programowaniu 5
Powód powstania zbioru 5
Podziękowania 6
Charakterystyka opracowanego zbioru zadań 6
To musisz przeczytać! 7
Dane do zadań 9

CZĘŚĆ 1. (#1) Ślady życia (40 zadań) 11

CZĘŚĆ 2. (#2) Pierwotniaczki (75 zadań) 21

Rozwiązania 45
Część 1. (#1) Ślady życia 45
Część 2. (#2) Pierwotniaczki 65

26589ec988c76404b19a97e88c6609a5
2
4 SPIS TREŚCI

26589ec988c76404b19a97e88c6609a5
2
O autorze… i programowaniu

Jestem programistą tworzącym oprogramowanie automatyzujące i organizu-


jące działalność firm, jednak nie mniejszą przyjemność sprawia mi nauczanie
w szkole. Próbuję łączyć obie pasje, których wspólnym mianownikiem jest język
programowania. Postrzegam w nim coś więcej niż narzędzie dające pracę. Pro-
gramowanie to czysty akt kreacji, przygoda i źródło satysfakcji. To sztuka, choć
wyrażona liniami kodu, a nie pędzlem, bardziej logiką niż uczuciami. To strategia
działania realizowana w kolejnych iteracjach projektu aż do osiągnięcia celu.
To sztuka myślenia.

Tak przy okazji — właśnie dlatego, że jest to sztuka myślenia, programowanie


powinno być jednym z podstawowych narzędzi kształtowania umysłu dziecia-
ków w szkole. Nie trzeba od razu zostawać programistą, by skorzystać na sztuce
myślenia. O ileż mniej porażek w szkole przeżywałyby nasze dzieci i młodzież,
gdyby sprawniej wyciągały wnioski, szybciej dostrzegały wzorce, łatwiej pro-
jektowały kolejne kroki swoich działań dla osiągnięcia celu, aż wreszcie precy-
zyjniej wyrażały swoje myśli. O korzyściach i fali ukojenia dla nauczycieli pły-
nących z tego faktu nie wspomnę.

Moim zdaniem programowanie nie jest czymś odrębnym od języka naturalnego,


potrzebnym tylko wąskiej grupie zawodowców, ale — pomimo formalizmu języ-
ków programowania — jest jego fundamentalną cegiełką, wewnętrzną ukrytą
składową, bez której każde zdanie i każda treść byłyby tylko nieuporządkowanym
zbiorem nieporozumień. Tym, co czynimy, w sporym stopniu są funkcje i algo-
rytmy. A to, co mówimy, w dużym stopniu jest opisem tego, co czynimy. Progra-
mowanie pozwala dobrze projektować i lepiej zrozumieć mechanizmy funkcjo-
nowania rzeczy i zjawisk, dlatego nie może nie mieć pozytywnego wpływu na
kształtowanie się sposobu naszego myślenia, gdyż język naturalny, język myśli,
zawiera w sobie logikę, opis, celowość i ładunek informacji.

Powód powstania zbioru


Pracując w szkole i ucząc języków programowania, często stawałem przed proble-
mem ugruntowania i szlifowania zdobytych umiejętności, sprawdzania w prak-
tyce kolejnych porcji wiedzy, by móc je mierzyć i oceniać. Zanim zaczniemy pro-
gramować poważniejsze aplikacje, po drodze tworzymy mnóstwo kodu, czego
cel jest tylko jeden: sprawdzić siebie, poznać podstawy, zrozumieć elementarne
klocki tworzące komputerową rzeczywistość. Uważam, że to bardzo ważny
czas, którego nie można uniknąć i który powinien być dobrze wykorzystany.
Wielu uczniów, wyczuwając instynktownie, jak wielkie możliwości stoją przed
nimi, a równocześnie nie mając jeszcze wyraźnego obrazu tych możliwości,

26589ec988c76404b19a97e88c6609a5
2
6 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

a także nie posiadając żadnego doświadczenia, stawia pytania: „Co mam teraz
robić?”, „Jaki program napisać?”, „Jak wykorzystać to, co było na lekcjach?”. Jednym
słowem: „Co zrobić z tą małą porcją wiedzy, którą posiadam? Jak ją zwiększyć?”.
W odpowiedzi na to pytanie powstawał ten zbiór zadań. Jest to próba ukierun-
kowania, uporządkowania i wzbogacenia tego czasu, który spędzamy pomiędzy
pierwszą lekcją z Hello World! a pierwszą stworzoną samodzielnie przez nas
aplikacją, którą sprzedaliśmy. Czasu radosnej nauki, kiedy wszystko wydaje się
możliwe, a ogranicza nas tylko wyobraźnia.

Innym powodem powstania zbioru jest próba przeciwstawienia się negatyw-


nym trendom obecnym wśród młodzieży szkolnej, które w mojej ocenie wydają
się nasilać. Są to: spadające zdolności kreatywnego i abstrakcyjnego myślenia
oraz problemy ze skupieniem uwagi. Dodatkowo wydłuża się czas poświęcony
na zabawę kosztem nauki, co jeszcze bardziej demotywuje do podjęcia wysiłku
związanego z jakąkolwiek pożyteczną pracą. Zdaję sobie sprawę, że jest to nie-
znacząca próba przeciwstawienia się tym trendom. Wydaje mi się jednak, że
lepsze coś niż nic. A „lepsze” nie przyjdzie samo, trzeba je wypracować.

Podziękowania
Praca nad zbiorem to mieszanina frajdy i zmęczenia i kiedy do głosu dochodzi
to drugie, przeoczenie błędów jest nieuniknione. Dziękuję Grzegorzowi Gilowi
za udzielenie mi pomocy w wyłapywaniu błędów i za podrzucenie kilku alter-
natywnych rozwiązań zadań.

Charakterystyka opracowanego zbioru zadań


 Zbiór zadań jest podzielony na części zależne od posiadanych umiejętno-
ści, a te podzielone są tak, aby odpowiadały procesowi nauki języka. Wzra-
stający poziom wymaganych umiejętności w kolejnych zadaniach jest do-
stosowany do naturalnego wzrostu poziomu znajomości języka C++.
Proponowane rozwiązania do każdego zadania uwzględniają wymagane
umiejętności w poszczególnych częściach zbioru. Przykładowo: począt-
kująca osoba nie potrafi tworzyć funkcji i nie zna wszystkich kontenerów,
ale posiada już wiedzę o pętlach czy instrukcji warunkowej, zatem w pro-
ponowanym rozwiązaniu zadania wykorzystuje się tylko to, co wymie-
nione jest w wymaganiach do poszczególnych części zbioru.
 Zbiór w pierwszej kolejności pomaga w przygotowaniach do matury
z informatyki i podczas nauki programowania na studiach, uwzględnia-
jąc wymagania systemu oświaty. Jednak wraz ze wzrostem wymaganych
umiejętności zbiór przeprowadza przez wiele mechanizmów języka C++,
które w dużym stopniu przekraczają wymagania szkolne.
 Zbiór uwzględnia standard C++20.

26589ec988c76404b19a97e88c6609a5
2
O AUTORZE… I PROGRAMOWANIU 7

 Zadania zostały przetestowane na żywych organizmach uczniów klas in-


formatycznych, z różnym skutkiem .
 Do każdego zadania istnieje proponowane rozwiązanie. Niekiedy jest ich
kilka — czasami eleganckie i krótkie w zapisie rozwiązanie zadania jest
obarczone koniecznością dużego wykorzystania zasobów komputera, a nie-
kiedy większa ilość kodu podnosi jego czytelność i przyśpiesza działanie.
 W zbiorze zadań założono, że użytkownik ma wiedzę o języku C++ i dla-
tego nie postawiono sobie w nim za cel tłumaczenia jego elementów.
Jednocześnie proponowane zagadnienia pełne są komentarzy, które odkry-
wają tajemnice języka poprzez przykłady. Niniejsze opracowanie świetnie
uzupełnia i domyka proces nauki C++, jednak same zadania nie wystarczą
do poznania tego języka.

To musisz przeczytać!
Ten fragment zbioru zawiera bardzo ważne informacje dotyczące zadań.
Przeczytaj je, inaczej możesz nie rozumieć oznaczeń stosowanych w zbiorze,
a treść zadań może rodzić niepotrzebne pytania.
 Jeżeli zadanie jasno czegoś nie określa, to oznacza, że masz dowolność
interpretacji treści zgodnie z logiką jego rozwiązania. Jeżeli masz lepszy
pomysł na zadanie, wykonaj je raz jeszcze! Jeżeli zadanie zrodziło w Two-
jej głowie pomysł na jakiś wspaniały program, napisz go! Takie podejście
pozwala wycisnąć maksimum z zadania i zwiększyć Twoje umiejętności.
Nasz mózg zgłębia narzędzie, którego używa, z czasem zwiększając moż-
liwości tegoż narzędzia poprzez kreatywne i twórcze pomysły. Gdy nagle
dostrzegasz lepsze rozwiązanie, jest to coś naturalnego i nie należy tego
pomijać, ale trzeba iść za ciosem i zrobić to! Tak rodzą się najlepsi.
 Liczba w nawiasie kwadratowym w nagłówku zadania (np. [6]) to suge-
rowana liczba punktów za zadanie, a zarazem przybliżona informacja
o trudności zadania w danej grupie umiejętności. Miarą trudności jest
moje widzi-mi-się, zatem jest to miara subiektywna. Wagi punktów w róż-
nych grupach są różne. Punktacja zadania (np. [1]) w grupie początkowej
ma mniejszą wagę i mniejszy stopień trudności od takiej samej punktacji
w grupie późniejszej, która wymaga większej porcji umiejętności. Nie-
kiedy punktacja jednego zadania jest rozbita i w treści występują takie
oznaczenia jak np. [3,], a następnie np. [2], co wskazuje na to, że w zada-
niu są etapy punktowane oddzielnie. Punktacja może wesprzeć nauczy-
ciela przy planowaniu np. sprawdzianu, proszę ją jednak traktować
orientacyjnie. Zatem [3,] i [2] to razem [5] punktów możliwych za po-
szczególne fragmenty zadania.
 We wszystkich zadaniach zakładamy poprawność danych (podobnie jest
na maturze!). Programy z rozwiązaniami zazwyczaj nie zawierają ob-
sługi błędów. Jeżeli dane początkowe mają być np. liczbami dodatnimi,
to takimi dokładnie mają być. Czasami jednak w rozwiązaniu wykonuję

26589ec988c76404b19a97e88c6609a5
2
8 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

kilka podstawowych testów, np. na nieudany odczyt danych z pliku albo


na to, czy liczba przy dzieleniu nie jest zerem, lub czy napis, który nie
może być pusty, faktycznie taki nie jest, itd.
 Czasami rozwiązania do zadań będą zapisane na kilka sposobów. Nie-
które są wydajniejsze lub bardziej skondensowane w zapisie, ale przez
to mniej czytelne. Inne przeciwnie.
 Rozwiązania są niekiedy opatrywane komentarzami, które przybliżają frag-
menty kodu. Jednak nie wszędzie komentarz jest obecny. Czytanie kodu
ze zrozumieniem jest częścią procesu nauki języka i zakładam wzrost tej
umiejętności wraz z kolejnymi zadaniami. Jeżeli mogę zasugerować coś
nauczycielom, to jest to odpytywanie z czytania kodu ze zrozumieniem,
polegające na dokładnym wyjaśnieniu zapisu i próbie określenia, co bę-
dzie wynikiem działania programu — to dobra praktyka. Weryfikuje, czy
ktoś z językiem rzeczywiście pracuje, czy zapytany tworzy w przeraże-
niu po prostu nową historię…
 Niekiedy rozwiązanie zadania nie daje konkretnego wyniku, ale ma zbu-
dować pewien algorytm/funkcjonalność. Dlatego w celach kontrolnych
podawane będą jakieś dane przykładowe, mimo że zadanie bazuje np. na
danych generowanych losowo. Ma to na celu weryfikację poprawności
algorytmu/programu dla wspólnych danych.
 Czasem podaję pewną sugestię, propozycję napisania we własnym zakre-
sie jakiegoś programu, większego projektu. Nie jest to jednak zadanie.
 Niektóre zadania naprawdę nie stanowią wyzwania, są raczej okazją do
lepszego poznania gramatyki języka. Rozwiązania takich zadań mają bar-
dziej charakter informacyjny, zapoznawczy, wprowadzający w jakąś przy-
datną technikę, którą zauważysz, analizując proponowane rozwiązanie.
 Niektóre zadania są podobne dla różnych części uwzględniających sto-
pień znajomości języka. Jest tak dlatego, że pewne rozwiązania warto za-
projektować z uwzględnieniem postępu w rozwoju języka. Pozwala to zo-
baczyć, jak bogaty język ułatwia programowanie i zwiększa możliwości
potencjalnego rozwoju programu. Rozwiązania zadań w poszczególnych
częściach zbioru zakładają tylko posiadanie niektórych umiejętności
programowania w języku C++. Oznacza to, że pewne zadania w oczywi-
sty sposób da się zrobić szybciej/sprytniej, ale będzie to możliwe w przy-
szłości, dopiero po poznaniu dalszych własności C++. Takie podejście
wiąże się z prostym faktem, że uczymy się od podstaw, a chcemy rozwią-
zywać zadania, posiadając nawet pewne minimalne umiejętności. Dlatego
z czasem warto wrócić do początkowych zadań i rozwiązać je, stosując
metody i umiejętności nabyte w późniejszym etapie kształcenia.
 Powinno się porównać własne rozwiązanie z proponowanym. Być może
nauczysz się czegoś nowego? Jeżeli Twoje rozwiązanie jest lepsze i bardziej
eleganckie, to masz darmową satysfakcję. A jeżeli nie, to masz darmową
porcję wiedzy i umiejętności.

26589ec988c76404b19a97e88c6609a5
2
O AUTORZE… I PROGRAMOWANIU 9

 W zadaniach oraz proponowanych ich rozwiązaniach nie zawsze wyko-


rzystywane są wszystkie wymienione wymagane umiejętności w danej
części zbioru. Lista umiejętności jest raczej pewnym zakresem, polem,
w obrębie którego się poruszamy.
 Druga część zbioru zadań, numerowana #2, zawiera także umiejętności
z pierwszej części.
 Zadania rozwiązywałem, korzystając przeważnie z Visual Studio 2022, zda-
rzało mi się jednak korzystać także z CodeBlocks. W niektórych sytuacjach
może istnieć problem z uzyskaniem polskiej czcionki. Wiąże się to zarówno
z kodowaniem czcionki w pliku, jak i z ustawieniami kodowymi w termi-
nalu, do tego środowisko IDE i pewne ustawienia lokalne mogą wpływać
na to, jak są wyświetlane polskie znaki (i czy w ogóle są). Zwróćcie na to
uwagę, gdyż może się okazać, że to, co u mnie wyświetlało się z uwzględ-
nieniem polskiej czcionki, u Was może jej nie uwzględniać, a na ekranie
terminala w miejsce naszych „ś” czy „Ż” pojawią się niedrukowalne,
dziwne znaki/krzaki. Musicie sobie z tym poradzić samodzielnie…

Dane do zadań
Poniższy link umożliwi Ci pobieranie plików z danymi do zadań:
https://ftp.helion.pl/przyklady/cppzbz.zip

W udostępnionym katalogu znajdziesz podkatalogi oznakowane #1 albo #2, co


odpowiada kolejnym częściom zbioru. Pliki zwykle zawierają w nazwie numer
zadania, np. plik 2_dane.txt odwołuje się do zadania nr 2. Jeżeli plików do zadania
będzie więcej, nazwy wszystkich plików zostaną wymienione w treści zadania.

26589ec988c76404b19a97e88c6609a5
2
10 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

26589ec988c76404b19a97e88c6609a5
2
CZĘŚĆ 1. (#1) Ślady życia (40 zadań)

Wymagane umiejętności, znajomość zagadnień:


 sprawna obsługa środowiska programistycznego, np. Visual Studio
2019/2022 albo CodeBlocks;
 podstawowy schemat pliku .cpp ze źródłem w języku C++;
 podstawowe typy liczbowe całkowite i „z przecinkiem”:
o int, long long int, short int wraz z modyfikatorem typu unsigned;
o float, double;
 różne operacje na liczbach (+, –, /, *, % itd.);
 tworzenie zmiennych różnego typu, przypisywanie wartości do zmiennych,
modyfikowanie wartości zmiennych (operator =), rozróżnianie zmiennej
globalnej (poza main()) oraz lokalnej (np. w pętli for);
 typ bool, operacje logiczne (and, or, ||, &&, !) , operatory porównania
(>, <, !=, <=, >=), pojęcie warunku, znajomość wartości true/false, wiedza
o interpretacji prawdy i fałszu przez komputer (np. liczba 0 to false,
a nie 0 to true itp.);
 instrukcja warunkowa if-else, wyrażenie warunkowe ( ) ? _ : _ ;;
 pętle for, while, do..while, wykorzystanie typu auto w pętli for, świadomość
zasięgu i czasu życia zmiennych inicjowanych w pętli for;
 typ char (znajomość faktu, że zmienne typu char mogą być interpretowane
jako liczby);
 kontener vector<> i podstawowe operacje z nim związane (sprawdzanie
rozmiaru, wstawianie elementów, usuwanie elementów, używanie itera-
torów .begin(), .end());
o typ size_t i jego związek np. z liczbą elementów w vector<>;
 kontener array<> (z przyczyn praktycznych będę wyłącznie korzystać
z vector<> zamiast array<>);
 starsze tablice [] (w rozwiązaniach je pomijam, będę korzystać z vector<>);
 instrukcje wejścia/wyjścia (na konsolę) cout, cin i operatory strumienia
<< oraz >>;
 operatory ++, --, +=, *=, -=, /=, %=;
 rozumienie i znajomość kolejności działań i priorytetów wyżej wymie-
nionych operatorów;
 funkcje z biblioteki <cmath>, takie jak: pow(), abs(), sqrt();
 korzystanie z typedef np. w celu utworzenia skrótu dla długich typów.

26589ec988c76404b19a97e88c6609a5
2
12 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Czasami używam zwrotu „pobierz z klawiatury”. Oznacza on wprowadzenie war-


tości do zmiennych za pomocą klawiatury, w trakcie działania programu (cin >>).

Zwroty „uwzględnij małe litery angielskie”, „uwzględnij tylko cyfry” i inne podobne
zwroty oznaczają, że wprowadzane dane mogą być tylko takie i nie zakładamy wy-
korzystania innych.

Zadania
Zadanie 1.1 [2]
Pobierz z klawiatury trzy nieujemne liczby całkowite. Znajdź największą z nich.
Wyświetl sumę pozostałych liczb tyle razy, ile wynosi wartość największej
liczby. [2]

Zadanie 1.2 [1]


Pobraną z klawiatury liczbę całkowitą zweryfikuj pod kątem parzystości.
Wyświetl tak lub nie, gdy jest lub nie jest parzysta. [1]

Zadanie 1.3 [1]


Pobierz liczbę całkowitą z klawiatury i sprawdź, czy jest podzielna: przez 3
i przez 5; przez 3, ale nie przez 5; przez 5, ale nie przez 3; ani przez 3, ani przez 5.
Właściwą odpowiedź wyświetl na ekranie. [1]

Zadanie 1.4 [1]


Pobierz znak (char) z klawiatury. Sprawdź, czy to samogłoska, spółgłoska, czy
cyfra. Poinformuj o tym, jaki to znak. Uwzględnij tylko małe litery alfabetu an-
gielskiego i cyfry. [1]

Zadanie 1.5 [1]


Masz takie wyrażenie: (((a1+a2)*a3)-a4)/a5 (elementy od a1 do a5 są typu float).
Pobierz z klawiatury każdą ze zmiennych a1 do a5, oblicz wartość wyrażenia
i wyświetl wynik. [1]

Zaprojektuj program tak, aby w przypadku dzielenia przez zero informował o tym
i nie wykonywał działania.

26589ec988c76404b19a97e88c6609a5
2
CZĘŚĆ 1. (#1) ŚLADY ŻYCIA (40 ZADAŃ) 13

Zadanie 1.6 [1]


Pobierz pięć liczb z klawiatury i wyświetl informację, ile spośród nich było pa-
rzystych, a ile nieparzystych. [1]

Zadanie 1.7 [1]


Pobieraj znaki z klawiatury aż do wprowadzenia znaku x. Ile znaków pobrano? [1]

Zadanie 1.8 [2]


Pobierz z klawiatury dwie liczby (float) i znak działania (jeden z tych: *, +, –, /).
W zależności od znaku wykonaj na pobranych dwóch liczbach odpowiednie
działanie i poinformuj o wyniku. Zwróć uwagę na dzielenie przez 0! Przykład:
dla pobranej liczby 3 i 9.5 oraz znaku + zwróć sumę 12.5. [2]

Sprawdź też operację przy zamianie liczb miejscami. Jeżeli wynik różni się od wcze-
śniejszego, wyświetl oba wyniki. Jeżeli jest taki sam, wyświetl go tylko jeden raz.
Na przykład dla liczb 5 i 2 oraz znaku / (dzielenie) trzeba wyświetlić 5/2 i 2/5, po-
nieważ dają różny wynik.

Zadanie 1.9 [1]


Pobierz liczbę całkowitą z klawiatury i wykonaj na niej poniższe operacje: jeżeli
liczba była ujemna, zmniejsz ją o 1; jeżeli liczba była dodatnia, zwiększ ją o 1;
jeżeli była zerem, pozostaw bez zmian; Wyświetl liczbę po zmianach. Następnie
określ parzystość liczby po zmianach i wyświetl informację na ten temat
(tak/nie). [1]

Zadanie 1.10 [1]


Wyświetl liczby całkowite od 1 do 100. Spróbuj zrobić to, wykorzystując różne
pętle (for, while, do..while). [1]

Zadanie 1.11 [1]


Wyświetl liczby całkowite od 100 do 10 włącznie, pomijając podzielne przez 7. [1]

Zadanie 1.12 [1]


Wyświetl liczby całkowite od –25 do 25 z pominięciem 0. [1]

Zadanie 1.13 [1]


Wyświetl liczby całkowite od 1 do 120 włącznie, z pominięciem liczb podzielnych
równocześnie przez 11 i 5. Wyświetl informacje, ile liczb się wyświetliło, a ile
zostało pominiętych. [1]

26589ec988c76404b19a97e88c6609a5
2
14 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie 1.14 [1]


Odgadnij wzór ciągu, a następnie wyświetl jego sto elementów. Początek ciągu:
3,1,2,1,3,1,2,1,.... [1]

Zadanie 1.15 [2]


Odgadnij wzór ciągu, a następnie wyświetl jego sto elementów. Początek ciągu:
1,2,2,3,3,3,4,4,4,4,.... [2]

Zadanie 1.16 [2]


Odgadnij wzór ciągu, a następnie wyświetl jego sto elementów. Początek ciągu:
100,99,97,94,90,85,.... [2]

Zadanie 1.17 [1]


Odgadnij wzór ciągu, a następnie wyświetl jego sto elementów. Początek ciągu:
6,2,8,3,10,4,12,5,14,6,.... [1]

Zadanie 1.18 [1]


Pobieraj liczbę z klawiatury i wyświetlaj jej dwukrotność. Operację powtarzaj,
dopóki nie zostanie wpisana wartość pomiędzy 1 a 10 włącznie. [1]

Zadanie 1.19 [1]


Wyświetl wszystkie liczby podzielne przez 6 ze zbioru od 0 do 1000 włącznie. [1]

Zadanie 1.20 [1]


Utwórz wektor i wstaw do niego dziesięć dowolnych liczb. Utwórz drugi wektor,
który na początku zawiera liczby parzyste z pierwszego wektora, a potem po-
zostałe. Wyświetl oba wektory. [1]

Zadanie 1.21 [1]


Pobierz pięć liczb z klawiatury. Jeżeli tworzą ciąg rosnący (zgodnie z kolejnością
pobierania), poinformuj o tym. [1]

Zadanie 1.22 [1]


Pobieraj liczby z klawiatury i wkładaj je do tablicy/wektora. Pobieranie ma się
zakończyć, gdy zostanie wprowadzona dwa razy z rzędu taka sama liczba. [1]

Zadanie 1.23 [2]


Pobieraj liczby z klawiatury i wkładaj je do wektora pod warunkiem, że taka
liczba jeszcze w wektorze nie istnieje. Jeżeli istnieje, zignoruj ją i pobieraj dalej.
Pobieranie zakończy się, gdy wektor będzie zawierał dziesięć liczb. [2]

26589ec988c76404b19a97e88c6609a5
2
CZĘŚĆ 1. (#1) ŚLADY ŻYCIA (40 ZADAŃ) 15

Zadanie 1.24 [2]


Pobieraj z klawiatury znaki (bez polskich ogonków i bez dużych liter) i wprowa-
dzaj je do wektora według zasady: samogłoski zawsze na początku wektora, po-
zostałe znaki na końcu wektora. Jeżeli pojawi się znak * lub #, nie wstawiaj ich,
tylko usuń z wektora pierwszy znak (dla *) lub ostatni (dla #), o ile jest co usuwać.
Zakończ pętlę pobierania i wstawiania, gdy wprowadzony będzie znak !. [2]

Zadanie 1.25 [1]


Pobieraj w pętli liczby z klawiatury. Wkładaj je do wektora V. Wnętrze pętli to
następujące kroki:
1. Pobierz liczbę i wprowadź ją na koniec wektora.
2. Pobierz liczbę i wprowadź ją na koniec wektora (tak, takie same
polecenie w ramach kroku pętli).
3. Jeżeli iloczyn dwóch ostatnich liczb z wektora nie przekracza 1000,
wprowadź również ten iloczyn do wektora V i wróć do punktu 1., a jeżeli
ten iloczyn przekroczył wartość 1000, zakończ pętlę. [1]

Zadanie 1.26 [6]


Utwórz wektor zawierający następujące cyfry (można skopiować z pliku
26_vector.txt):
vector<int> v={1,2,4,3,6,8,7,7,8,3,4,5,6,7,1,3,9,1,0,4,2,3,6,9};

Znajdź w wektorze i wyświetl wszystkie podciągi trójelementowe (trzy kolejne


liczby wektora), które tworzą ciągi niemalejące. [1,]
Znajdź jeden najdłuższy podciąg niemalejący. [3,]
Policz liczbę wystąpień każdej liczby w wektorze. [2]

Zadanie 1.27 [7]


Utwórz trzy wektory z następującą zawartością: v1={1,3,5,7,9}, v2={1,4,7,11,15},
v3={1,2,3,4,5,6,7,8,9,20} (plik 27_vectory.txt) Potraktuj je jak zbiory, w któ-
rych każdy element może wystąpić tylko jeden raz. Przykładowo, po dodaniu
do zbioru v1 liczby 5, zbiór nie uległby zmianie, gdyż 5 już tam jest. Dla podanych
wektorów/zbiorów wyświetl:
a) część wspólną zbiorów: v1 i v2, [1,]
b) różnicę zbioru v3 i sumy zbiorów v1+v2: v3–(v1+v2), [4,]
c) sumę wszystkich zbiorów v1, v2 i v3: v1+v2+v3. [2]

Różnica zbioru A – B to takie elementy A, których nie ma w B. Suma zbiorów A + B


to wszystkie elementy z A i B (bez powtórzeń). Część wspólna A i B to tylko takie
elementy, którą są równocześnie w A i B.

26589ec988c76404b19a97e88c6609a5
2
16 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie można wykonać błyskawicznie, wykorzystując bibliotekę <set> wraz z kon-


tenerem set<>. Jednak w tej części zbioru zadań założono brak znajomości tych
kontenerów. Proponowane odpowiedzi w zbiorze zadań wykorzystują tylko te
umiejętności, które są wspomniane na początku tej części.

Zadanie 1.28 [2]


Pobieraj w pętli jeden znak (char). Ignoruj znaki niebędące znakami cyfr. Przerwij
pętlę, gdy zbierzesz pięć znaków będących cyframi, np. '1', '4', '3', '5', '0'.
Utwórz zmienną całkowitą, która będzie liczbą utworzoną z tych cyfr. Ma to być
faktyczna zmienna, np. typu long long int. Dla podanego przykładu byłaby to
liczba 14 350. [2]

Zadanie 1.29 [5]


Kasia postanowiła w 2022 roku zaznaczać dni, w których udało jej się pilnować
diety, jak również te, w których jej się to nie udało. Dla każdego dnia roku, numero-
wanego od 1 do 365, utwórz dla Kasi wektor vector<bool> i skopiuj do niego nastę-
pujące wartości, gdzie 1 to wartość true, a 0 to wartość false (plik 29_dieta.txt).
1,1,0,1,0,0,0,0,0,1,1,1,1,1,0,1,0,0,1,0,1,1,0,0,0,1,1,0,0,1,1,1,0,0,1,0,0,0,0,0,1,1,
0,0,0,1,1,1,1,1,0,0,0,1,1,0,1,0,1,0,0,0,1,0,0,0,0,1,0,1,1,1,1,1,1,1,1,0,0,1,0,0,1,1,
1,0,1,0,0,1,1,0,1,0,0,1,1,0,1,1,1,0,0,0,0,1,0,0,0,1,1,0,1,0,1,1,0,1,0,1,1,1,1,1,1,0,
0,1,0,0,1,1,1,0,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,0,1,1,0,1,1,0,0,1,1,0,0,1,0,0,1,0,
0,0,0,1,0,1,0,1,0,0,1,0,1,1,0,0,1,0,0,0,1,0,0,1,1,0,1,0,1,0,1,0,1,0,1,1,0,1,1,1,0,0,
1,1,0,0,1,0,0,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,0,0,1,1,1,1,1,1,1,0,1,0,1,0,0,0,1,1,0,0,
0,1,0,0,0,0,1,1,0,1,0,1,1,0,0,0,1,1,1,1,0,1,0,0,1,0,1,1,0,0,1,0,0,0,1,0,0,0,0,0,1,1,
0,1,1,1,1,0,1,0,0,1,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,0,0,1,1,1,0,0,0,1,1,1,1,0,0,1,0,0,
0,1,1,1,1,0,0,0,1,1,0,1,0,1,0,0,1,1,1,1,1,0,1,0,1,1,1,1,1

Każda cyfra (0 lub 1) to kolejny dzień udany (1) lub nieudany (0).

Utwórz odpowiedni wektor zawierający wyżej wymienione dane. Odpowiedz


na następujące pytania:
a) Przez ile dni w roku Kasia odnosiła sukces dietetyczny? [1,]
b) Ile było okresów trwających przynajmniej pięć dni z rzędu, które
stanowiły porażkę dietetyczną? Podaj numer dnia w roku
rozpoczynającego każdy z okresów. [4]

Zadanie 1.30 [3]


Pewien kosmiczny blob, okrążający swoją gwiazdę, postanowił zwiększyć swoją
masę. Na początku blob ważył 1 kg i przez pierwsze dwa okrążenia swojej gwiazdy
nie udało mu się wzrosnąć. Ale przy trzecim okrążeniu blob ważył tyle, ile wy-
nosiła suma wartości jego wagi z ostatnich dwóch okrążeń. Od tego momentu
wszystko potoczyło się błyskawicznie. Kolejne okrążenie ponownie zaowoco-
wało wagą bloba równą sumie wag z ostatnich dwóch okrążeń i ten schemat
trwał już cały czas. Ile wynosiła waga kosmicznego bloba po trzynastym okrąże-
niu macierzystej gwiazdy? Przyjmij, że dwa pierwsze okrążenia to waga 1 i 1. [3]

26589ec988c76404b19a97e88c6609a5
2
CZĘŚĆ 1. (#1) ŚLADY ŻYCIA (40 ZADAŃ) 17

Zadanie 1.31 [1]


Spróbuj odpowiedzieć na pytania do podanego kodu, wykorzystując tylko swoją
wiedzę i nie używając kompilatora:
int a = 0;
// a) Co się wyświetli w dwóch następnych instrukcjach? Wyjaśnij to.
cout << ++a << endl;
cout << a << endl;
// b) Co się wyświetli po wykonaniu dwóch poniższych instrukcji? Wyjaśnij to.
cout << (a++ - 1 && 1) << endl;
cout << a << endl;
// c) A co tu się wyświetli?
cout << 1 + 2 * 3 - 4 / 5 << endl;
// d) Poniższa instrukcja nie jest poprawna. Potrafisz wyjaśnić dlaczego?
cout << true and false << endl;

Pytania znajdują się w komentarzach i zostały oznaczone jako a), b), c) i d). [1]

Zadanie 1.32 [2]


Skopiuj poniższy wektor do swojego kodu lub skopiuj go z pliku 32_wektor.txt.
vector<int> x = { 2,7,1,1,4,9,3,2,1,4,1,9,6,1,3,0,1,2,3,6,8,5,6,9,
3,0,8,1,8,8,7,0,7,8,5,0,2,2,3,7,1,7,2,4,7,7,5,9,0,7,7,9,2,2,2,7,
0,0,5,4,6,3,9,3,5,1,0,0,9,2,9,2,8,5,0,8,5,7,0,9,6,4,9,7,8,8,6,5,
4,3,2,5,8,9,4,6,8,7,9,9 };

Wyświetl kolejne liczby określające odległość między kolejnymi wartościami 9


w wektorze. Przyjmij, że sąsiadujące bezpośrednio dziewiątki dzieli odległość 0,
dziewiątki rozdzielone jedną liczbą (np. 9, 5, 9) dzieli odległość 1 itd. [2]

Zadanie 1.33 [2]


Skopiuj poniższy wektor do swojego kodu lub skopiuj go z pliku 33_wektor.txt.
vector<int> x = { 2,7,1,1,4,9,3,2,1,4,1,9,6,1,3,0,1,2,3,6,8,5,6,9,
3,0,8,1,8,8,7,0,7,8,5,0,2,2,3,7,1,7,2,4,7,7,5,9,0,7,7,9,2,2,2,7,
0,0,5,4,6,3,9,3,5,1,0,0,9,2,9,2,8,5,0,8,5,7,0,9,6,4,9,7,8,8,6,5,
4,3,2,5,8,9,4,6,8,7,9,9 };

Odpowiedz na następujące pytania:


a) Ile razy wystąpiła sytuacja, w której dwie sąsiednie liczby były
identyczne? [1,]
b) Ile razy wystąpiła sytuacja, w której dwie sąsiednie liczby łącznie
miały wartość 10? [1]

Zadanie 1.34 [2]


Pobieraj w pętli znak (char) z klawiatury. Za każdym razem po pobraniu znaku wy-
świetlaj jego wartość całkowitą (int). Gdy suma tych wartości uzyskana z kolej-
nych znaków przekroczy 350, zakończ pętlę. Wyświetlaj również po pobraniu
znaku aktualny stan sumy. [1,]
Ogranicz się do małych i dużych liter angielskich oraz cyfr. Jeżeli zostanie wpro-
wadzony inny znak, zignoruj go. [1]

26589ec988c76404b19a97e88c6609a5
2
18 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie 1.35 [1]


Wstaw do wektora v dziesięć dowolnych liczb całkowitych. Korzystając tylko
z iteratora zwracanego przez funkcję v.begin()/v.end() lub korzystając z funkcji
v.front()/v.back(), wyświetl wszystkie jego elementy (w dowolnej kolejności,
żadnego nie pomijając). [1]

Możesz przestawiać elementy wektora i je usuwać. Nie możesz jednak w żadnym


momencie użyć notacji z pozycją, np. v[0], ani wykorzystać pętli jak w przykła-
dzie poniżej:
for (auto e : v)

Zadanie 1.36 [1]


Sprawdź, czy trzy zmienne typu float mogą utworzyć trójkąt prostokątny, przy
założeniu, że wartości zmiennych są długościami boków. Dla ułatwienia przyjmij,
że zmienne są zawsze >0. Jeżeli istnieje możliwość utworzenia trójkąta, poin-
formuj o tym odpowiednią wiadomością. Możesz wykorzystać to, że w trójkącie
prostokątnym suma kwadratów długości przyprostokątnych wynosi tyle samo,
ile kwadrat długości przeciwprostokątnej: (a^2+b^2=c^2). [1]

Zadanie 1.37 [1]


Dla dwóch liczb, float A i float B, wykonaj operację mnożenia (A*B), nie korzy-
stając ze znaku mnożenia *. Wykonaj to samo dla A typu float oraz B typu int,
ale tym razem nie możesz użyć * ani / (mnożenia ani dzielenia). [1]

Zadanie 1.38 [3]


W podanym ciągu poszukaj wszystkich podciągów, których suma wynosi 10. Pokaż
elementy je tworzące i pozycje tych elementów (ciąg znajduje się również w pliku
38_ciag.txt). Przez podciąg rozumiemy fragment zbioru składający się z sąsia-
dujących ze sobą liczb, czyli np. podciąg czteroelementowy to dowolne cztery
sąsiadujące ze sobą liczby z początkowego zbioru/wektora, jedna po drugiej,
bez omijania jakiejkolwiek. Na przykład {1,2,3,2} to podciąg składający się
z pierwszych czterech liczb całego ciągu. [3]
{1,2,3,2,5,6,9,1,3,7,5,8,0,9,3,1,2,5,7,6,3,4,2,1,0,8,9,7,8,4,6,3,2,5,4,7,8,9,1,3,2,5,
4,7,5,6,8,0,1,2,3,6,5,8,7,1,1,2,3,4,4,5,5,6,8,9,0,9,8,1,9,7,5,4,1,2,7,6,9,3,4,2,6};

26589ec988c76404b19a97e88c6609a5
2
CZĘŚĆ 1. (#1) ŚLADY ŻYCIA (40 ZADAŃ) 19

Zadanie 1.39 [3]


Skopiuj do wektora następujące znaki:
{'x','P','Q','4','\n','%','u','@','e',
'T','B','$', '!',':','"','1','<','d','k','L','$',')','$','B','x',
'w','q','P','c','X','B','>','?','[','r','x','$', '#','}','|','d',
'l','n','b','V','!'};

(znajdują się one również w pliku 39_znaki.txt). Wyświetl te znaki z wektora,


które się powtórzyły, ale nie leżą na jego początku ani końcu. Wyświetl je jeden
raz. Podaj sumę, którą tworzą wszystkie występujące w wektorze znaki będące
cyfrą (np. znak '8' i znak '2' daje sumę 10). [3]

Zadanie 1.40 [50]


Gratulacje! Jeżeli masz za sobą wszystkie zadania, weź prysznic albo gorącą kąpiel
i połóż się spać. Gdy tylko się obudzisz, rozpocznij wykonywanie zadań z na-
stępnej części zbioru. Powodzenia! [50]

26589ec988c76404b19a97e88c6609a5
2
20 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

26589ec988c76404b19a97e88c6609a5
2
CZĘŚĆ 2. (#2) Pierwotniaczki (75 zadań)

Umiejętności z części drugiej (#2), Pierwotniaczki, zawierają umiejętności


z części pierwszej (#1), Ślady życia.

Wymagane umiejętności, znajomość zagadnień:


 tworzenie funkcji, w szczególności przekazywanie argumentów różnego
typu (np. wektora, tablicy) do funkcji, przekazywanie przez wartość, przez
referencję; zwracanie wartości przez funkcję;
 tworzenie funkcji rekurencyjnych;
 typ void;
 przeciążenie funkcji, rozróżnianie i stosowanie deklaracji funkcji i defi-
nicji funkcji;
 typ pair<__,__> (para);
 rozumienie zagnieżdżania typów, np. wektor zawierający wektor
vector<vector<int>> albo para z wektorem pair<int, vector<string>>;
 losowanie liczb całkowitych i zmiennoprzecinkowych: biblioteka <random>
lub przynajmniej proste wykorzystanie funkcji rand() wraz z operatorem %;
 operacje na plikach (podstawowy odczyt i zapis) za pomocą >> , << lub
z użyciem getline(), biblioteki <fstream> oraz <string>;
 wstawianie pobranych z pliku danych do różnych zmiennych/tablic/
kontenerów/kontenerów zagnieżdżonych/struktur;
 napisy/typ string (różne operacje na napisach, przeszukiwanie itp., zna-
jomość string::npos), działania na napisach;
 wchar_t, wstring, wcin, wcout, wifstream, wofstream i związane z tym róż-
nice względem string, literał napisów dla wstring (L"napis");
 funkcje konwertujące (np. stoi(), stod(), to_string());
 operacje na bitach, biblioteka <bitset> i typ bitset<N>, operatory bitowe,
przesunięcia bitowe itp.;
 tworzenie struktury (struct) jako własnego typu złożonego;
 proste rzutowanie typu (rozumienie, kiedy kompilator może stosować
domyślną konwersję między typami);
 przydatna jest orientacja w komunikatach zgłaszanych przez kompilator
(niekoniecznie przy rozwiązywaniu zadań);
 manipulatory dla cout: fixed, setprecision z biblioteki <iomanip>;
 try {} catch () {}: podstawowe użycie, znajomość zastosowania.

26589ec988c76404b19a97e88c6609a5
2
22 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

W tej części zbioru podczas rozwiązywania zadań twórz jak najwięcej funkcji. Oczy-
wiście z zachowaniem zdrowego rozsądku. Szukaj fragmentów kodu, który się po-
wtarza, i twórz z niego funkcje, opatrując je sugestywnymi nazwami. Trzy proste
funkcje, dobrze nazwane i wywołujące siebie, mogą być o wiele czytelniejsze niż
jedna, długa, zawiła i do tego źle nazwana.

Zadania
Zadanie 2.1 [1]
Wyświetl swoje imię w pętli tyle razy, ile jest w tym imieniu samogłosek (uwzględ-
nij sześć samogłosek, to jest "eyuioa"). [1]

Zadanie 2.2 [2]


Wylosuj trzy liczby i umieść je w wektorze. Utwórz funkcję, która znajduje naj-
większą liczbę w przekazanym do niej wektorze i zwraca ją, a z wektora usuwa.
Jeżeli liczba ta wystąpiła w wektorze wiele razy, usuń tylko jedną, dowolną.
Wyświetl sumę pozostałych liczb tyle razy, ile wynosiła ta maksymalna liczba.
Na przykład dla 1,2,3. wyświetlasz trzy razy sumę 1+2. [2]

Zadanie 2.3 [1]


Losuj w pętli dowolną angielską literę małą lub dużą tak długo, aż zostanie wylo-
sowana mała litera 'z' lub duża 'A'. Podaj liczbę losowań po zakończeniu działa-
nia pętli. Wylosowane litery umieszczaj w napisie. Pokaż tak uzyskany napis. [1]

Zadanie 2.4 [2]


Wygeneruj dwadzieścia losowych liczb całkowitych od 0 do 20. Za każdym razem,
gdy wylosujesz taką liczbę, umieszczaj ją w wektorze na losowej pozycji. Nie
możesz jednak nadpisać istniejących już w wektorze wartości. Pokaż zawartość
wektora, gdy osiągnie wielkość dwudziestu liczb. [2]

Niektóre funkcje możesz sobie zachować, mogą bowiem przydać się w wielu za-
daniach — przykładowo: funkcje wyświetlające zawartość wektora czy generujące
wektory z losowymi liczbami i/lub losową wielkością.

Zadanie 2.5 [1]


Wyświetlaj losowe liczby całkowite od 0 do 100 tak długo, aż wypadnie 100.
Wyświetl informację, ile losowań nastąpiło, zanim przerwała się pętla przy
wartości 100. [1]

26589ec988c76404b19a97e88c6609a5
2
CZĘŚĆ 2. (#2) PIERWOTNIACZKI (75 ZADAŃ) 23

Zadanie 2.6 [1]


Wypełnij dziesięcioelementową tablicę/wektor losowymi liczbami całkowitymi
z zakresu od –10 do 10. Ile jest liczb ujemnych w tak wylosowanej tablicy, ile
jest liczb dodatnich, ile parzystych, a ile nieparzystych? [1]

Zadanie 2.7 [2]


Wylosuj dwadzieścia liczb z zakresu od 0 do 1000 każda i wyświetl trzy najwięk-
sze z nich. [2]

Zadanie 2.8 [1]


Wylosuj i wyświetl liczbę ułamkową (typ double) w zakresie 0 do 1 włącznie
z maksymalnie trzema miejscami po przecinku. Skorzystaj z funkcji rand(). [1]

Zadanie 2.9 [2]


Utwórz tablicę/wektor dwudziestu losowych liczb typu double z zakresu od –1 do 1
i precyzją do trzech miejsc po przecinku. Oblicz średnią wszystkich liczb. [2]

Zadanie 2.10 [1]


Wylosuj liczbę całkowitą L między 20 a 30 włącznie oraz pobierz z klawiatury
znak Z. Wyświetl L-krotnie znak Z. [1]

Zadanie 2.11 [1]


Wykorzystuj operator bitowy &, aby sprawdzać, czy liczba nieujemna jest parzysta.
Utwórz funkcję sprawdzającą w ten sposób parzystość i zwracającą true/false
(parzysta/nieparzysta). [1]

Zadanie 2.12 [2]


Pobierz z klawiatury dwie liczby całkowite a, b. Utwórz funkcję zwracającą liczbę
double, gdzie a to część całkowita, a wartość bezwzględna z b to część ułamkowa
zwracanej liczby. Na przykład dla 45 i –11 zwróć 45.11. [2]

Zadanie 2.13 [2]


Pobierz znak z klawiatury, a następnie wylosuj dwie liczby całkowite a, b w za-
kresie od 5 do 10 każda. Utwórz funkcję, która otrzyma te wartości jako argu-
menty i narysuje a wierszy, w których będzie b znaków (znak pobrany z klawia-
tury na początku). Na przykład dla znaku # i liczb 3 i 8 narysuj trzy wiersze
w każdym po osiem znaków #. [2]

26589ec988c76404b19a97e88c6609a5
2
24 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie 2.14 [2]


Utwórz pętlę, która losuje liczbę z zakresu od 1 do 1000 włącznie, ale po każ-
dym kroku zmienia zakres losowania od ostatnio wylosowanej liczby do 1000
włącznie. Pętla przerywa się, gdy wylosujesz 1000. Przykładowo, pierwsze lo-
sowanie jest z zakresu <1;1000> i np. wypada 200. Zatem drugie losowanie jest
z zakresu <200;1000> i np. wypada 254. Zatem trzecie losowanie ma być doko-
nane z zakresu <254;1000> itd. Wylosowane liczby mają być zwracane w wek-
torze przez funkcję. [2]

Zadanie 2.15 [1]


Wypełnij wektor losowymi liczbami całkowitymi, następnie wszystkie liczby
parzyste wyzeruj, a nieparzystym zmień znak, po czym wyświetl ten wektor od
tyłu (od elementu ostatniego do pierwszego). Ilość liczb w wektorze ma być
również losowa: od 10 do 100 włącznie, a same liczby — dowolne. [1]

Zadanie 2.16 [1]


Pobierz lub wylosuj liczbę całkowitą n z zakresu <5;12>. Następnie dla tego n
narysuj „kwadrat” złożony ze znaków #, który ma n wierszy i n kolumn (czyli n
znaków w wierszu). Na przykład dla n=5:
#####
#####
#####
#####
#####

Zrób z tego funkcję rysującą dla podanej liczby i znaku. [1]

Zadanie 2.17 [2]


Dla losowego całkowitego n z zakresu <5;12> narysuj szachownicę ze znaku '#'
oraz spacji ' '. [2] Na przykład dla n=5:
# # #
# #
# # #
# #
# # #

Zadanie 2.18 [1]


Dla losowego całkowitego n z zakresu <5;12> narysuj „kwadrat” składający się
z n wierszy i n kolumn, którego krawędź to znak '#', a wnętrze jest puste (spacje).
Na przykład: [1]
#####
# #
# #
# #
#####

26589ec988c76404b19a97e88c6609a5
2
CZĘŚĆ 2. (#2) PIERWOTNIACZKI (75 ZADAŃ) 25

Zadanie 2.19 [2]


Dla losowego całkowitego n z zakresu <5;12> narysuj „trójkąt prostokątny”.
Przykładowo, dla n=5 ma to wyglądać tak:
#
##
###
####
#####

W ostatnim wierszu ma być pięć (ogólnie n) znaków '#', a w pierwszym — jeden


znak '#'. Następnie narysuj podobny trójkąt, ale tak, by najdłuższy bok nie był
z lewej, ale z prawej strony. [2]
#
##
###
####
#####

Zadanie 2.20 [3]


Wylosuj nieparzyste całkowite n z zakresu <7;21> (jeśli będzie parzyste, losuj
ponownie), a następnie narysuj „piramidę”, w której w pierwszym wierszu jest
jeden znak '#', a w drugim są trzy znaki '#' itd. W ostatnim wierszu ma być n
znaków.

Piramida ma być symetryczna, czyli środkowy znak '#' w każdej linii ma być w tej
samej pionowej linii/kolumnie. Na przykład dla n=5:
#
###
#####

Następnie narysuj „diament”, czyli początkowo to samo, ale po osiągnięciu naj-


dłuższej (ostatniej) linii znaków '#' rysuj odbicie lustrzane, traktując tę ostat-
nią linię jak oś symetrii. Efektem ma być figura jak w przykładzie niżej dla n=7:
#
###
#####
####### (najdłuższa linia (symetria pozioma) dla n=7 znaków)
#####
###
#

Zadbaj o to, aby obie figury rysowała funkcja otrzymująca jako argumenty znak n. [3]

26589ec988c76404b19a97e88c6609a5
2
26 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie 2.21 [3]


Narysuj „kwadrat” złożony ze znaków '#' dla dowolnego całkowitego n z prze-
działu <5;12>. Jedno z wewnętrznych pól (wylosuj które) ma być znakiem '@',
a nie znakiem '#'. Nie może to być krawędź „kwadratu”! [1,] Na przykład:
#####
##@##
#####
#####
#####

Następnie zrób to samo, ale kwadrat ma być pusty w środku (spacje) i posiadać
tylko krawędzie. Znak '@' ponownie nie może znajdować się na krawędzi. [2]
#####
# @ #
# #
# #
#####

Zadanie 2.22 [4]


Dla naturalnego N >= 3 narysuj „choinkę” złożoną z piramid („trójkątów”):
#
###
##### (pierwsza, szczytowa piramidka)

Każda kolejna część choinki ma mieć piramidkę o jeden wiersz dłuższą, a łączna
liczba piramid tworzących choinkę ma być równa N. Pierwsza piramidka two-
rząca czubek choinki ma być zawsze złożona z trzech linii. Przykład dla N=3:
#
###
#####
#
###
#####
#######
#
###
#####
#######
######### (N=3 -> trzy piramidki tworzące choinkę)

Oczywiście choinka ma być symetryczna, czyli środkowa kolumna każdej piramidy


ma być w tej samej kolumnie co środkowe kolumny pozostałych piramid. [4]

Zadanie 2.23 [2]


Utwórz funkcję pozwalającą wykonać działanie potęgowania liczby wymiernej
do potęgi naturalnej (całkowitej nieujemnej) i zwracającą wynik takiej potęgi.
Utwórz przeciążenie funkcji dla potęgi całkowitej (czyli może być potęga ujemna).
Do obliczenia potęgi wykorzystaj techniki iteracyjne. [1,] Następnie spróbuj
wykorzystać rekurencję. [1]

26589ec988c76404b19a97e88c6609a5
2
CZĘŚĆ 2. (#2) PIERWOTNIACZKI (75 ZADAŃ) 27

Zadanie 2.24 [2]


Utwórz funkcję, która zwraca zaokrąglenie (typu long long int) liczby wymiernej
(double): zaokrąglenie do góry, gdy część ułamkowa >=.50, i do dołu — w prze-
ciwnym razie. [1,] Zwróć uwagę na zaokrąglenie liczby ujemnej. 2.75 przechodzi
w 3 (zaokrąglenie zwiększa liczbę), ale –2.75 przechodzi w –3 (zaokrąglenie
zmniejsza liczbę!). [1]

Zadanie 2.25 [1]


Utwórz funkcję, która zmienia wartość przekazanej zmiennej (ale nie używa in-
strukcji return!) w taki sposób, by część ułamkowa przekazanej zmiennej po-
dwoiła się (3.22 -> 3.44; 3.6 -> 4.2 itd.) [1]

Zadanie 2.26 [1]


Utwórz funkcję, która zwraca wartość bezwzględną przekazanej do niej liczby
double. [1]

Zadanie 2.27 [0]


Sprawdź w Internecie (lub zapytaj o to sąsiadkę), jakie strony w sieci zawierają
szczegółowy opis języka C++ z uwzględnieniem standardu C++17 lub nowszego.
Zwróć uwagę, czy na stronach tych wyraźnie mówi się o standardach języka.
Poszukaj stron po angielsku. [0]

Zadanie 2.28 [1]


Utwórz funkcję, która oblicza wartość funkcji liniowej ax+b w punkcie dla podanych
niezbędnych argumentów (współczynniki a, b oraz wartość punktu x) i zwraca
tę wartość. Korzystaj z double. [1]

Zadanie 2.29 [2]


Utwórz funkcję obliczającą wartość funkcji liniowej dla podanego x i podanych
współczynników (wszystko double). Następnie utwórz losową tablicę dwuwymia-
rową [100] [2] (sto wierszy, dwie kolumny) i potraktuj wiersz jak punkt w układzie
współrzędnych. Punkty to losowe liczby z zakresu od –10 do 10 z dokładnością
do jednego miejsca po przecinku. Dla funkcji liniowej 2x+3 sprawdź, które z punk-
tów są nad jej wykresem, które są pod wykresem, a które leżą na nim. Podaj
statystykę, ile punktów leży pod wykresem funkcji, ile leży nad nim i ile na linii
utworzonej przez ten wykres. Jeżeli Twój algorytm jest dobry, to dla funkcji
2x+3 podane punkty:
punkty = { {0,1},{1,10},{2,7} };

będą leżały: jeden nad wykresem funkcji liniowej, jeden pod nim, jeden na wy-
kresie. [2]

26589ec988c76404b19a97e88c6609a5
2
28 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie 2.30 [2]


Losuj liczby całkowite z przedziału <1;100> tak długo, aż suma trzech ostatnich
liczb będzie większa lub równa 80 i mniejsza lub równa 90. Podaj ilość wyloso-
wanych liczb. Wylosowane liczby wkładaj na koniec wektora, o ile wkładana
liczba jest większa lub równa ostatniej w wektorze. Pokaż wektor. [2]

Zadanie 2.31 [1]


Losuj liczby całkowite z przedziału <0;1000> tak długo, aż zostanie wylosowana
liczba 1000. Każdą liczbę wylosowaną podzielną przez 10 dodaj do pliku liczby.txt
z zachowaniem zasady: jedna liczba w wierszu. [1]

Zadanie 2.32 [1]


Utwórz program, który odczyta wszystkie liczby z pliku tekstowego i wyświetli
je. Umieść liczby z pliku w wektorze. Liczby zawarte w pliku powinny spełniać
następujące reguły:
 każda liczba jest typu int;
 w jednym wierszu znajduje się jedna liczba;
 w każdym wierszu pliku jest liczba (nie ma pustych wierszy, ale gdyby
się jednak trafiły, omijaj je).

(Plik może mieć dowolną zawartość i długość zgodną z zasadami pliku. Po pro-
stu utwórz go samodzielnie/ręcznie. Możesz skorzystać z pliku utworzonego
w zadaniu 2.31). [1]

Zadanie 2.33 [2]


Utwórz program, który odczyta wszystkie liczby z pliku tekstowego i wyświetli
je. Liczby umieść w wektorze. Zasady obowiązujące w pliku:
 każda liczba jest typu int;
 w jednym wierszu znajdują się dwie liczby oddzielone średnikiem;
 nie powinno być pustych wierszy (puste wiersze trzeba omijać).

(Plik może mieć dowolną zawartość zgodną z zasadami pliku, po prostu utwórz
go samodzielnie/ręcznie lub pobierz plik 33_dane.txt.) [2]:
430;130
380;130
770;290
650;430
890;380
210;1000

26589ec988c76404b19a97e88c6609a5
2
CZĘŚĆ 2. (#2) PIERWOTNIACZKI (75 ZADAŃ) 29

Zadanie 2.34 [2]


Utwórz program, który odczyta wszystkie liczby i teksty z pliku, a następnie je
wyświetli. Zasady obowiązujące w pliku:
 każda liczba jest typu int;
 w jednym wierszu znajdują się trzy liczby oddzielone średnikiem, następ-
nie jest dowolnie długi napis, np.:
1;231;3423;dowolnie długi napis
321;345;67;inny długi napis
-351;211;0;potwornie długi napis, inny niż wszystkie
itd.;
 nie powinno być wierszy błędnych ani pustych, ale pusty wiersz może
się zdarzyć na końcu pliku (np. na maturze w plikach z danymi na końcu
bywa pozostawiany pusty wiersz).

Pobrane liczby umieść w wektorze i wyświetl. Pobrane napisy umieść w jednym


długim napisie i wyświetl. (Plik może mieć dowolną zawartość zgodną z zasa-
dami pliku, po prostu utwórz go samodzielnie/ręcznie lub skopiuj dane z przy-
kładu lub z pliku 34_dane.txt).

Zwróć uwagę na kodowanie plików. Kodowanie UTF-8/ANSII czy inne ma znacze-


nie przy odczycie, szczególnie gdy zależy Ci na polskich znakach. [2]

Zadanie 2.35 [4]


Utwórz program, który odczyta wszystkie liczby i teksty z pliku, a następnie je
wyświetli. Zasady obowiązujące w pliku:
 każda liczba w pliku jest typu double (np. 123.21 to liczba typu double, ale
sprawdź, czy Twój program konwertuje taką liczbę, pobierając z pliku
ciąg z przecinkiem czy z kropką: 123.21 albo 123,21; możesz poszukać
własnego rozwiązania tego problemu i konwertować liczby z przecinkiem
i z kropką;
 w jednym wierszu znajdują się liczby i napisy oddzielone średnikiem, jednak
ich kolejność i liczba w wierszu nie są znane i mogą być różne! (nie ma
schematu);
np.:
1;231;3423;dowolnie długi napis;345456;inny napis
napis;321;345;67;inny długi napis;8893;krótki tekst;123123;1212;12;tekst
-31.21;napis kosmiczny;0.001;-1.0;2
itd.

26589ec988c76404b19a97e88c6609a5
2
30 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Wyświetl pobrane liczby w kolejności odczytu. Pobrane napisy umieść w wekto-


rze z napisami, każdy napis otocz znakami '#'. Pokaż zawartość wektora. Pusta
linia może wystąpić na końcu pliku.

(Plik może mieć dowolną zawartość zgodną z zasadami pliku, po prostu utwórz go
samodzielnie/ręcznie albo skopiuj linie z przykładu lub pobierz plik 35_dane.txt). [4]

Zadanie 2.36 [3]


Utwórz własną dowolną strukturę (struct) złożoną z typów: int, string, char,
float. Następnie zaprojektuj funkcje/mechaniki, które:
 zapiszą (lub dopiszą) w pliku zmienną utworzonego wcześniej typu struk-
turalnego (musi być możliwość zapisu wielu takich elementów w jednym
pliku);
 będą odczytywać z pliku dane, na podstawie których utworzysz zmienną
utworzonego typu strukturalnego (w pliku może być wiele zmiennych tego
typu). Załadowane z pliku dane włóż do wektora. Oto przykład (zarys):
struct A {int a; string b; float c; char d; };
vector<A> va;
// funkcje/mechaniki
void dopisz(A& element, …); // dopisz na koniec pliku jeden element
void dopisz(vector<A>& v, …); // dopisz cały wektor elementów do pliku
vector<A> pobierz(); // załaduj dane z pliku i zwróć wektor elementów

Sugeruję przy zapisie stosować regułę: jeden element typu A umieszczony w jed-
nej linii. Przy załadowaniu każda linia to kolejna wartość w wektorze. Sposób
zapisania elementu jest dowolny i zakłada kreatywność. [3]

Zadanie 2.37 [2]


Utwórz funkcję, która zwraca true, jeśli otrzymany w argumencie napis (string)
jest palindromem, lub false w przeciwnym razie. (Palindrom to napis, który za-
pisany od tyłu i od przodu jest taki sam) [2]

Zadanie 2.38 [2]


Utwórz funkcję, która jako argument otrzymuje napisy A i B. Zwraca liczbę wy-
stąpień napisu A w napisie B. [2]

Zadanie 2.39 [4]


Napisz własną funkcję podobną do funkcji stol(), która zamienia string na
liczbę typu long long int i ją zwraca. [2,] Zaprojektuj funkcję, która wcześniej
sprawdzi, czy możliwa jest zamiana tekstu na liczbę. [2]

Zadanie 2.40 [2]


Napisz własną funkcję (algorytm), która liczbę całkowitą zamienia na napis
i zwraca ten napis (string). [2]

26589ec988c76404b19a97e88c6609a5
2
CZĘŚĆ 2. (#2) PIERWOTNIACZKI (75 ZADAŃ) 31

Zadanie 2.41 [6]


Napisz własną funkcję konwertującą, która pobiera napis reprezentujący liczbę
binarną, np. "11110", a następnie zwraca liczbę całkowitą dziesiętną (tu 30), która
tę liczbę reprezentuje. Utwórz drugą funkcję, która wykonuje operację odwrotną:
jako argument otrzymuje liczbę całkowitą (np. 30), a następnie zwraca napis
zawierający jej reprezentację binarną (tu "11110"). [2,]

Zaprojektuj dwie uniwersalne funkcje konwertujące liczby jak wyżej, ale dla do-
wolnej podstawy systemowej (od 2 do 16, czyli nie tylko dla systemu dwójko-
wego, ale także dla innych, do szesnastkowego włącznie). [4]

Zadanie 2.42 [2]


Ciąg tekstowy T składa się z losowych cyfr i liter angielskich. Znajdź wszystkie
podciągi możliwie jak najdłuższe, składające się z samych cyfr. Przykład: dla
ciągu T = "abd65asd7891das1d" będą to podciągi "65", "7891", "1". [2]

Zadanie 2.43 [3]


Ciąg tekstowy T składa się z losowych cyfr i liter angielskich. Znajdź przynajmniej
jeden najdłuższy podciąg ciągu T, który składa się z samych cyfr, przy czym te
cyfry tworzą podciąg niemalejący, np. w ciągu T = "dfgnqeiut98tna1223v0w3r123
334asdsh" istnieje przynajmniej jeden najdłuższy podciąg niemalejący składa-
jący się z samych cyfr "123334". [3]

Podciąg 12333 też jest niemalejący, ale nie jest najdłuższy.

Zadanie 2.44 [5]

Utwórz vector<vector<string>> W, który zawierać będzie 15 wierszy i 15 kolumn


z napisami (15×15). Wstaw do W losowe ciągi tekstowe dokładnie o długości
trzech znaków każdy. Te trzyznakowe ciągi powinny składać się z losowych li-
terek ze zbioru "abcdef". Znajdź wszystkie obszary 2×2 składające się z napisów:
"abc", "bcd", "cde" lub "def". [5] Przykład dla W o mniejszych rozmiarach (6×5)
— istnieją 4 obszary 2×2.

26589ec988c76404b19a97e88c6609a5
2
32 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Dla poniższych danych istnieją dwa obszary. Sprawdź, czy Twój program je znajdzie.
Poniższy kod znajduje się w pliku 44_kod.txt.

-------------------------
vector<vector<string>> W = {
{"ebb","cbe","beb","bdd","fcf","eed","bdd","cfd","cec","fee","ebf","cba","bff","acf","aee"},
{"ddc","eee","cac","cca","daa","cce","cbd","cad","afa","ced","fcc","cdd","cca","cfc","afd"},
{"dad","afb","bae","ffd","dba","efd","bac","dda","cca","beb","add","fba","bbe","fbd","fab"},
{"dfd","bcd","ecc","bfb","efb","cbb","dcf","afb","aaf","fcd","dee","dba","dca","baa","cee"},
{"fab","fba","efc","dad","caf","bad","dba","afa","fbd","cbf","ccb","fda","cff","eac","bde"},
{"efa","eac","ada","edd","fcd","fae","dff","cab","eab","dcc","dbd","bac","bfe","efe","eec"},
{"ccc","bcc","fbf","afa","abc","cde","fec","faa","bfe","cac","acd","dad","eca","bbe","afd"},
{"eba","abb","cfd","ccb","abc","def","ffc","ead","cdd","baf","bef","fbd","afb","bae","bfe"},
{"fcf","acf","bdc","baa","cdf","adf","edb","cab","ebe","faf","dee","ddc","ebd","aad","eaa"},
{"eee","aec","cbc","edd","bcf","fbb","acc","abf","dbc","cab","bcd","bbc","ebc","fee","fcd"},
{"cdc","cef","bfe","def","ede","ade","ade","dea","cbc","bce","bce","cad","fbb","dbb","ccb"},
{"feb","dba","afe","efa","add","aeb","bfc","bee","aca","acc","ebe","ead","ffa","baa","eca"},
{"eea","fcd","bdf","baf","fdb","fdb","ddd","bce","eed","edf","efc","fca","dff","def","abc"},
{"ebc","fcd","fad","cde","daf","eee","dfd","aaf","cff","dcc","aff","cfb","afc","bcd","cde"},
{"cca","afe","daf","ecf","cfd","cdb","bfe","aea","ffe","dae","bae","fce","ade","bbc","fcd"}}
;

Zadanie 2.45 [3]


W pliku 45_dane.txt znajdziesz następującą zawartość (7 wierszy, 20 znaków
w wierszu):
-...........--.....-
.---.---.---.---.--.
.-----........-----.
.------------------.
......--------..-...
....................
-......--------....-

Znajdź wszystkie wiersze i kolumny (znaki tworzące wiersz lub kolumnę) będące
palindromem. [3]

Zadanie 2.46 [5]


Pobierz ciąg tekstowy z klawiatury (bez polskich znaków ąęśćźńżół). Następnie,
używając tylko liczb dziesiętnych, spacji oraz średnika, wymyśl sposób zapisu
tego napisu w pliku kod.txt. Stwórz mechanizm odczytu treści pliku kod.txt i od-
wracając swoją własną metodę, zamień treść z pliku na tekst, który na początku
pobrałeś z klawiatury. [4,] Stwórz wersję uwzględniającą polskie znaki. [1]

Na przykład pobierasz słowo "rower". Następnie zapisujesz je w jakiś sposób


w pliku kod.txt, korzystając tylko z liczb dziesiętnych, spacji i średnika (nie możesz
wprost zapisać słowa "rower"). Następnie utwórz funkcję odwracającą ten proces:
przeczytaj plik kod.txt i zamień jego zawartość na słowo "rower" (wyświetl wynik
na ekranie jako dowód poprawnego przeczytania i odkodowania napisu z pliku).

26589ec988c76404b19a97e88c6609a5
2
CZĘŚĆ 2. (#2) PIERWOTNIACZKI (75 ZADAŃ) 33

Zadanie 2.47 [1]


Utwórz funkcję, która dla podanego jako argument wektora v z liczbami całkowi-
tymi oraz pewnej liczby x szuka tej liczby x w wektorze v i zwraca liczbę jej wy-
stąpień. [1]

Zadanie 2.48 [2]


Utwórz funkcję, która w wektorze v przekazanym jako argument szuka wszystkich
podciągów przynajmniej dwuelementowych, złożonych z takich samych liczb.
Funkcja powinna wyświetlać wszystkie takie podciągi, od najdłuższych po najkrót-
sze, podając indeks pierwszego i ostatniego elementu dla każdego podciągu. [2]

Na przykład {3,2,1,1,4,2,4,4,4} zawiera cztery podciągi przynajmniej dwue-


lementowe, złożone z takich samych liczb:
 1,1 od pozycji 2 do 3,
 4,4 od pozycji 6 do 7,
 4,4 od pozycji 7 do 8,
 4,4,4 od pozycji 6 do 8.

Zadanie 2.49 [2]


Utwórz funkcję, która otrzymuje dwa wektory z liczbami, a zwraca wektor zawie-
rający tylko te liczby, które występują w obu wektorach (część wspólna). Liczby
występujące w wektorze zwracanym nie powinny się powtarzać. [2]

Zadanie 2.50 [4]


Utwórz funkcję, która przetwarza napis tak, aby zniknęły z niego wszelkie pod-
ciągi znaków powtarzających się. Zasada usuwania:
 Szukając od lewej, znajdź pierwszą parę identycznych sąsiednich znaków
i usuń ją.
 Powtarzaj tę czynność aż do momentu, gdy nie zostanie znaleziona ani
jedna para sąsiednich identycznych znaków. [2,]

Wykonaj zadanie dla następujących napisów (są w pliku 50_dane.txt):


skfuu12m2111flx
npq985yy5vnprr8ettemzp9yamppp98tywnmtvb9q8y4nqp948tydlfaaafld
1abbbbaaccdccdeeddccaeffabcdefa121122

Utwórz drugą funkcję z tą różnicą, że dwa identyczne sąsiednie znaki będzie


zamieniać na jeden, np. xx zamieni na x. Sprawdź wynik obu funkcji dla tych
samych napisów. [2]

Zadanie 2.51 [1]


Utwórz funkcję, która dla podanej liczby całkowitej dodatniej zwraca true, jeśli
liczba jest pierwsza, lub false w przeciwnym razie. [1]

26589ec988c76404b19a97e88c6609a5
2
34 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie 2.52 [2]


Utwórz funkcję, która przekazane dwa wektory z liczbami łączy w jeden wektor
i zwraca go. Liczby w wektorze wynikowym powinny być ułożone naprzemiennie:
raz liczba z wektora jednego, raz z drugiego. Liczby do nowego wektora pobie-
raj z istniejących od początku, kierując się ku końcowi (od lewej do prawej).
Gdy liczby w jakimś wektorze się wyczerpią, niewykorzystane liczby z drugiego
wektora lądują na końcu wektora wynikowego. [2]

Zadanie 2.53 [8]


Sprawdź poprawność wyrażenia algebraicznego podanego jako tekst. Najlepiej
zaprojektuj funkcję zwracającą true/false. Nie chodzi o obliczenie wyrażenia,
ale sprawdzenie poprawności jego formalnego zapisu. Wyrażenie algebraiczne
może składać się z liczb dodatnich i ujemnych całkowitych, małych liter angiel-
skich, działań +, -, *, /, ^, %, znaku równości = oraz z nawiasów (). (Przyjmijmy,
że w wyrażeniu może być wiele razy porównanie. Na przykład a+1=b-2=c*3=d/4
jest poprawne). [8]

Przykładowe poprawne wyrażenia:


(12*x+3*(3*d-a)^3)/11=z
-(-12^a*b*c/12-(-5-a*b))
10/0 (tak, matematycznie niemożliwe jest dzielenie przez 0, ale zapis jest formalnie poprawny)

Przykład niepoprawnego wyrażenia:


---a
a+b=c=d=
(a--))=2+3*(4)
a=
abc
a**2
2a (tak, zwyczajowo 2a jest poprawne i to jest skrót dla 2*a, ale tutaj musimy zapisać to jawnie)

Zadanie 2.54 [4]


Korzystając ze zbioru imion i nazwisk, napisz generator w postaci funkcji, która
zwraca losowe imię i nazwisko. (pliki imiona.txt oraz nazwiska.txt utwórz sam,
zachowując zasadę „jedno imię/nazwisko w jednej linii pliku”). Zwróć uwagę,
że generator nie musi uwzględniać płci, zatem np. Janina Kowalski nie jest błędem.
[2,] Zaprojektuj generator, który uwzględnia płeć. Możesz np. przechowywać
dwie formy nazwiska w jednej linii, męską i żeńską (Kowalski;Kowalska), a przy
imionach umieszczać informację o płci: Piotr;m itd. [2]

Zadanie 2.55 [2]


W pewnym kraju wszystkie imiona są zlepkiem sylab (od jednej do czterech),
w których każda sylaba składa się z trzech znaków, ma w środku 'e' lub 'o',
kończy się dowolną spółgłoską angielską bez 'q', 'v' i 'x', a zaczyna się jedną
z liter: 's', 'r', 'j', 'c', 'g'. Jeżeli imię składa się z parzystej liczby sylab,

26589ec988c76404b19a97e88c6609a5
2
CZĘŚĆ 2. (#2) PIERWOTNIACZKI (75 ZADAŃ) 35

wszystkie sylaby mają w środku tę samą samogłoskę (w każdej same 'e' lub
w każdej same 'o'), a jeżeli imię składa się z nieparzystej liczby sylab, to każda
następna sylaba musi mieć inną samogłoskę w środku w odniesieniu do samo-
głoski z poprzedniej sylaby. Na podstawie tych informacji utwórz generator
imion w postaci funkcji, która zwraca losowe imię. Wygeneruj piętnaście imion
i przeczytaj je na głos pierwszej osobie, jaką zobaczysz. [2]

Zadanie 2.56 [3]


Wygeneruj losową liczbę składającą się z dziesięciu cyfr. (Może być przedsta-
wiona jako string). Liczba ta nie może się zaczynać od 0, suma jej cyfr nie może
być mniejsza niż 30, a żadne bezpośrednio sąsiadujące cyfry nie mogą być iden-
tyczne, chyba że są to dwie ostatnie cyfry — te mogą być identyczne. Trzecia
cyfra, licząc od lewej, nie może być liczbą parzystą. Zwróć uwagę na to, czy twój
losowy generator jest faktycznie jak najbardziej losowy i nie zawiera zbyt sztyw-
nych ograniczeń (np. gdy pewne możliwe i poprawne układy cyfr tworzących
liczbę mają niewielką szansę (lub nie mają żadnej szansy!) na wystąpienie). [3]

Zadanie 2.57 [1]


Struktura Punkt zawiera wartości x i y typu int (nie double!). Utwórz funkcję,
która otrzymuje jako argumenty trzy zmienne typu Punkt i sprawdza, czy mogą
one razem leżeć na jednej linii prostej. Oto wzór funkcji liniowej dla dwóch
punktów:
(y−yA) * (xB−xA) − (yB−yA) * (x−xA)=0)

[1]

Zadanie 2.58 [1]


Utwórz funkcję wyświetlającą wzór funkcji liniowej (string) na podstawie dwóch
punktów. Zbuduj do tego własną strukturę Punkt reprezentującą punkt na
płaszczyźnie. Korzystaj z double. Oto wzór funkcji liniowej dla dwóch punktów:
(y−yA) * (xB−xA) − (yB−yA) * (x−xA)=0 )

[1]

Zadanie 2.59 [5]


Zaprojektuj funkcję, która dla podanej liczby naturalnej N>=1 i N<=365 reprezen-
tującej dzień 2022 roku zwróci informację o tym dniu (2022-01-01 to sobota,
luty ma 28 dni). Na przykład dla N=3 obliczona data to 2022-01-03. Podaj rów-
nież, jaki to dzień tygodnia (dla N=3 to poniedziałek). [1,]

Zaprojektuj też funkcję dla dowolnego roku większego niż 2022. Uważaj na mecha-
nizm lat przestępnych! Funkcja jako argument powinna pobierać rok i liczbę
repezentującą dzień roku, np. f(2033,200) oznaczałoby: podaj informację o dniu
nr 200 w 2033 roku (zwróć datę oraz dzień roku, np. środa itd.). [4]

26589ec988c76404b19a97e88c6609a5
2
36 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie 2.60 [2]


Utwórz program, który dla dwóch napisów (string) reprezentujących czas
w formacie 24-godzinnym, zachowujących następujący format: _ _:_ _:_ _
(godziny:minuty:sekundy), np.: dla 09:05:08 i 13:10:33 obliczy czas pomiędzy nimi,
podany w takim samym formacie (w przykładzie różnica wynosi 04:05:25).
Zakładamy poprawne godziny od 00:00:00 do 24:00:00. [2]

Zadanie 2.61 [2]


Utwórz funkcję, która porównuje dwa napisy (słowa bez spacji), zbudowane
z małych liter polskiego alfabetu, a następnie zwraca napisy w kolejności alfa-
betycznej. [2]

Zadanie 2.62 [1]


Utwórz funkcję, która przyjmuje na wejście liczbę całkowitą dodatnią (unsigned
long long int) i zwraca liczbę, która składa się z tych samych cyfr, ale od tyłu.
Na przykład dla liczby 9811 powinna być zwrócona liczba 1189. Gdy liczba na
wejście kończy się przynajmniej jednym zerem, jak np. 3520 albo 300, zwróć
253 oraz 3. [1]

Zadanie 2.63 [5]


Skopiuj poniższe dane (tabela pod treścią) i umieść w pliku tekstowym (lub pobierz
plik 63_dane.txt), a następnie umieść go w katalogu z Twoim projektem, aby można
było otwierać ten plik do odczytu. Odpowiedz na następujące pytania:
 Jaka jest średnia liczb w pierwszej i ostatniej kolumnie? [1,]
 Które kolumny (numer) posiadają największą liczbę? [1,]
 Ile jest wierszy, w których nie występuje liczba podzielna przez 10? [1,]
 Ile jest wierszy, w których pierwsze trzy liczby zachowują niemalejący
porządek? [1,]
 Ile jest wierszy, w których są dokładnie trzy liczby z zakresu <85;100> [1]

Przy kopiowaniu danych między liczbami odstępy mogą być spacją lub tabula-
torem. W C++ znak tabulatora to "\t".

92 41 27 93 94 49
54 13 56 56 79 78
43 52 26 67 73 46
17 9 16 94 76 90
84 27 18 41 24 84
93 71 53 73 4 42
51 40 39 87 69 32

26589ec988c76404b19a97e88c6609a5
2
CZĘŚĆ 2. (#2) PIERWOTNIACZKI (75 ZADAŃ) 37

48 17 49 89 62 67
9 60 71 93 11 46
53 43 78 99 58 7
83 93 24 14 15 50
74 37 46 49 33 33
18 72 66 13 46 71
51 59 3 76 12 83
56 28 84 2 8 17
2 64 52 17 65 2
79 66 84 72 73 12
73 40 96 66 29 31
46 38 15 86 55 29
5 94 59 10 43 5
18 20 41 6 11 62
79 35 7 50 100 57
79 45 23 30 97 18
50 72 91 19 58 100
72 10 9 4 12 3
87 61 8 24 41 6
19 49 25 67 58 39
43 8 80 34 21 18
47 84 74 35 58 71
94 20 93 71 99 66

Zadanie 2.64 [4]


Skopiuj dane znajdujące się pod treścią zadania do pliku tekstowego (lub po-
bierz plik 64_dane.txt) i umieść go w katalogu z Twoim projektem, aby można
było otwierać ten plik do odczytu. Odpowiedz na następujące pytania, przyjmu-
jąc, że pierwsza kolumna to oznaczenie osoby (A, B, C, D, E), druga to wartość
pewnego pomiaru, którego dokonała ta osoba, a trzecia kolumna to numer dnia
badań, w którym dokonano pomiaru (każdego dnia jest jeden pomiar!):
 Która osoba dokonywała najwięcej pomiarów? [1,]
 Policz sumę oraz średnią wszystkich pomiarów dla każdej z osób. [1,]
 Zakładając, że pierwszy dzień pomiarów to wtorek, drugi środa itd., policz
sumę pomiarów ze wszystkich wtorków. [2]

26589ec988c76404b19a97e88c6609a5
2
38 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Przy kopiowaniu danych między liczbami i napisami odstępy mogą być spacją
lub tabulatorem. W C++ znak tabulatora to "\t".

C 79 1
B 28 2
A 79 3
C 42 4
B 80 5
C 49 6
C 32 7
D 9 8
E 39 9
D 45 10
E 36 11
A 5 12
E 98 13
B 81 14
C 14 15
C 86 16
A 10 17
C 38 18
B 29 19
C 43 20
C 64 21
E 100 22
B 77 23
A 31 24
C 65 25
B 65 26
D 12 27
B 77 28
E 45 29
E 99 30
C 43 31
D 89 32
A 85 33

26589ec988c76404b19a97e88c6609a5
2
CZĘŚĆ 2. (#2) PIERWOTNIACZKI (75 ZADAŃ) 39

E 88 34
E 62 35
A 98 36
D 57 37
B 1 38
B 71 39
B 56 40
B 53 41
C 65 42
A 35 43
C 64 44
E 94 45
B 42 46
A 53 47
B 47 48
E 91 49
A 5 50
B 36 51
B 92 52
D 32 53
A 64 54
B 78 55
B 39 56
A 62 57
A 34 58
C 84 59
A 72 60
B 39 61
C 9 62
B 79 63
B 78 64
D 37 65
C 77 66
E 82 67
B 13 68

26589ec988c76404b19a97e88c6609a5
2
40 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

B 26 69
C 66 70
C 1 71
E 23 72
B 65 73
C 6 74
A 61 75
C 78 76
C 83 77
B 61 78
E 61 79
C 62 80
C 4 81
E 7 82
A 20 83
B 9 84
A 30 85
E 49 86
C 24 87
D 67 88
E 66 89
A 9 90
C 73 91
D 71 92
B 8 93
E 53 94
B 57 95
A 8 96
A 72 97
B 46 98
E 19 99
D 32 100

26589ec988c76404b19a97e88c6609a5
2
CZĘŚĆ 2. (#2) PIERWOTNIACZKI (75 ZADAŃ) 41

Zadanie 2.65 [3]


Poniższy ciąg tekstowy:
xfac8*1101011*1110100xc8x32xff*1010o7311o1212xabcd*101*1*0x1o0xd*11111

zawiera liczby szesnastkowe, ósemkowe i binarne (plik 65_dane.txt). Liczby szes-


nastkowe rozpoczynają się od 'x', binarne od '*', a ósemkowe od 'o'. Wyświetl
wszystkie te liczby w postaci liczb dziesiętnych. Ciąg skopiuj do programu
i umieść na początku w zmiennej tekstowej typu string. Twoje rozwiązanie po-
winno być uniwersalne i powinno działać dla dowolnego innego ciągu o tych sa-
mych założeniach odnośnie do liczb szesnastkowych, ósemkowych i binarnych.
Jak zawsze zakładamy pełną poprawność danych. [3]

Zadanie 2.66 [5]


W matematyce występują macierze. Można mnożyć macierz przez liczbę albo
macierz przez macierz. Wykorzystaj typ vector<vector<int>> do reprezentacji
macierzy (dwuwymiarowej). Następnie utwórz funkcję, która jako argument
otrzymuje liczbę i macierz lub macierz i macierz (skorzystaj z przeciążenia
funkcji lub utwórz dwie oddzielne funkcje) i zwraca wynik mnożenia podanej
macierzy przez liczbę lub macierz (wynik to również macierz reprezentowana
przez typ vector<vector<int>>). [5] Oblicz wynik dla następujących działań:

5 9 −1 4 8 2
7 4 0 ∗ 11 − 2 0
−3 5 2 3 5 3
2494
⎡3 0 2 2⎤
⎢ ⎥
⎢7 3 1 8⎥ ∗ 7
⎢1 2 3 4⎥
⎣9 6 3 1⎦

Mnożenie macierzy przez liczbę to mnożenie każdego jej elementu przez tę liczbę.
Mnożenie macierzy A i macierzy B (nie jest ono naprzemienne!) to mnożenie każ-
dego wiersza z macierzy A przez każdą kolumną z macierzy B. Mechanizm mnożenia
powinien być pokazany na lekcjach matematyki. Można go poszukać w Internecie.

Zadanie 2.67 [2]


W ciągu tekstowym złożonym z dowolnych małych liter alfabetu angielskiego
wyszukaj wszystkie możliwe podciągi minimum dwuznakowe, które tworzą pa-
lindromy. Zadanie realizuj za pomocą funkcji, która zwraca wektor z palindro-
mami (lub pusty wektor). [2]

Zadanie 2.68 [1]


Spróbuj sprawdzić, czy liczba całkowita N jest podzielna przez liczbę całkowitą p.
Nie możesz jednak skorzystać z operatora reszty z dzielenia, %. [1]

26589ec988c76404b19a97e88c6609a5
2
42 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie 2.69 [6]


Utwórz funkcję:
vector<int> oddo(int zakres_od, int zakres_do) { … }

która będzie zwracać wektor z liczbami całkowitymi z zakresu określonego


jako argumenty funkcji. Przykładowo: dla zakres_od = 4 i zakres_do = 8 zwracać
ma się wektor zawierający {4,5,6,7,8}, dla zakresu <–3;5> -> {-3,-2,-
1,0,1,2,3,4,5}, dla zakresu <3;–1> wektor malejący z liczbami {3,2,1,0,-1} itd.
Gdy zakres_od i zakres_do są równe, zwracamy zbiór jednoelementowy, np.
<3;3> -> {3}. [2,]

Wykorzystując funkcję oddo(), utwórz dziesięć zbiorów o losowo określonych


zakresach. Granice zakresu (zakres_od i zakres_do) mają być losową liczbą z prze-
działu <–10;10>. Następnie dla tych zbiorów odszukaj i pokaż wszystkie liczby,
które wystąpiły w przynajmniej pięciu z dziesięciu zbiorów (losowość nie gwa-
rantuje istnienia takich liczb). [4]

Zadanie 2.70 [5]


Utwórz funkcję sgen():
string sgen(int minL, int maxL, string dict) {}

która dla 0 < minL < maxL i niepustego napisu dict zwraca losowe słowo złożone
ze znaków zawartych w dict o długości nie mniejszej niż minL i nie większej niż
maxL. Na przykład sgen(2,4,"abc") może zwrócić 'bcca', ponieważ długość napisu
zawiera się pomiędzy 2 i 4 i składa się ze znaków napisu „abc”. [2,] Dla argumen-
tów sgen(5,10,"qazwsxedcrfvtgby") wylosuj 25 000 słów i umieść je w wektorze.
Następnie znajdź wszystkie słowa, które się powtórzyły.

Może się okazać, że nie ma takich słów. Algorytm może długo działać, w zależności
od pomysłu na jego realizację. Aby sprawdzić, czy Twój algorytm działa poprawnie,
możesz wylosować w ramach testu małą liczbę słów, np. 100 lub 200. [3]

Zastanów się, czy stworzony przez Ciebie algorytm szukania powtarzających się
słów da się jakoś przyśpieszyć. Czuj się w pełni wolny. Zwracane słowa możesz
przechowywać w inny sposób, jeżeli uznasz to za pomocne. Spróbuj ulepszać
algorytm, porównując czas działania kolejnych jego wersji.

To może się przydać (lecz nie musi): kasowanie z wektora jest optymalne, gdy usu-
wamy tylko ostatni element metodą pop_back(). Kasowanie elementów ze środka
lub z początku wymaga realokacji wektora w pamięci komputera. Przy dużych wek-
torach wiąże się to ze zwiększonym zużyciem zasobów.

26589ec988c76404b19a97e88c6609a5
2
CZĘŚĆ 2. (#2) PIERWOTNIACZKI (75 ZADAŃ) 43

Zadanie 2.71 [9]


Zaprojektuj symulację zdarzenia, którym jest spadanie liści z drzewa. Na początku
na drzewie jest 3000 liści. Zasady symulacji są następujące:
 Zdarzenie spadania liści odbywa się z częstotliwością pomiędzy 1 sekundą
a 10 sekundami.
 W każdym zdarzeniu spadania liści może spaść od 0 do 10 liści, w tym:
od 0 do 3 liści może spadać z prawdopodobieństwem 50%; od 4 do 7 liści
może spadać z prawdopodobieństwem 30%; a szansa na opad od 8 do
10 liści w zdarzeniu spadania to 20%.

Zasymuluj proces spadania liści, zapisując kolejne opadnięcia w dowolny sposób.


Symulację kończy upadek wszystkich możliwych liści. Zwróć uwagę na ostatni
krok przed opadem wszystkich liści. Na przykład na drzewie zostało 5 liści a wy-
losował się opad od 8 do 10 liści. Zmień go na opad 5 liści i zakończ proces. [3,]

Dla utworzonych podczas symulacji danych spróbuj odpowiedzieć na następu-


jące pytania:
 Po jakim czasie (podaj w godzinach, minutach i sekundach) drzewo stra-
ciło wszystkie liście? [1,]
 Jaki procent spadków stanowiły spadki zawierające od 0 do 3 liści? [1,]
 Ile razy w krokach symulacji nie spadł ani jeden liść? (losowało się 0 opa-
dłych liści). [1,]

Przyjmij, że ponumerowaliśmy kolejne kroki symulacji (zdarzenie opadania),


licząc od 0. Znajdź dziesięć kolejnych (następujących po sobie) kroków, dla któ-
rych spadło najmniej liści. Podaj numery tych kroków. [3]

Zadanie 2.72 [2]


Utwórz funkcję, która pobiera liczbę bitową o określonej długości bitów (8 albo
16) i informuje, czy bity tej liczby tworzą palindrom? Wykorzystaj bibliotekę
<bitset> i typ bitset<n> dla n==8 lub n==16. Funkcja nie powinna pracować na
napisach, tylko na faktycznych liczbach (mogą być w postaci 0b0101101 itd.).
Przykładowo, dla bitset<8> i liczby 10011001 mamy do czynienia z palindromem.
Dla liczby 00111100 również. [2]

Zadanie 2.73 [6]


Utwórz różne funkcje, które przyjmują za argumenty dwie liczby bitowe w po-
staci napisów (string). Nie zamieniaj napisów na wartości liczbowe, gdyż napis
reprezentujący liczbę bitową może mieć dowolną długość (setki bitów), a tym
samym daleko przekraczać zakres liczbowy komputera. Liczba musi więc po-
zostawać w postaci napisu. Liczby mogą zaczynać się od znaku '0', co powinno
być uwzględnione! Twoje funkcje powinny obejmować:
 dodawanie: zwracać napis reprezentujący liczbę bitową, która jest sumą
obu liczb przekazanych do funkcji; np. „111” + „1” to „1000”; [3,]

26589ec988c76404b19a97e88c6609a5
2
44 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

 test negacji: zwracać true, jeśli jedna liczba jest bitową negacją drugiej,
lub false w przeciwnym razie. Liczby reprezentowane przez string w obu
przypadkach powinny być takiej samej długości z uwzględnieniem po-
czątkowego zera; na przykład „00111” to negacja „11000” (true); [1,]
 wskazanie liczby większej: zwracać liczbę bitową, która jest większa. [2]

Zadanie 2.74 [3]


Utwórz wektor z kolejnymi liczbami całkowitymi od 1 do 100 włącznie ({1,2,3,
…,100}). Przeprowadź operację polegającą na wyrzucaniu co trzeciej liczby,
stosując następujący sposób liczenia. „Stojąc” na pierwszym elemencie zbioru
(liczba 1), przesuń się trzy razy (ku końcowi wektora, w prawo). Zatrzymasz się
na liczbie 4. Skasuj ją (w jej miejsce wskoczy liczba 5, gdyż po skasowaniu liczby
z wektora nie ma miejsca pustego!). Przesuń się ponownie trzy razy, na liczbę 8.
Skasuj ją. Wykonuj tę operację „przesuń-skasuj” tak długo, aż zostanie jedna
liczba w wektorze. Jaka liczba pozostanie? [2,]

Gdy dojdziemy do ostatniego elementu, traktujemy wektor, jak gdyby był cykliczny,
czyli po ostatniej liczbie kolejnym krokiem jest przejście do liczby pierwszej w tym
wektorze. Zwróć też uwagę, że gdy skasujemy element na końcu wektora, w celu
zachowania cykliczności przechodzimy na pozycję pierwszego elementu w wektorze,
tak jakby ten pierwszy „wskoczył” w miejsce właśnie skasowanego ostatniego.

Aby to zobrazować, przeanalizuj przykład dla sześciu liczb (podkreślona liczba


to zajmowana pozycja w wektorze):
start> [1,2,3,4,5,6] >przesuń o 3> [1,2,3,4,5,6] >usuń> [1,2,3,5,6] >przesuń o 3>
[1,2,3,5,6] >usuń> [1,3,5,6] >przesuń o 3> [1,3,5,6] >usuń> [3,5,6] >przesuń o 3>
[3,5,6] >usuń> [5,6] >przesuń o 3> [5,6] >usuń> [5]

Przykład dla ośmiu liczb:


[1,2,3,4,5,6,7,8] > [1,2,3,4,5,6,7,8] > [1,2,3,5,6,7,8] > [1,2,3,5,6,7,8] >
[1,2,3,5,6,7] > [1,2,3,5,6,7] > [1,2,3,6,7] > [1,2,3,6,7] > [1,3,6,7] > [1,3,6,7] >
[3,6,7] > [3,6,7] > [6,7] > [6,7] > [6]

Stwórz mechanizm/funkcję dla wektora z kolejnymi liczbami od 1 do N i dla do-


wolnego K>=2 oznaczającego kroki przesunięcia. [1]

Usuwanie elementów z wnętrza wektora nie jest operacją zbyt wydajną, przez wzgląd
na realokację wektora w pamięci. Jeżeli wiesz, jak korzystać z listy, możesz jej użyć
zamiast wektora.

Zadanie 2.75 [100]


Gratulacje! Jeżeli masz wszystkie wcześniejsze zadania za sobą, pozostało Ci już tylko
jedno: zrób dobrą herbatę, przygotuj pyszny smakołyk, rzuć okiem na piękny
widok z tarasu i pomyśl, które zadania można by było wykonać lepiej. [100]

26589ec988c76404b19a97e88c6609a5
2
Rozwiązania

Kilka słów wyjaśnienia


Możesz zauważyć, że niektóre zadania można wykonać lepiej, szybciej, stosując
pełnię możliwości języka C++. Rozwiązania tu proponowane zakładają jednak
posiadanie ograniczonej wiedzy i umiejętności z zakresu języka C++. Wynika to
z naturalnego procesu uczenia się języka, w którym kolejne możliwości otwierają
się przed nami dopiero po jakimś czasie. Pomimo mniejszego zakresu umiejęt-
ności rozwiązywanie zadań na tym etapie jest jak najbardziej możliwe. Tworząc
rozwiązania zadań, próbowałem uwzględnić wykorzystanie tylko pewnej porcji
umiejętności. Z czasem w rozwiązaniach zadań będą wykorzystywane rosnące
umiejętności w zakresie posługiwania się językiem C++.

Poniżej znajdują się proponowane rozwiązania, jednak nie muszą one być wcale
najlepsze. Porównaj je ze swoimi rozwiązaniami. Jeżeli moje są lepsze, to jest
wydajniejsze, bardziej czytelne, istotnie krótsze itd., to spróbuj je zrozumieć.
W ten sposób będziesz się uczyć i rozwijać.

Jeżeli posiadasz większe umiejętności niż zakładane w części pierwszej (#1)


i drugiej (#2), śmiało z nich korzystaj. Pamiętaj jednak, że poniższe rozwiązania
ograniczają się do technik i umiejętności wymienionych w obydwu częściach
tego zbioru zadań.

Część 1.
(#1) Ślady życia
Zadanie #1.1

Przykładowe rozwiązanie 1.
#include <iostream>
using namespace std;
int main() {
setlocale(LC_ALL, "");
unsigned a, b, c; // czyli unsigned int
unsigned suma = 0, maks;
cout << "Podaj kolejne 3 liczby całkowite nieujemne:";
cin >> a >> b >> c;
if (a > b) {
maks = a;
suma += b;
}
else {

26589ec988c76404b19a97e88c6609a5
2
46 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

maks = b;
suma += a;
}
if (maks > c) {
suma += c;
}
else {
suma += maks;
maks = c;
}
for (unsigned i = 1; i <= maks; i++) {
cout << suma << " ";
}
}

Przykładowe rozwiązanie 2.
#include <iostream>
using namespace std;
int main() {
setlocale(LC_ALL, "");
unsigned a, b, c; // to samo co unsigned int
cout << "Podaj kolejne 3 liczby całkowite nieujemne:";
cin >> a >> b >> c;
unsigned suma = a + b + c;
unsigned maks = (a > b) ? a : b;
suma -= maks = (maks > c) ? maks : c;
while (maks--) {
cout << suma << " ";
}
}

Zadanie #1.2
#include <iostream>
using namespace std;
int main() {
setlocale(LC_ALL, "");
int a;
cout << "Podaj liczbę całkowitą:";
cin >> a;
if (a % 2 == 0) cout << "tak\n";
else cout << "nie\n";
}

Zadanie #1.3
#include <iostream>
using namespace std;
int main() {
setlocale(LC_ALL, "");
int a;
cout << "Podaj liczbę całkowitą:";
cin >> a;
if (a % 3 != 0 and a % 5 != 0) {

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 47

cout << "niepodzielna ani przez 3, ani przez 5\n";


}
else if (a % 3 == 0 and a % 5 != 0) {
cout << "podzielna przez 3, ale nie przez 5\n";
}
else if (a % 3 != 0 and a % 5 == 0) {
cout << "podzielna przez 5, ale nie przez 3\n";
}
else {
cout << "podzielna przez 3 i przez 5 (równocześnie)\n";
// czy to oznacza, że podzielna przez 15? :)
}
}

Zadanie #1.4
#include <iostream>
#include <vector>
using namespace std;
int main() {
setlocale(LC_ALL, "");
char znak;
cin >> znak; // wpisz tylko małe litery angielskie lub cyfry
vector<char> samogloski = { 'a','e','i','o','u','y' };
// kod '0' to 48, '1' to 49 itd.; przy porównaniu char jest rzutowany na liczbę
if (znak >= 48 and znak <= 48 + 9) {
cout << "Znak to cyfra.\n";
return 0; // zakończ program
}
bool samogloska = false;
for (auto s : samogloski)
if (znak == s) {
samogloska = true;
break;
}
if (samogloska) cout << "Znak to samogłoska.\n";
else cout << "Znak to spółgłoska.\n";
}

Zadanie #1.5
#include <iostream>
using namespace std;
int main() {
setlocale(LC_ALL, "");
float a1, a2, a3, a4, a5;
cin >> a1 >> a2 >> a3 >> a4 >> a5;
if (a5 == 0.0) {
cout << "Dzielenie przez 0 to nie najlepszy pomysł.\n";
return 0; // opuść program
}
cout << "Wartość wyrażenia: " << (((a1 + a2) * a3) - a4) / a5 << endl;
// uwaga: starsze kompilatory mogą mieć problem z rzeczywistym porównaniem a5 == 0.0,
// gdyż liczba 0.0 może być przybliżeniem, a faktyczna
// wartość może wynosić np. 0.00000000000082790 itp.
}

26589ec988c76404b19a97e88c6609a5
2
48 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie #1.6
#include <iostream>
using namespace std;
int main() {
setlocale(LC_ALL, "");
unsigned ilep = 0, ilenp = 0;
int temp;
for (int i = 5; i--;) { // jeśli i będzie == 0, warunek stanie się fałszem
cin >> temp;
if (temp % 2 == 1) ilenp++;
else ilep++;
}
cout << "Nieparzystych " << ilenp << "\n";
cout << "Parzystych " << ilep << "\n";
}

Zadanie #1.7
#include <iostream>
using namespace std;
int main() {
setlocale(LC_ALL, "");
char znak;
unsigned ile = 0;
do {
cout << "Podaj znak:";
cin >> znak;
ile++;
} while (znak != 'x');
cout << "Pobrano " << ile << " znaków.\n";
}

Zadanie #1.8
#include <iostream>
using namespace std;
int main() {
setlocale(LC_ALL, "");
float a, b;
char znak;
cout << "Podaj dwie liczby: ";
cin >> a >> b;
cout << "Podaj znak: ";
cin >> znak;
if (znak == '+') {
cout << a << znak << b << "=" << a + b << endl;
}
else if (znak == '-') {
cout << a << znak << b << "=" << a - b << endl;
if (a - b != b - a)
cout << b << znak << a << "=" << b - a << endl;
}
else if (znak == '*') {
cout << a << znak << b << "=" << a * b << endl;
}
else if (znak == '/') {

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 49

if (a != 0.0) {
cout << b << znak << a << "=" << b / a << endl;
}
if (b != 0.0 and a!=b) {
cout << a << znak << b << "=" << a / b << endl;
}
}
else {
cout << "Coś nie tak, znak nierozpoznany.\n";
}
}

Zadanie #1.9
#include <iostream>
using namespace std;
int main() {
setlocale(LC_ALL, "");
int x;
cin >> x;
if (x < 0) x--;
else if (x > 0) x++;
cout << x << endl;
if (x % 2 == 0) cout << "tak";
else cout << "nie";
}

Zadanie #1.10
#include <iostream>
using namespace std;
int main() {
setlocale(LC_ALL, "");

// 1. sposób
for (int i = 1; i <= 100; i++) cout << i << " "; // zmienna i żyje tylko w pętli for,
// nie istnieje poza nią
cout << endl;

// 2. sposób
for (int i = 100; i--;) cout << 100 - i << " ";
cout << endl;

// 3. sposób
for (int i = 0; 100 - i++; ) cout << i << " ";
cout << endl;

// 4. sposób
int i = 1; // teraz zmienna i żyje w programie (poza pętlami)
while (i <= 100) cout << i++ << " ";
cout << endl;

// 5. sposób
i = 1;
do {
cout << i++ << " ";
} while (i<=100);
cout << endl;
}

26589ec988c76404b19a97e88c6609a5
2
50 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie #1.11
#include <iostream>
using namespace std;
int main() {
setlocale(LC_ALL, "");
for (int i = 100; i >= 10; i--) {
if (i % 7 != 0) cout << i << " ";
}
}

Zadanie #1.12
#include <iostream>
using namespace std;
int main() {
setlocale(LC_ALL, "");
for (int i = -25; i <= 25; i++) {
if (i != 0) cout << i << " ";
}
}

Zadanie #1.13
#include <iostream>
using namespace std;
int main() {
setlocale(LC_ALL, "");
int ile = 0;
for (int i = 1; i <= 120; i++) {
if (i % 5 == 0 and i % 11 == 0) continue;
cout << i << " ";
ile++;
}
cout << "\n\nLiczb wyświetlonych: " << ile << endl;
cout << "\n\nLiczb pominiętych: " << 120 - ile << endl;
}

Zadanie #1.14
#include <iostream>
#include <vector>
using namespace std;
int main() {
setlocale(LC_ALL, "");
// wzór to cyklicznie powtarzający się ciąg 3, 1, 2, 1 itd.
vector<int> cykl = { 3,1,2,1 };
size_t elementy = 1;
while (elementy <= 100) {
cout << cykl[(elementy++ - 1) % 4] << " ";
// cykl[0], cykl[1], cykl[2], cykl[3], cykl[0] i tak 100 razy
}
}
/* Uwaga! Jak interpretować część (elementy++ - 1)?
Komputer spróbuje obliczyć różnicę (elementy++) - (1).
W tym celu musi obliczyć wartość po lewej i prawej stronie znaku odejmowania.
Wyrażenie elementy++ najpierw zwraca wartość elementy.

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 51

Wynosi ona 1, więc do różnicy z lewej strony zostanie wstawione 1.


Zatem operacja odejmowania ma postać 1-1, czyli 0.
Operator ++ po prawej stronie oczywiście zadziała, ale już po obliczeniu różnicy.
Spróbuj wyrażenia (++elementy – 1) i sprawdź, co się stanie.
Uwaga! Dla czytelności można było napisać to w dwóch liniach (jak poniżej), czasami wybieramy
bardziej skondensowany kod, a dobra znajomość kolejności operacji nie psuje czytelności.
---- postać czytelniejsza ----
cout << cykl[(elementy-1)%4] << " ";
elementy++;
----
*/

Zadanie #1.15
#include <iostream>
using namespace std;
int main() {
setlocale(LC_ALL, "");
// 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, ...
// wzór to kolejne liczby od 1, wyświetlane tyle razy, ile wynosi ta liczba. Zatem kolejny element to
// pięć piątek... potem sześć szóstek itd.
int n = 1, temp = 0;
int ile = 1;
while (ile <= 100) {
// najpierw temp porównany jest z n, potem temp rośnie o jeden
if (temp++ < n) {
cout << n << " ";
ile++;
}
else {
temp = 0;
n++;
}
}
/*
1 2 2 3 3 3 4 4 4 4 5 5 5 5 5 6 6 6 6 6 6 7 7 7 7 7 7 7 8 8 8 8 8 8 8 8 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10
10 10 10 10 11 11 11 11 11 11 11 11 11 11 11 12 12 12 12 12 12 12 12 12 12 12 12 13 13 13 13 13
13 13 13 13 13 13 13 13 14 14 14 14 14 14 14 14 14
*/
}

Zadanie #1.16
#include <iostream>
using namespace std;
int main() {
setlocale(LC_ALL, "");
// 100, 99, 97, 94, 90, 85, ...
// Kolejne liczby są mniejsze o liczbę rosnącą o jeden.
// Zatem następne będzie 85-6, czyli 79, potem 79-7 itd.
int ile = 1;
int n = 100;
while (ile <= 100) {
cout << n << " ";
n -= ile++;
}

26589ec988c76404b19a97e88c6609a5
2
52 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

/*
100 99 97 94 90 85 79 72 64 55 45 34 22 9 -5 -20 -36 -53 -71 -90 -110 -131 -153 -176 -200 -225 -251
-278 -306 -335 -365 -396 -428 -461 -495 -530 -566 -603 -641 -680 -720 -761 -803 -846 -890 -935 -981
-1028 -1076 -1125 -1175 -1226 -1278 -1331 -1385 -1440 -1496 -1553 -1611 -1670 -1730 -1791 -1853
-1916 -1980 -2045 -2111 -2178 -2246 -2315 -2385 -2456 -2528 -2601 -2675 -2750 -2826 -2903 -2981
-3060 -3140 -3221 -3303 -3386 -3470 -3555 -3641 -3728 -3816 -3905 -3995 -4086 -4178 -4271 -4365
-4460 -4556 -4653 -4751 -4850
*/
}

Zadanie #1.17
#include <iostream>
using namespace std;
int main() {
setlocale(LC_ALL, "");
// 6, 2, 8, 3, 10, 4, 12, 5, 14, 6, ...
// Kolejne wyrazy ciągu to 16 i 7. Mamy tu jakby dwa ciągi przemieszane. Jeden to parzyste liczby
// zaczynające się od 6, a drugi to kolejne liczby zaczynające się od 2. Oba ciągi przeplatają się...
int a = 6, b = 2;
for (int i = 1; i <= 100; i++) {
if (i % 2 == 1) { // ciąg a
cout << a << ", ";
a += 2;
}
else { // ciąg b
cout << b++ << ", ";
}
}
}

/*
6, 2, 8, 3, 10, 4, 12, 5, 14, 6, 16, 7, 18, 8, 20, 9, 22, 10, 24, 11, 26, 12, 28, 13, 30, 14, 32, 15, 34, 16, 36, 17,
38, 18, 40, 19, 42, 20, 44, 21, 46, 22, 48, 23, 50, 24, 52, 25, 54, 26, 56, 27, 58, 28, 60, 29, 62, 30, 64, 31,
66, 32, 68, 33, 70, 34, 72, 35, 74, 36, 76, 37, 78, 38, 80, 39, 82, 40, 84, 41, 86, 42, 88, 43, 90, 44, 92, 45,
94, 46, 96, 47, 98, 48, 100, 49, 102, 50, 104, 51
*/

Zadanie #1.18
#include <iostream>
using namespace std;
int main() {
setlocale(LC_ALL, "");
int pobrana;
do {
cout << "Podaj liczbę:";
cin >> pobrana;
cout << 2 * pobrana << "\n";
} while (pobrana < 1 or pobrana > 10);
}

Zadanie #1.19
#include <iostream>
using namespace std;
int main() {
setlocale(LC_ALL, "");
// wersja naiwna (więcej kroków, if w pętli)

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 53

for (int i = 0; i <= 1000; i++) {


if (i % 6 == 0) cout << i << " ";
}
cout << "\n\n\n";
// wersja sprytniejsza (liczby podzielne przez 6 to po prostu jej wielokrotności)
for (int i = 0; i <= 1000; i += 6) {
cout << i << " ";
}
}

Zadanie #1.20
#include <iostream>
#include <vector>
using namespace std;
int main() {
setlocale(LC_ALL, "");

vector<int> baza = { 1,4,7,6,3,7,23,-14,22,1 };


cout << baza.size() << endl; // 10 liczb w wektorze
vector<int> kopia;
for (auto e : baza) {
cout << e << " "; // pokazuje zawartość pierwszego wektora (baza)
if (e % 2 == 0) kopia.insert(kopia.begin(), e);
else kopia.push_back(e);
}
cout << "\n\n\n";
for (auto e : kopia) cout << e << " "; // pokazuje drugi wektor (kopia)
}

Zadanie #1.21
Przykładowe rozwiązanie 1.
#include <iostream>
#include <vector>
using namespace std;
int main() {
setlocale(LC_ALL, "");
vector<int> v;
int temp;
for (int i = 5; i--;) {
cin >> temp;
v.push_back(temp);
cout << temp << " ";
}
// test na ciąg rosnący (każda kolejna liczba musi być większa)
bool jest = true;
for (size_t pozycja = 0; pozycja < v.size() - 1; pozycja++) {
if (v[pozycja] >= v[pozycja + 1]) {
jest = false;
break;
}
}
if (jest) cout << "Ciąg jest rosnący.";
}

26589ec988c76404b19a97e88c6609a5
2
54 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Przykładowe rozwiązanie 2.
#include <iostream>
using namespace std;

int main() {
setlocale(LC_ALL, "");
int poprzednia;
int obecna;
bool rosnacy = true;

cin >> poprzednia;

for (int i = 4; i--;) {


cin >> obecna;
if (rosnacy) { // jeśli wiemy, że ciąg może być rosnący
if (obecna <= poprzednia)
rosnacy = false;
else
poprzednia = obecna;
}
}
if (rosnacy)
cout << "Ciąg jest rosnący" << endl;
}

Zadanie #1.22
#include <iostream>
#include <vector>
using namespace std;
int main() {
setlocale(LC_ALL, "");
vector<int> v;
int pomoc;
while (true) {
cout << ": ";
cin >> pomoc;
v.push_back(pomoc);
if (v.size() >= 2 && v.back() == v[v.size() - 2]) break; // porównanie dwóch
// ostatnich elementów
}
}

Zadanie #1.23
#include <iostream>
#include <vector>
using namespace std;
int main() {
setlocale(LC_ALL, "");
vector<int> v;
int pomoc;
while (v.size() < 10) {
cout << ": ";
cin >> pomoc;
bool istnieje = false;

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 55

for (auto e : v)
if (pomoc == e) {
istnieje = true;
break;
}
if (!istnieje) v.push_back(pomoc);
cout << "liczba elementów w wektorze: " << v.size() << "\n";
}
cout << "ilość=" << v.size() << endl;
for (auto e : v) cout << e << " "; // podgląd wektora
}

Zadanie #1.24
#include <iostream>
#include <vector>
using namespace std;
int main() {
setlocale(LC_ALL, "");
vector<char> samogloski = { 'e','y','u','i','o','a' };
vector<char> znaki;
char pomoc;
do {
cout << ": ";
cin >> pomoc;
// test na samogłoskę
bool jest = false;
for (char e : samogloski) if (e == pomoc) {
jest = true;
break;
}
if (jest)
znaki.insert(znaki.begin(), pomoc); // dodaj na początek
else if (pomoc == '*' and znaki.size())
znaki.erase(znaki.begin()); // usuwam pierwszy
else if (pomoc == '#' and znaki.size())
znaki.pop_back(); // wyrzucam z końca
else znaki.push_back(pomoc); // dodaj na koniec
// za każdym razem prezentuj zawartość wektora w celu monitorowania operacji
for (auto e : znaki) cout << e;
cout << endl;
} while (pomoc != '!');
}
/* Ciekawostka: W przypadku kontenerów vector<> usuwanie i dodawanie na końcu wektora jest
wydajne.
Operacje usuwania/dodawania w środku lub na początku wymagają przenoszenia
kontenera w pamięci w nowe miejsce. Jednak dla potrzeb edukacji i przy tak
malutkich programach kwestie optymalizacji możemy świadomie pomijać. */

Zadanie #1.25
#include <iostream>
#include <vector>
using namespace std;
int main() {
setlocale(LC_ALL, "");

26589ec988c76404b19a97e88c6609a5
2
56 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

vector<float> liczby;
float a, b;
do {
cout << "Podaj liczbę: ";
cin >> a;
cout << "Podaj liczbę: ";
cin >> b;
liczby.push_back(a);
liczby.push_back(b);
if (a * b <= 1000.0) liczby.push_back(a * b);
// oglądam zawartość dla prezentacji
for (auto e : liczby) cout << e << " ";
cout << endl;
} while (a * b <= 1000);
}

Zadanie #1.26
#include <iostream>
#include <vector>
using namespace std;
int main() {
setlocale(LC_ALL, "");
vector<int> v = { 1,2,4,3,6,8,7,7,8,3,4,5,6,7,1,3,9,1,0,4,2,3,6,9 };

// a
for (size_t i = 0; i < v.size() - 2; i++) {
if (v[i] <= v[i + 1] and v[i + 1] <= v[i + 2]) // niemalejąca trójka liczb w wektorze?
cout << v[i] << " " << v[i + 1] << " " << v[i + 2] << endl;
}

// b
int start = 0, pozm = 0, dl = 1, dlm = 0; // pozm: pozycja maksymalnego ciągu, dlm:
// długość maksymalnego ciągu
for (size_t poz = 0; poz < v.size() - 1; poz++) {
if (v[poz] <= v[poz + 1]) { // porządek zachowany
if (dl == 1) start = poz; // pierwszy porządek po nieporządku
dl++; // długość obecnego znalezionego porządku
if (dlm < dl) { // jeżeli obecna długość jest większa niż dotychczasowa maksymalna,
// zapamiętuję ją
dlm = dl;
pozm = start;
}
}
else dl = 1; // brak porządku, zaczynamy od nowa numerowanie (nowa pozycja startowa,
// nowa długość)
}
cout << "Najdłuższy podciąg ";
for (int i = pozm; i < pozm + dlm; i++) cout << v[i] << ",";
cout << " zaczyna się na pozycji " << pozm << " i ma długość " << dlm << endl;

// c
// zauważ, że największą liczbą w wektorze jest 9, najmniejszą 0. Wykorzystamy to!
vector<int> liczniki;
liczniki.resize(10, 0); // 10 elementów o pozycji 0-9, z wartościami 0
cout << endl;
for (auto e : liczniki) cout << e << ","; // wszędzie wartości 0

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 57

cout << endl;


for (auto e : v) liczniki[e]++; // procedura zliczania! :D
for (auto e : liczniki) cout << e << ","; // wartości po zliczaniu
cout << endl;

// prezentacja zliczenia
for (int poz = 0; poz < liczniki.size(); poz++) {
cout << "Liczba " << poz << " wystąpień: " << liczniki[poz] << endl;
}
cout << "\n\n";
}

Zadanie #1.27
#include <iostream>
#include <vector>
using namespace std;
int main() {
setlocale(LC_ALL, "");
vector<int> v1 = { 1,3,5,7,9 };
vector<int> v2 = { 1,4,7,11,15 };
vector<int> v3 = { 1,2,3,4,5,6,7,8,9,20 };

// a
cout << "v1 część wspólna z v2 = ";
for (auto e1 : v1) {
for (auto e2 : v2) {
if (e1 == e2) cout << e1 << " ";
}
}
cout << "\n\n";

// b
vector<int> v12{}; // wektor z sumą v1+v2
v12.insert(v12.begin(), v1.begin(), v1.end()); // v12 zawiera wszystko z v1
vector<int> v312; // wektor z różnicą v3-(v1+v2)
// dodam elementy z v2 do v12 (ze sprawdzeniem, czy ich tam już nie ma)
for (auto dodaj : v2) {
bool jest = false;
for (auto e : v12) {
if (e == dodaj) {
jest = true; // element już jest, nie dodam go
break;
}
}
if (!jest) v12.push_back(dodaj); // nie ma, więc dodaję
}
cout << "v3 - v1+v2 = ";
for (auto e : v3) {
bool jest = false;
for (auto f : v12) {
if (e == f) {
jest = true;
break;
}
}
if (!jest) v312.push_back(e);

26589ec988c76404b19a97e88c6609a5
2
58 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

}
for (auto e : v312) cout << e << " ";
cout << "\n\n";

// c
vector<int> v123 = v12; // v123 będzie sumą v12 i v3, gdzie v12 był sumą v1 i v2
cout << "v1+v2+v3 = ";
for (auto dodaj : v3) {
bool jest = false;
for (auto e : v123) {
if (e == dodaj) {
jest = true;
break;
}
}
if (!jest) v123.push_back(dodaj); // nie ma, więc dodaję
}
for (auto e : v123) cout << e << " ";
cout << endl;
// c, wersja po cwaniacku
// można zauważyć, że v3-(v1+v2) daje liczby, które po dodaniu do v12 dadzą odpowiedź :)
vector<int> suma = v12;
// na koniec wektora suma() doklejam zawartość v312
suma.insert(suma.end(), v312.begin(), v312.end());
cout << "v1+v2+v3 = ";
for (auto e : suma) cout << e << " ";
}

Zadanie #1.28
#include <iostream>
#include <vector>
using namespace std;
int main() {
setlocale(LC_ALL, "");
vector<char> cyfry;
char znak;
do {
cout << ": ";
cin >> znak;
// skorzystaj z faktu, że char jest łatwo konwertowalny na int, gdzie '0' ma kod 48 itd.
if (znak >= 48 and znak <= 48 + 9) {
cyfry.push_back(znak);
cout << "dodałem " << znak - 48 << "\n";
}
else {
cout << "ignoruję znak\n";
}
} while (cyfry.size() < 5);
long long int x = 0;
for (int poz = cyfry.size() - 1, podstawa = 1; poz >= 0; poz--, podstawa *= 10) {
x += (cyfry[poz] - 48) * podstawa;
}
cout << "Liczba to: " << x << endl;
}

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 59

Zadanie #1.29
#include <iostream>
#include <vector>
using namespace std;
int main() {
setlocale(LC_ALL, "");
vector<bool> dane = {
1,1,0,1,0,0,0,0,0,1,1,1,1,1,0,1,0,0,1,0,1,1,0,0,0,1,1,0,0,1,1,1,0,0,1,0,0,0,0,0,1,1,
0,0,0,1,1,1,1,1,0,0,0,1,1,0,1,0,1,0,0,0,1,0,0,0,0,1,0,1,1,1,1,1,1,1,1,0,0,1,0,0,1,1,
1,0,1,0,0,1,1,0,1,0,0,1,1,0,1,1,1,0,0,0,0,1,0,0,0,1,1,0,1,0,1,1,0,1,0,1,1,1,1,1,1,0,
0,1,0,0,1,1,1,0,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,0,1,1,0,1,1,0,0,1,1,0,0,1,0,0,1,0,
0,0,0,1,0,1,0,1,0,0,1,0,1,1,0,0,1,0,0,0,1,0,0,1,1,0,1,0,1,0,1,0,1,0,1,1,0,1,1,1,0,0,
1,1,0,0,1,0,0,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,0,0,1,1,1,1,1,1,1,0,1,0,1,0,0,0,1,1,0,0,
0,1,0,0,0,0,1,1,0,1,0,1,1,0,0,0,1,1,1,1,0,1,0,0,1,0,1,1,0,0,1,0,0,0,1,0,0,0,0,0,1,1,
0,1,1,1,1,0,1,0,0,1,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,0,0,1,1,1,0,0,0,1,1,1,1,0,0,1,0,0,
0,1,1,1,1,0,0,0,1,1,0,1,0,1,0,0,1,1,1,1,1,0,1,0,1,1,1,1,1 };
// 1 i 0 są łatwo konwertowalne na true i false
cout << "Liczba dni: " << dane.size() << endl;

// a
int sukces_dni = 0;
for (bool dzien : dane) {
if (dzien) sukces_dni++;
}
cout << "W czasie " << dane.size() << " dni Kasia odniosła sukces " << sukces_dni <<
´" razy.\n\n";

// b
int okresy5 = 0; // odpowiedź
int czas = 0; // pomocnicza zmienna
vector<int> poczatki; // początkowe dni okresów porażek trwających minimum 5 dni
int dzien = 1;
for (bool sukces : dane) {
if (!sukces) { // jeżeli true
czas++;
}
else {
if (czas >= 5) {
okresy5++;
poczatki.push_back(dzien - czas);
}
czas = 0;
}
dzien++;
}
cout << "Okresów trwających przynajmniej 5 dni bez właściwej diety było: "
´<< okresy5 << endl;
cout << "Początkowe dni okresów to: ";
for (auto start : poczatki) cout << start << " ";
}

Zadanie #1.30
#include <iostream>
#include <vector>
using namespace std;

26589ec988c76404b19a97e88c6609a5
2
60 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

int main() {
setlocale(LC_ALL, "");
long long int waga = 1;
int okrazenia = 13;
vector<int> okrazenia_waga;
okrazenia_waga.resize(okrazenia); // gromadzimy wagę po kolejnych okrążeniach
okrazenia_waga[0] = 1; // pierwsze okrążenie (liczymy od 0)
okrazenia_waga[1] = 1; // drugie okrążenie
for (int okr = 2; okr < okrazenia; okr++) {
// suma wag ostatnich dwóch okrążeń
okrazenia_waga[okr] = okrazenia_waga[okr - 1] + okrazenia_waga[okr - 2];
}
cout << "Po okrążeniu = " << okrazenia << " waga bloba to " << okrazenia_waga
´[okrazenia - 1] << endl;
cout << "A oto historia wagi w kolejnych okrążeniach:";
for (auto waga : okrazenia_waga) cout << waga << " ";
}

Zadanie #1.31

Rozwiązanie a)
Dwa razy wyświetli się 1. Za pierwszym razem najpierw a jest inkrementowane
(++a), dopiero potem trafia do strumienia wyjściowego. Za drugim razem a jako
wartość 1 bezpośrednio trafia do strumienia.

Rozwiązanie b)
Wyświetli się 0. Prawostronny operator inkrementacji ++ ma mniejszy priorytet
niż odejmowanie, dlatego najpierw obliczona zostanie wartość a–1, czyli będzie
to 0 (bo a to wciąż 1). Następnie wykonane zostanie porównanie 0&&1, które
oczywiście daje wartość false, co przy wyświetlaniu pokaże 0. Pod koniec inkre-
mentacja zwiększy a do wartości 2 i to ona wyświetli się w drugiej linijce kodu.

Rozwiązanie c)
Siedem (1+6–0=7). Kolejność działań jest jak na matematyce, jednak wynik dzie-
lenia literałów całkowitych 4/5 jest konwertowany na liczbę całkowitą poprzez
redukcję części ułamkowej. Zatem 4/5, choć wynosi 0.8, to po odcięciu części po
przecinku (redukcja do typu całkowitego, bo takiego typu są literały 4 oraz 5)
jest to po prostu 0.

Rozwiązanie d)
Operator and ma mniejszy priorytet niż operator <<, w efekcie komputer pró-
buje wykonać jakby operację: (cout << true) and (false << endl), co jest —
nie oszukujmy się — absurdalne ! Nie da się logicznie za pomocą koniunkcji
(i) połączyć części objętych nawiasem.

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 61

Zadanie #1.32
#include <iostream>
#include <vector>
using namespace std;
//////////////////////////////////////////////////////
int main() {
vector<int> x = { 2,7,1,1,4,9,3,2,1,4,1,9,6,1,3,0,1,2,3,6,8,5,6,9,
3,0,8,1,8,8,7,0,7,8,5,0,2,2,3,7,1,7,2,4,7,7,5,9,0,7,7,9,2,2,2,7,
0,0,5,4,6,3,9,3,5,1,0,0,9,2,9,2,8,5,0,8,5,7,0,9,6,4,9,7,8,8,6,5,
4,3,2,5,8,9,4,6,8,7,9,9 };
int odl = -1;
for (size_t poz = 0; poz < x.size(); poz++) {
if (x[poz] == 9) {
if (odl != -1) {
cout << odl << " ";
}
odl = 0;
}
else if (odl != -1) odl++;
}
}

Zadanie #1.33
#include <iostream>
#include <vector>
using namespace std;
//////////////////////////////////////////////////////
int main() {
vector<int> x = { 2,7,1,1,4,9,3,2,1,4,1,9,6,1,3,0,1,2,3,6,8,5,6,9,
3,0,8,1,8,8,7,0,7,8,5,0,2,2,3,7,1,7,2,4,7,7,5,9,0,7,7,9,2,2,2,7,
0,0,5,4,6,3,9,3,5,1,0,0,9,2,9,2,8,5,0,8,5,7,0,9,6,4,9,7,8,8,6,5,
4,3,2,5,8,9,4,6,8,7,9,9 };
int ile_razy_sasiadki = 0;
int dziesiec = 0;
for (size_t poz = 0; poz < x.size() - 1; poz++) {
if (x[poz] == x[poz + 1]) {
ile_razy_sasiadki++;
cout << x[poz] << "," << x[poz + 1] << endl;
}
if (x[poz] + x[poz + 1] == 10) {
dziesiec++;
cout << x[poz] << "," << x[poz + 1] << "=10" << endl;
}
}
cout << "a) " << ile_razy_sasiadki << endl; // 11
cout << "b) " << dziesiec << endl; // 6
}

Zadanie #1.34
#include <iostream>
using namespace std;
//////////////////////////////////////////////////////
int main() {

26589ec988c76404b19a97e88c6609a5
2
62 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

setlocale(LC_ALL, "");
char znak;
int suma(0);
do {
cout << "Podaj znak:";
cin >> znak;
cout << "Wpisano znak " << znak;
if (!(znak >= 65 and znak <= 90)
and !(znak >= 97 and znak <= 122)
and !(znak >= 48 and znak <= 57)) {
cout << "Wprowadzono niedozwolony znak!\n";
continue;
}
suma += znak;
cout << ", wartość znaku: " << znak - 0;
cout << ", aktualna suma = " << suma << endl;
} while (suma <= 350);
}

Zadanie #1.35
Przykładowe rozwiązanie 1.
#include <iostream>
#include <vector>
using namespace std;
//////////////////////////////////////////////////////
int main() {
setlocale(LC_ALL, "");
vector<int> v = { 3,2,4,3,5,4,6,5,6,8 };
while (v.size()) {
cout << v.front() << " ";
v.front() = v.back();
v.pop_back();
}
}

Przykładowe rozwiązanie 2.
#include <iostream>
#include <vector>
using namespace std;
//////////////////////////////////////////////////////
int main() {
setlocale(LC_ALL, "");
vector<int> v = { 3,2,4,3,5,4,6,5,6,8 };
auto iter = v.begin();
while (iter != v.end()) cout << *iter++ << " "; // czary :)
// iter++ przesuwa wskaźnik (iterator) na kolejny element,
// a operator * pobiera wartość, na którą wskazuje iterator.
// Całość trwa, dopóki iterator nie wskoczy za ostatni element wektora
}

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 63

Zadanie #1.36
#include <iostream>
using namespace std;
//////////////////////////////////////////////////////
int main() {
setlocale(LC_ALL, "");
float a = 5, b = 4, c = 3; // trójkąt egipski o bokach 3, 4, 5 działa :)
// sugestia: sprawdź wyniki dla boków: a=10, b=10, c=sqrt(200) oraz dla a=4, b=3, c=2.
// Pierwszy przypadek tworzy trójkąt prostokątny, drugi nie
bool sukces = false;
// przetestuję trzy możliwe przypadki boków
if (a * a + b * b == c * c) sukces = true;
else if (a * a + c * c == b * b) sukces = true;
else if (b * b + c * c == a * a) sukces = true;
if (sukces) cout << "No i mamy możliwość zbudowania trójkąta prostokątnego.\n";
else cout << "Nie da rady zbudować trójkąta prostokątnego.\n";
}

Zadanie #1.37
#include <iostream>
using namespace std;
//////////////////////////////////////////////////////
int main() {
setlocale(LC_ALL, "");
float a, b;
a = 10.2;
b = 11.7;
cout << "Powinniśmy otrzymać " << a * b << ", jednak bez korzystania ze znaku *\n";
cout << "Bez * = " << a / (1. / b) << endl;

float A = 10.25;
int B = 12;
cout << "Powinniśmy otrzymać " << A * B << ", jednak bez korzystania ze znaku * i / \n";
float suma = 0.; // 0. to to samo co 0.0
while (B > 0) {
suma += A;
B -= 1;
}
cout << "Bez * / = " << suma << endl;
}

Zadanie #1.38
#include <iostream>
#include <vector>
using namespace std;
//////////////////////////////////////////////////////
int main() {
setlocale(LC_ALL, "");
vector<int> v = { 1,2,3,2,5,6,9,1,3,7,5,8,0,9,3,1,2,5,7,6,3,4,2,1,0,8,9,7,8,
4,6,3,2,5,4,7,8,9,1,3,2,5,4,7,5,6,8,0,1,2,3,6,5,8,7,1,1,2,3,4,4,5,5,6,8,
9,0,9,8,1,9,7,5,4,1,2,7,6,9,3,4,2,6 };

26589ec988c76404b19a97e88c6609a5
2
64 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

// Rozwiązanie 1.
for (unsigned poz = 0; poz < v.size(); poz++) {
unsigned suma = 0;
for (int dl = 0; poz + dl < v.size(); dl++) {
suma += v[poz + dl];
if (suma == 10) {
cout << "PODCIĄG: ";
for (unsigned i = poz; i <= poz + dl; i++) cout << v[i] << " ";
cout << "POZYCJE: ";
for (unsigned i = poz; i <= poz + dl; i++) cout << i << " ";
cout << endl;
}
else if (suma > 10) break;
}
}
cout << "\n\n";
// Rozwiązanie 2.
int N = v.size();
for (int dlugosc_podciagu = N; dlugosc_podciagu >= 1; dlugosc_podciagu--) {
for (int start = 0; start + dlugosc_podciagu <= N; start++) {
unsigned koniec = start + dlugosc_podciagu - 1;
unsigned suma = 0;
for (unsigned x = start; x <= koniec; x++) {
suma += v[x];
if (suma > 10) break;
}
if (suma == 10) {
cout << "PODCIĄG: ";
for (unsigned x = start; x <= koniec; x++) cout << v[x] << " ";
cout << "POZYCJE: ";
for (unsigned x = start; x <= koniec; x++) cout << x << " ";
cout << endl;
}
}
}
}

Zadanie #1.39
#include <iostream>
#include <vector>
using namespace std;
//////////////////////////////////////////////////////
int main() {
setlocale(LC_ALL, "");
vector<char> znaki = { 'x','P','Q','4','\n','%','u','@','e',
'T','B','$', '!',':','"','1','<','d','k','L','$',')','$','B','x',
'w','q','P','c','X','B','>','?','[','r','x','$','#','}','|','d','l','n','b','V','!' };
unsigned suma_znakow = 0;
for (auto e : znaki) if (e >= 48 and e <= 48 + 9) suma_znakow += e - 48;
cout << "Suma znaków: " << suma_znakow << endl;
// usuwam znaki, które są na początku i na końcu, aby ich nie wyświetlać
char s = znaki.front();
char k = znaki.back();
for (int poz = 0; poz < znaki.size(); poz++) {
if (znaki[poz] == s or znaki[poz] == k) {
znaki.erase(znaki.begin() + poz);

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 65

poz--;
continue;
}
}
// rozpoczynam poszukiwania powtarzających się znaków, które nie leżały na początku
// i końcu wektora
for (int poz = 0; poz < znaki.size(); poz++) {
bool dublet = false;
for (int spr = poz + 1; spr < znaki.size(); spr++) {
if (znaki[poz] == znaki[spr]) { // jest powtórka
dublet = true;
// teraz usuwam powtórzenia, by ponownie nie wyświetlić powtórki
znaki.erase(znaki.begin() + spr);
spr--;
}
}
if (dublet) {
cout << znaki[poz] << endl;
}
}
}

Zadanie #1.40
Jak się spało?

Część 2.
(#2) Pierwotniaczki
Zadanie #2.1
#include <iostream>
#include <vector>
using namespace std;
//////////////////////////////////////////////////////
string zad1(string imie) {
string samogloski = "eyuioaEYUIOA";
int ilerazy = 0;
for (auto literka : imie) {
if (samogloski.find(literka) != string::npos) ilerazy++;
}
string wynik("");
while (ilerazy--) wynik += imie + " ";
return wynik;
}
int main() {
setlocale(LC_ALL, "");
vector<string> imiona={ "Toudi", "Barnaba", "Pantofelek", "Max"}; // test dla kilku imion
while (imiona.size()) {
cout << imiona.back() << ":" << endl;
cout << zad1(imiona.back()) << endl;
imiona.pop_back();
}
}

26589ec988c76404b19a97e88c6609a5
2
66 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie #2.2
#include <iostream>
#include <ctime>
#include <vector>
using namespace std;
//////////////////////////////////////////////////////
int zad2(vector<int>& v) {
int maks = v[0];
int poz = -1;
for (int i = 0; i < v.size(); i++) {
if (v[i] >= maks) {
maks = v[i];
poz = i;
}
}
v.erase(v.begin() + poz);
return maks;
}
int suma(vector<int> v) {
int suma = 0;
for (auto e : v) suma += e;
return suma;
}
int main() {
setlocale(LC_ALL, "");
srand(time(0)); // bez tego losowanie z wykorzystaniem funkcji rand() zawsze zwróci ten sam
// wynik
vector<int> v;
for (int i = 3; i--;) {
v.push_back(rand() % 20 + 1); // [dowolna liczba z zakresu 1-20]
cout << v.back() << " ";
}
cout << endl;
int maks = zad2(v);
int s = suma(v);
while (maks--) cout << s << " ";
}

Zadanie #2.3
#include <iostream>
#include <ctime>
using namespace std;
//////////////////////////////////////////////////////
string wylosowany_napis() {
// angielskie
string litery = "qazwsxedcrfvtgbyhnujmikolpQAZWSXEDCRFVTGBYHNUJMIKOLP";
char znak;
int ile = 0;
string wynik;
do {
znak = litery[rand() % litery.size()]; // losuję pozycję w napisie
wynik += znak;
ile++;
} while (znak != 'z' and znak != 'A');

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 67

cout << ile << endl;


return wynik;
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
cout << wylosowany_napis() << endl;
}

Zadanie #2.4
Przykładowe rozwiązanie 1.
#include <iostream>
#include <ctime>
#include <vector>
using namespace std;
//////////////////////////////////////////////////////
vector<int> vector_generator(int ile = 10, int start = 0, int koniec = 20) {
// gdy do argumentu przypiszesz wartość, będzie ona domyślna
vector<int> v;
for (int i = 1; i <= ile; i++) {
int losowa = rand() % (koniec - start + 1) + start;
int pozycja = (v.size()) ? rand() % v.size() : 0;
v.insert(v.begin() + pozycja, losowa); // nie nadpisze, przesunie
}
return v;
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
for (auto e : vector_generator(20)) cout << e << " ";
}

Przykładowe rozwiązanie 2.
#include <iostream>
#include <ctime>
#include <vector>
using namespace std;
//////////////////////////////////////////////////////
int wylosuj_liczbe(int poczatek, int koniec) {
return rand() % (koniec - poczatek + 1) + poczatek;
}

bool czy_wszystkie_zajete(const vector<bool>& wektor) {


for (auto i : wektor) {
if (!i) return false;
}
return true;
}

int main() {
setlocale(LC_ALL, "");
srand(time(0));

vector<int> liczby(20, -1); // tworzę wektor złożony z dwudziestu liczb równych -1


vector<bool> zajete_indeksy(liczby.size(), false); // tworzę wektor zajętych indeksów
// na początku żaden nie jest zajęty (true - zajęty)

26589ec988c76404b19a97e88c6609a5
2
68 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

while (!czy_wszystkie_zajete(zajete_indeksy)) { // jeżeli nie wszystkie zajęte


int wylosowana = wylosuj_liczbe(0, 20);
int indeks = wylosuj_liczbe(0, liczby.size() - 1);
while (zajete_indeksy[indeks]) { // losuj, aż znajdziesz puste miejsce
indeks = wylosuj_liczbe(0, liczby.size() - 1);
}

liczby[indeks] = wylosowana;
zajete_indeksy[indeks] = true;
}

for (auto i : liczby) {


cout << i << " ";
}
}

Zadanie #2.5
#include <iostream>
#include <ctime>
using namespace std;
//////////////////////////////////////////////////////
void zad5() {
unsigned ile = 0;
while (true) {
int x = rand() % 101;
cout << x << " ";
if (x != 100) ile++;
else break;
}
cout << "\nIle = " << ile << " nie licząc 100." << endl;
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
zad5();
}

Zadanie #2.6
#include <iostream>
#include <ctime>
#include <vector>
using namespace std;
//////////////////////////////////////////////////////
void zad6() {
vector<int> v;
// uważaj, może wypaść 0 nieznaną ilość razy
unsigned uj = 0;
unsigned dod = 0;
unsigned parz = 0;
for (int i = 10; i--;) {
v.push_back(rand() % 21 - 10); // [-10:10]
if (v.back() < 0) uj++;
if (v.back() > 0) dod++;
if (v.back() % 2 == 0) parz++;
}

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 69

cout << "Uj=" << uj << " Dod=" << dod << " Parz=" << parz
<< " Nieparz=" << 10 - parz << endl;
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
zad6();
}

Zadanie #2.7
#include <iostream>
#include <ctime>
#include <vector>
using namespace std;
//////////////////////////////////////////////////////
int szukajMaksa(vector<int>& v) {
int maks = v[0];
int ost_p(0);
for (int poz = 0; poz < v.size(); poz++) {
if (maks < v[poz]) {
maks = v[poz];
ost_p = poz;
}
}
v[ost_p] = -1; // gwarancja, że już tej liczby nie uznam za maksymalną
return maks;
}
void zad7() {
vector<int> v;
for (int i = 20; i--;) {
v.push_back(rand() % 1001); // 0-1000
cout << v.back() << " ";
}
cout << v.size() << endl;
cout << "\n\n";
for (int trzy = 3; trzy--;) {
cout << szukajMaksa(v) << endl;
}
}

int main() {
setlocale(LC_ALL, "");
srand(time(0));
zad7();
}

Zadanie #2.8
#include <iostream>
#include <ctime>
#include <vector>
#include <cmath>
#include <iomanip>
using namespace std;
//////////////////////////////////////////////////////
double double_01_Generator_simple() { // wersja 1., sztywna

26589ec988c76404b19a97e88c6609a5
2
70 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

return rand() % 1001 / 1000.0;


}

// wersja 2. z funkcją pow() z biblioteki <cmath>


// pow(a,b) zwraca a do potęgi b <cmath>
double double_01_Generator_v1(int poprzecinku = 3) {
unsigned long long d = pow(10, poprzecinku);
unsigned long long x = rand() % d;
cout << x << " / " << d * 1.0 << endl;
return x / (d * 1.0);
}
// wersja 3., gdy nie znam pow()
double double_01_Generator_v2(int poprzecinku = 3) {
unsigned long long d = 1;
for (int i = 1; i <= poprzecinku; i++) d *= 10;
unsigned long long x = rand() % d;
cout << x << " / " << d * 1.0 << endl;
return x / (d * 1.0); // pow(a,b) zwraca a do potęgi b <cmath>
}

int main() {
setlocale(LC_ALL, ""); srand(time(0));
// wszystkie funkcje zwracają liczbę [0,1] z różną dokładnością po przecinku
cout << fixed; // będzie tyle miejsc po przecinku, ile setprecision "powie"
cout << setprecision(3) << double_01_Generator_simple() << endl << endl;
// zawsze 3 miejsca po przecinku
cout << setprecision(3) << double_01_Generator_v1(3) << endl;
// 3 miejsca po przecinku
cout << setprecision(5) << double_01_Generator_v1(5) << endl;
// 5 miejsc po przecinku
cout << setprecision(2) << double_01_Generator_v2(2) << endl;
// 2 miejsca po przecinku
cout << setprecision(6) << double_01_Generator_v2(6) << endl;
// 6 miejsc po przecinku
}

Zadanie #2.9
#include <iostream>
#include <ctime>
#include <vector>
#include <cmath>
#include <iomanip>
using namespace std;
//////////////////////////////////////////////////////
double double_simple_Generator() { // wersja nieuniwersalna [-1.000:1.000]
return (rand() % 2001 - 1000) / 1000.0;
}
// double_Generator, wersja uniwersalna. Pozwala wygenerować
// liczbę z zakresu [a;b] o podanej precyzji liczb po przecinku,
// funkcja pow() z biblioteki <cmath> : pow(a,b) = a do potęgi b
double double_Generator(int start, int koniec, int poprzecinku = 3) {
long long d = pow(10, poprzecinku);
long long x = rand() % (koniec * d - start * d + 1) + start * d;
return x / (d * 1.0);
}
vector<double> zad9() {

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 71

vector<double> v;
double suma = 0.0;
for (int i = 20; i--;) {
v.push_back(double_simple_Generator()); // 20 losowych
suma += v.back();
}
cout << "Średnia = " << suma / 20.0 << "\n\n";
return v; // zwróć wylosowany wektor
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));

for (auto e : zad9()) cout << e << " ";


cout << "\n\n";

// dodatkowa prezentacja funkcji double_Generator()


// liczba [50:1000] z 1 miejscem po przecinku
cout << fixed << setprecision(1) << double_Generator(50, 1000, 1) << "\n";
// liczba [-10:10] z 5 miejscami po przecinku
cout << fixed << setprecision(5) << double_Generator(-10, 10, 5) << "\n";
}

Zadanie #2.10
#include <iostream>
#include <ctime>
using namespace std;
//////////////////////////////////////////////////////
pair<int,char> zad10() {
int temp, L = rand() % 11 + 20;
temp = L;
cout << "L=" << L << endl << ":";
char Z;
cin >> Z;
while (temp--) cout << Z;
cout << endl;
return { L, Z };
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
auto p = zad10();
// zerknij na to ;)
cout << string(p.first,p.second) << endl;
}

Zadanie #2.11
#include <iostream>
using namespace std;
//////////////////////////////////////////////////////
bool jestParzysta(unsigned x) {
return !(x & 1);
}
int main() {
cout << jestParzysta(10) << endl;
cout << jestParzysta(13) << endl;
}

26589ec988c76404b19a97e88c6609a5
2
72 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie #2.12
#include <iostream>
#include <iomanip>
using namespace std;
//////////////////////////////////////////////////////
double zlep(long long int a, long long int b) {
// wartość bezwzględna to funkcja abs() z biblioteki <cmath>,
// ale można zrobić szybką operację:
if (b < 0) b = -b; // zamiast abs()
long long int temp = b;
double d = 10;
while (temp / 10) {
d *= 10;
temp /= 10;
}
return a + b / d;
}
void zad12() {
int a, b;
cout << "Podaj a b:";
cin >> a >> b;
cout << setprecision(15) << zlep(a, b) << endl;
}
int main() {
setlocale(LC_ALL, "");
zad12();
}

Zadanie #2.13
#include <iostream>
#include <ctime>
using namespace std;
//////////////////////////////////////////////////////
void rysuj(char znak, int wiersze, int kolumny) {
while (wiersze--) {
for (int i = 1; i <= kolumny; i++)
cout << znak;
cout << endl;
}
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
char znak;
int a, b;
cout << "Znak: ";
cin >> znak;
a = rand() % 6 + 5;
b = rand() % 6 + 5;
rysuj(znak, a, b);
}

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 73

Zadanie #2.14
#include <iostream>
#include <ctime>
#include <vector>
using namespace std;
//////////////////////////////////////////////////////
vector<int> losowanko() {
vector<int> v;
int losowa, od = 1;
do {
losowa = rand() % (1000 - od + 1) + od;
cout << "losowa=" << losowa << endl;
od = losowa;
v.push_back(losowa);
} while (losowa < 1000);
return v;
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
for (auto e : losowanko()) cout << e << " ";
}

Zadanie #2.15
#include <iostream>
#include <ctime>
#include <vector>
using namespace std;
//////////////////////////////////////////////////////
void zad15() {
vector<int> v;
int ile = rand() % 91 + 10; // losowa ilość
while (ile--) v.push_back(rand() % 100 + 1); // generuję wektor
cout << "Przed: ";
for (int i = v.size() - 1; i >= 0; i--) cout << v[i] << " ";
cout << endl;
for (auto& e : v) {
if (e & 1) e = -e;
else e = 0;
}
cout << "Po: ";
for (int i = v.size() - 1; i >= 0; i--) cout << v[i] << " ";
cout << "\n\n";
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
zad15();
}

Zadanie #2.16
#include <iostream>
#include <ctime>
using namespace std;
//////////////////////////////////////////////////////

26589ec988c76404b19a97e88c6609a5
2
74 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

void rysuj(char znak, int n) {


int temp = n;
while (n--) {
cout << string(temp, znak) << endl; // string(ile_razy, znak)
}
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
rysuj('#', rand() % 8 + 5); // 5-12
cout << "\n";
rysuj('$', 5);
}

Zadanie #2.17
#include <iostream>
#include <ctime>
using namespace std;
//////////////////////////////////////////////////////
void szachownica(char znak, int n) {
for (int w = 1; w <= n; w++) {
for (int k = 1; k <= n; k++)
// gdy w oraz k są równocześnie parzyste lub nieparzyste, pokaż znak; jeśli nie, to spacje
if ((w & 1 and k & 1) or (!(w & 1) and !(k & 1))) cout << znak;
else cout << ' ';
cout << endl;
}
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
szachownica('#', rand() % 8 + 5);
cout << "\n";
szachownica('$', 12);
}

Zadanie #2.18
#include <iostream>
#include <ctime>
using namespace std;
//////////////////////////////////////////////////////
void kwadrat_pusty(char znak, int n) {
for (int w = 1; w <= n; w++) {
for (int k = 1; k <= n; k++)
if (w == 1 or w == n or k == 1 or k == n) cout << znak;
else cout << ' ';
cout << endl;
}
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
kwadrat_pusty('#', rand() % 8 + 5);
}

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 75

Zadanie #2.19
#include <iostream>
#include <ctime>
using namespace std;
//////////////////////////////////////////////////////
void troj(char znak, int n) {
for (int w = 1; w <= n; w++) {
for (int k = 1; k <= w; k++)
cout << znak;
cout << endl;
}
}
void troj_v2(char znak, int n) {
for (int w = 1; w <= n; w++) {
cout << string(n - w, ' ');
for (int k = 1; k <= w; k++) {
cout << znak;
}
cout << endl;
}
}

int main() {
setlocale(LC_ALL, ""); srand(time(0));
int r = rand() % 8 + 5;
troj('#', r);
troj_v2('#', r);
}

Zadanie #2.20
#include <iostream>
#include <ctime>
using namespace std;
//////////////////////////////////////////////////////
void trojkat(char znak, int n) {
for (int w = 1; w <= n; w++) {
cout << string(n - w, ' ');
cout << string(2 * w - 1, znak) << endl;
}
}
void diament(char znak, int n) {
trojkat(znak, n);
for (int w = n - 1; w >= 1; w--) {
cout << string(n - w, ' ');
cout << string(2 * w - 1, znak) << endl;
}
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
int r;
do { r = rand() % 15 + 7; } while (r % 2 == 0); // aż do uzyskania nieparzystej
trojkat('#', r);
diament('#', r);
}

26589ec988c76404b19a97e88c6609a5
2
76 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie #2.21
#include <iostream>
#include <ctime>
using namespace std;
//////////////////////////////////////////////////////
void kwadrat_malpa(char znak, char malpa, int n) {
// losuję pozycję znaku małpy [2;n-1][2;n-1]
int x = rand() % (n - 2) + 2;
int y = rand() % (n - 2) + 2;
for (int w = 1; w <= n; w++) { // wiersze
if (w == x) {
for (int k = 1; k <= n; k++) // kolumny
if (k == y) cout << malpa;
else cout << znak;
cout << endl;
}
else cout << string(n, znak) << endl; // cały wiersz
}
}
void kwadrat_pusty_malpa(char znak, char malpa, int n) {
int x = rand() % (n - 2) + 2;
int y = rand() % (n - 2) + 2;
for (int w = 1; w <= n; w++) { // wiersze
for (int k = 1; k <= n; k++) { // kolumny
if (k == 1 or k == n or w == 1 or w == n) cout << znak;
else if (w == x and k == y) cout << malpa;
else cout << ' ';
}
cout << endl;
}
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
kwadrat_malpa('#', '@', rand() % 8 + 5);
cout << endl;
kwadrat_pusty_malpa('#', '@', rand() % 8 + 5);
}

Zadanie #2.22
#include <iostream>
#include <ctime>
using namespace std;
//////////////////////////////////////////////////////
void trojkat(char znak, int n, int spacje_wiodace = 0) {
for (int w = 1; w <= n; w++) {
cout << string(n - w + spacje_wiodace, ' ');
cout << string(2 * w - 1, znak) << endl;
}
}

void choinka(char znak, int N) {


if (N < 3) { cout << "Popraw N.\n"; return; }
for (int piramida = 1; piramida <= N; piramida++) {
trojkat(znak, piramida + 2, N - piramida);

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 77

}
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
choinka('#', rand()%8+5);
}

Zadanie #2.23
Przykładowe rozwiązanie 1.
#include <iostream>
using namespace std;
//////////////////////////////////////////////////////
double potega(double x, unsigned int e) {
double wynik = 1;
for (int i = 1; i <= e; i++) {
wynik *= x;
}
return wynik;
}
double potega(double x, int e) {
if (e < 0) {
return 1 / potega(x, (unsigned)-e);
}
return potega(x, (unsigned)e);
}
int main() {
setlocale(LC_ALL, "");
cout << potega(2, 3) << endl; // 2 do potęgi trzeciej
cout << potega(2, 0) << endl; // 2 do 0
cout << potega(2, -3); // 2 do -3
}

Przykładowe rozwiązanie 2.
#include <iostream>
using namespace std;
//////////////////////////////////////////////////////
double potega(double x, unsigned int e) {
return e == 0 ? 1 : x * potega(x, e - 1);
}
double potega(double x, int e) {
if (e < 0)
return 1 / potega(x, -e);
else
return potega(x, (unsigned int)e);
}
int main() {
setlocale(LC_ALL, "");
cout << potega(2, 6) << endl;
cout << potega(2, 0) << endl;
cout << potega(2, -6) << " " << 1 / 64.0 << endl;
}

26589ec988c76404b19a97e88c6609a5
2
78 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie #2.24
#include <iostream>
using namespace std;
//////////////////////////////////////////////////////
typedef long long int L;
long long int zaokr(double x) {
double reszta = x - L(x); // >=.5
if (reszta >= 0.5) return L(x) + 1;
else if (reszta <= -0.5) return L(x) - 1;
return L(x);
}
int main() {
setlocale(LC_ALL, "");
cout << zaokr(231.24123) << endl;
cout << zaokr(-231.24123) << endl;
cout << zaokr(231.94123) << endl;
cout << zaokr(-231.94123) << endl;
}

Zadanie #2.25
#include <iostream>
using namespace std;
typedef long long int L;
//////////////////////////////////////////////////////
void podwajamPoKropce(double& x) { // referencja zmieni x, bez zwracania x
L calk = x;
x = calk + (x - calk) * 2;
}

int main() {
setlocale(LC_ALL, "");
double x = 1.34;
podwajamPoKropce(x);
cout << x << endl;
x = -1.99;
podwajamPoKropce(x);
cout << x << endl;
}

Zadanie #2.26
#include <iostream>
using namespace std;
//////////////////////////////////////////////////////
double wartb(double x) {
return (x < 0) ? -x : x;
}
int main() {
cout << wartb(-5) << " " << wartb(3.14) << endl;
}

Zadanie #2.27
(treść zadania nie wymaga podawania rozwiązania)

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 79

Zadanie #2.28
#include <iostream>
#include <vector>
using namespace std;
//////////////////////////////////////////////////////
double liniowa(double a, double b, double x) {
return a * x + b;
}
// lub np. tak
double liniowa2(vector<double>wsp, double x) {
return wsp[0] * x + wsp[1];
}
int main() {
setlocale(LC_ALL, "");
cout << liniowa(3, -4, 2.5) << endl; // 3x-4 => 3*2.5-4
cout << liniowa2({ 3,-4 }, 2.5); // przekazano wektor definiowany w locie jako {3,-4}
}

Zadanie #2.29
#include <iostream>
#include <ctime>
#include <vector>
using namespace std;
typedef long long int L;
//////////////////////////////////////////////////////
double liniowa(vector<double>wsp, double x) {
return wsp[0] * x + wsp[1];
}
void zliczaj(vector<vector<double>>& punkty) {
L na = 0, pod = 0, nad = 0;
for (auto& v : punkty) {
if (v[1] == liniowa({ 2,3 }, v[0])) // 2x+3 dla {x[0]}
na++;
else if (v[1] > liniowa({ 2,3 }, v[0]))
nad++;
else pod++;
}
cout << "Nad=" << nad << " Pod=" << pod << " Na=" << na << endl;
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
vector<vector<double>> punkty; // wektor zawiera wektory
punkty.resize(100); // 100 punktów
for (auto& v : punkty) { // losuj punkt {x,y}
v.push_back((rand() % 201 - 100) / 10.0); // x
v.push_back((rand() % 201 - 100) / 10.0); // y
}
zliczaj(punkty);
// uwaga: "na" będzie najczęściej równe 0, trudno strzelić
punkty.clear();
punkty.resize(0);
punkty = { {0,1},{1,10},{2,7} };
zliczaj(punkty);
}

26589ec988c76404b19a97e88c6609a5
2
80 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie #2.30
#include <iostream>
#include <ctime>
#include <vector>
using namespace std;
typedef long long int L;
//////////////////////////////////////////////////////
int main() {
setlocale(LC_ALL, ""); srand(time(0));
vector<int> v;
vector<int> ostatnie3;
int suma, pozycja = 0;
ostatnie3.resize(3, 0); // ustaw 3 elementy i przypisz im wartość 0
L ile = 0;
do {
suma = 0;
int losowa = rand() % 100 + 1;
ile++;
if (!v.size() or v.back() <= losowa) {
v.push_back(losowa);
}
cout << losowa << " ";
ostatnie3[pozycja] = losowa; // zapis ostatnich 3 elementów
pozycja = (++pozycja) % 3; // pozycja = 0,1,2,0,1,2,0,1,2,0,1,2
// obliczam sumę (muszą być minimum 3 elementy)
for (auto e : ostatnie3) {
if (e == 0) {
suma = 0;
break;
}
suma += e;
}
} while (!(suma >= 80 and suma <= 90));
cout << "\nWektor zapisanych liczb:\n";
for (auto e : v) cout << e << " ";
cout << endl;
cout << "Ile=" << ile << endl;
}

Zadanie #2.31
#include <iostream>
#include <ctime>
#include <vector>
#include <fstream>
using namespace std;
typedef long long int L;
//////////////////////////////////////////////////////
int main() {
setlocale(LC_ALL, ""); srand(time(0));
ofstream plik;
plik.open("liczby.txt");
int n;
do {
n = rand() % 1001;

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 81

if (n % 10 == 0) { // if (!n%10)
plik << n << endl;
}
} while (n != 1000);
plik.close();
}

Zadanie #2.32
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
//////////////////////////////////////////////////////
int main() {
setlocale(LC_ALL, "");
ifstream plik;
plik.open("liczby.txt"); // z zadania #2.31
int n;
vector<int> v;
while (!plik.eof()) {
// uwaga: gdy w pliku jest wiersz pusty, np. na końcu pliku, co
// jest częste w danych źródłowych do zadań maturalnych,
// można sprawdzić poprawność odczytu jak niżej
if (plik >> n) v.push_back(n);
}
plik.close();
for (auto e : v) cout << e << " ";
}

Zadanie #2.33
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
//////////////////////////////////////////////////////
int main() {
setlocale(LC_ALL, "");
// rozwiązanie nr 1, operator >>
ifstream plik;
plik.open("33_dane.txt"); // format wiersza 120;500
int n;
char znak;
vector<int> v;
while (!plik.eof()) {
if (plik >> n) // liczba do średnika
v.push_back(n);
plik >> znak; // ; średnik
if (plik >> n) // liczba po średniku
v.push_back(n);
}
plik.close();
for (auto e : v) cout << e << " ";
cout << endl << endl;

26589ec988c76404b19a97e88c6609a5
2
82 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

// rozwiązanie nr 2, getline, stoi


plik.open("33_dane.txt");
string tn;
vector<int> v2;
int i = 1;
// czytam do napotkania błędu lub końca pliku
while (!plik.eof()) {
if (i % 2 == 1) getline(plik, tn, ';'); // do średnika
else getline(plik, tn); // czytaj do końca wiersza lub pliku
i = (i + 1) % 2; // na zmianę, czy czytam do ';', czy do końca wiersza/pliku
// jeśli nie ma cyfr w przeczytanym wierszu, omijam
if (tn.find_first_of("0123456789") == string::npos) continue;
n = stoi(tn); // zamień ze string na int (system dziesiętny)
v2.push_back(n);
}
plik.close();
for (auto e : v2) cout << e << " ";
}
// uwaga: można np. tak: stoi (napis,nullptr,2); // binarny jako podstawa
// uwaga: można np. tak: stoi (napis,nullptr,16); // szesnastkowy jako podstawa

Zadanie #2.34
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
//////////////////////////////////////////////////////
int main() {
setlocale(LC_ALL, "");
ifstream plik;
plik.open("34_dane.txt");
/*
1;231;3423;dowolnie długi napis
321;345;67;inny długi napis
-351;211;0;potwornie długi napis, inny niż wszystkie
*/
string napis, pomoc;
vector<L> v;
int i = 1;
while (!plik.eof() ) {
if (i % 4 != 0) {
getline(plik, pomoc, ';');
if (pomoc.find_first_of("0123456789")!=string::npos)
v.push_back(stoll(pomoc)); // stoll: string -> long long int
}
else {
getline(plik, pomoc);
napis += pomoc;
}
i = (i + 1) % 4;
}
plik.close();
for (auto e : v) cout << e << " ";
cout << endl << napis << endl;
}

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 83

Zadanie #2.35
Rozwiązanie 1. Wykorzystuję sprawdzanie błędów: try-catch.
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
//////////////////////////////////////////////////////
bool czyDouble(string& txt) { // sprawdzam, czy txt da się zamienić na double
try {
stod(txt);
}
catch (exception e) {
return false;
}
return true;
}

int main() {
setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "C"); // przeczyta -31.21 jako double
ifstream plik;
plik.open("35_dane.txt");
string wiersz, fragment;
vector<string> napisy;
/*
1;231;3423;dowolnie długi napis;345456;inny napis
napis;321;345;67;inny długi napis;8893;krótki tekst;123123;1212;12;tekst
-31.21;napis kosmiczny;0.001;-1.0;2
*/
while (!plik.eof() and getline(plik >> std::ws, wiersz)) { // cały wiersz
// analiza wiersza od średnika do średnika
int pozp = 0, pozk = -1;
while ((pozk = wiersz.find(";", ++pozk)) != string::npos) {
fragment = wiersz.substr(pozp, pozk - pozp);
pozp = pozk + 1;
if (czyDouble(fragment)) {
cout << stod(fragment) << endl;
}
else {
napisy.push_back("#" + fragment + "#");
}
}
fragment = wiersz.substr(pozp);
if (czyDouble(fragment)) {
cout << fragment << endl;
}
else {
napisy.push_back("#" + fragment + "#");
}
}
for (auto e : napisy) cout << e << endl;
plik.close();
}

26589ec988c76404b19a97e88c6609a5
2
84 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Rozwiązanie 2. Wykorzystuję tylko podstawowe rzeczy.


#include <iostream>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
//////////////////////////////////////////////////////
bool czyDouble(string& txt) { // sprawdzam, czy txt da się zamienić na double
if (txt == "") return false; // pusty napis to nie liczba
if (txt.find_first_of("0123456789") == string::npos) return false; // nie ma cyfr
string pomoc = txt;
int poz = 0;
while ((poz = pomoc.find_first_of("0123456789")) != string::npos) {
pomoc.erase(pomoc.begin() + poz); // usuwam cyfry, powinno zostać nic lub . albo -.
}
if (pomoc == "." or pomoc == "-." or pomoc == "") return true;
return false;
}

int main() {
setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "C"); // "12.3" -> 12.3
ifstream plik;
plik.open("35_dane.txt");
string wiersz, fragment;
vector<string> napisy;
/*
1;231;3423;dowolnie długi napis;345456;inny napis
napis;321;345;67;inny długi napis;8893;krótki tekst;123123;1212;12;tekst
-31.21;napis kosmiczny;0.001;-1.0;2
*/
while (!plik.eof() and getline(plik >> std::ws, wiersz)) {
// analiza wiersza od średnika do średnika
int pozp = 0, pozk = -1;
while ((pozk = wiersz.find(";", ++pozk)) != string::npos) {
fragment = wiersz.substr(pozp, pozk - pozp);
pozp = pozk + 1;
if (czyDouble(fragment)) {
cout << stod(fragment) << endl;
}
else {
napisy.push_back("#" + fragment + "#");
}
}
fragment = wiersz.substr(pozp);
if (czyDouble(fragment)) {
cout << fragment << endl;
}
else {
napisy.push_back("#" + fragment + "#");
}
}
for (auto e : napisy) cout << e << endl;
plik.close();
}

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 85

Rozwiązanie 3. Wykorzystuję stringstream (napis jest źródłem, jakby był


plikiem, z którego mogę czytać).
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <sstream> // stringstream
using namespace std;
typedef long long int L;
//////////////////////////////////////////////////////
int main() {
setlocale(LC_ALL, "");
ifstream plik;
plik.open("35_dane.txt");
string wiersz, fragment;
vector<string> napisy;
/*
1;231;3423;dowolnie długi napis;345456;inny napis
napis;321;345;67;inny długi napis;8893;krótki tekst;123123;1212;12;tekst
-31.21;napis kosmiczny;0.001;-1.0;2
*/
while (!plik.eof() and getline(plik >> std::ws, wiersz)) {
stringstream ss{ wiersz += ";" };
double n;
string txt;
while (getline(ss, txt, ';').good()) {
stringstream spom{ txt };
if (spom >> n) {
cout << n << endl;
}
else {
napisy.push_back("#" + txt + "#");
}
}
}
for (auto e : napisy) cout << e << endl;
plik.close();
}

Zadanie #2.36
#include <iostream>
#include <ctime>
#include <vector>
#include <cmath>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
//////////////////////////////////////////////////////
struct A {
int a;
string b;
float c;
char d;
};

26589ec988c76404b19a97e88c6609a5
2
86 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

void dopisz(A& element, string plik, bool dopisz = true) { // dopisz na koniec pliku
ofstream p;
if (dopisz) p.open(plik, ios_base::app); // ios_base::app sprawia, że można dopisać
// do pliku
else p.open(plik); // otwieram, ale nie żeby dodać, ale by utworzyć całkiem nowy plik
p << element.a << ";" << element.b << ";" << element.c << ";" << element.d <<
´endl; // a;b;c;d w linii pliku
p.close();
// uwaga: jeżeli A.b będzie napisem zawierającym znak średnika, pomysł na zapis zostanie zepsuty;
// zakładam jednak, dla uproszczenia, że napis nie będzie zawierać średnika
}
void dopisz(vector<A>& v, string plik) { // zapisz cały wektor (przeciążenie funkcji)
ofstream p;
p.open(plik, ios_base::app); // ios_base::app sprawia, że można dopisać do pliku
for (auto& e : v)
p << e.a << ";" << e.b << ";" << e.c << ";" << e.d << endl; // a;b;c;d w linii pliku
p.close();
}
vector<A> pobierz(string plik) { // załaduj dane, zakładamy poprawność pliku
ifstream p;
p.open(plik);
vector<A> v;
while (!p.eof()) {
A element;
string pomoc;
// jeśli jest pusty wiersz na końcu, to nic nie czytam
if (!(getline(p, pomoc, ';')).good()) break;
element.a = stoi(pomoc); // int
getline(p, pomoc, ';');
element.b = pomoc; // string
getline(p, pomoc, ';');
element.c = stof(pomoc); // float
p >> element.d; // char
v.push_back(element);
}
p.close();
return v;
}

int main() {
setlocale(LC_ALL, ""); srand(time(0));
// przykłady użycia funkcji (powstanie plik zad36.txt)
A a({ 1,"kaszanka",4.5,'a' }); // nowy element typu A, dane zostaną wstawione
// do a.a, a.b, a.c, a.d
dopisz(a, "zad36.txt", false); // utwórz plik od nowa, dopisz linię
a.a++;
a.b += " jest fajna";
a.c *= 2;
a.d = 'b';
dopisz(a, "zad36.txt"); // dopisz linię

vector<A> v = { {1,"2",3.5,'4'},{2,"3",4.5,'5'} };
dopisz(v, "zad36.txt"); // dopisz cały wektor elementów

vector<A> laduj = pobierz("zad36.txt"); // pobiera z pliku elementy, daje wektor


cout << "Załadowane dane z pliku: \n";

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 87

for (auto& e : laduj) {


cout << e.a << " " << e.b << " " << e.c << " " << e.d << endl;
}
}

Zadanie #2.37
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
//////////////////////////////////////////////////////
// metoda znak po znaku (porównuję pierwszy z ostatnim, drugi z przedostatnim itd.)
bool palindrom(string txt) {
for (int i = 0, k = txt.size() - 1; i <= k; i++, k--) {
if (txt[i] != txt[k]) return false; // jeśli nie są równe, nie może być palindrom
}
return true;
}
// metoda wykorzystująca wbudowane funkcje biblioteki standardowej: assign,
// assign tworzy nowy napis na bazie innego; utworzę nowy
// na podstawie starego, ale traktowanego "od tyłu"
// rbegin() początek, ale od tyłu, rend() koniec od początku :)
// (reverse begin, reverse end)
bool palindrom2(string txt) {
string nowy;
nowy.assign(txt.rbegin(), txt.rend());
return (nowy == txt); // true lub false
}

int main() {
setlocale(LC_ALL, "");
cout << palindrom("krowa") << endl; // nie
cout << palindrom("kajak") << endl; // tak
cout << palindrom("x") << endl; // tak

cout << palindrom2("krowa") << endl; // nie


cout << palindrom2("kajak") << endl; // tak
cout << palindrom2("x") << endl; // tak
}

Zadanie #2.38
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
UL ileAwB(string A, string B) {
UL i = 0;
L poz = -1;

26589ec988c76404b19a97e88c6609a5
2
88 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

while ((poz = B.find(A, ++poz)) != string::npos) i++;


return i;
}
int main() {
setlocale(LC_ALL, "");
string A = "kro";
string B = "Makro nie jest krotochwilą, jednak krowom nic do tego.\n"; // 3x kro
cout << ileAwB(A, B);
}

Zadanie #2.39
Przykładowe rozwiązanie 1.
#include <iostream>
#include <ctime>
#include <vector>
#include <cmath>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
// wersja zakładająca poprawność napisu
L stol_(string x) {
L xi = 0;
L mnoznik = 1;
bool minus = false;
if (x[0] == '-') {
minus = true;
x = x.substr(1); // nowy napis bez pierwszego znaku '-'
}
while (x.size()) {
// znaki '0', '1' itd. mają wartość liczbową 48, 49 itd. Wykorzystam to.
xi += (x.back() - 48) * mnoznik; // * 1, * 10, * 100...
mnoznik *= 10;
x.pop_back();
}
return (minus) ? -xi : xi;
}
// wersja z poprawnym napisem, ale inny sposób
L stol2_(string x) {
L xi = 0;
vector<L> liczby{ 0,1,2,3,4,5,6,7,8,9 };
string znaki = "0123456789";
L mnoznik = 1;
bool minus = false;
if (x[0] == '-') {
minus = true;
x = x.substr(1);
}
while (x.size()) {
L liczba = liczby[znaki.find(x.back())]; // działa tylko dla poprawnego napisu!
xi += liczba * mnoznik;
mnoznik *= 10;

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 89

x.pop_back();
}
return (minus) ? -xi : xi;
}

// wersja z testem, czy zmiana jest możliwa;


// wykonam tylko funkcję sprawdzającą, czy da się zamienić (można jej użyć
// w funkcjach wyżej utworzonych)
bool czyLiczba(string x) {
if (x[0] == '-') x = x.substr(1); // minus może być na początku, ale nie jest potrzebny
// do analizy
if (x.find_first_not_of("0123456789") == string::npos) return true;
return false;

}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
cout << stol_("3120") << endl;
cout << stol2_("3120") << endl;
cout << stol_("-215") << endl;
cout << stol2_("-215") << endl;

cout << czyLiczba("123") << endl; // tak


cout << czyLiczba("12-3") << endl; // nie (to nie działania, tylko konwersja)
cout << czyLiczba("-123") << endl; // tak
cout << czyLiczba("123x123") << endl; // nie
}

Przykładowe rozwiązanie 2.
#include <iostream>
#include <string>

using namespace std;

long long stol_(const string& str) {


long long result = 0;
bool negative = false;
if (str[0] == '-')
negative = true;

for (int i = negative ? 1 : 0; i < str.size(); ++i) {


result *= 10;
result += str[i] - '0';
}

return negative ? -result : result;


}

int main() {
cout << stol_("3120") << endl;
cout << stol_("3120") << endl;
cout << stol_("-215") << endl;
cout << stol_("-215") << endl;
}

26589ec988c76404b19a97e88c6609a5
2
90 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie #2.40
#include <iostream>
#include <ctime>
#include <vector>
#include <cmath>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
string L2string(L x) {
string napis = "";
string minus = "";
if (x < 0) { x *= -1; minus = "-"; }
while (x != 0) {
napis = char(x % 10 + 48) + napis;
x /= 10;
}
napis += (napis == "") ? "0" : "";
return minus + napis;
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
cout << L2string(1443) << endl;
cout << L2string(-1443) << endl;
cout << L2string(0) << endl;
cout << L2string(-0) << endl;
cout << L2string(+0) << endl;
}

Zadanie #2.41
Przykładowe rozwiązanie 1.
#include <iostream>
#include <ctime>
#include <vector>
#include <cmath>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
UL binary_string2dec(string binary) {
UL dec = 0;
UL potega = binary.size() - 1;
for (auto bit : binary) { // bit to '1' albo '0'
dec += (bit - 48) * pow(2, potega--);
}
return dec;
}
string dec2binary_string(UL dec) {
string binary = "";

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 91

while (dec != 0) {
binary = char((dec % 2) + 48) + binary;
dec /= 2;
}
return binary;
}
// a teraz rozwiązania bardziej uniwersalne niż wcześniejsze, dla dowolnego systemu
// o podstawie 2, 3, ..., 16
UL str2dec(string s, UL podstawa) {
// zwróć uwagę, że pozycja cyfry to jej wartość w systemie dziesiętnym,
// np. 3 ma pozycję 3, a f pozycję 15
string cyfrySystemu = "0123456789abcdef";
UL dec = 0;
UL potega = s.size() - 1;
for (auto cyfra : s) {
UL vpoz = cyfrySystemu.find(cyfra); // pozycja vpoz jest równocześnie wartością
// dziesiętną cyfry
dec += vpoz * pow(podstawa, potega--);
}
return dec;
}

string dec2str(UL dec, UL podstawa) {


string cyfrySystemu = "0123456789abcdef";
string s;
while (dec != 0) {
s = cyfrySystemu[(dec % podstawa)] + s;
dec /= podstawa;
}
return s;
}

int main() {
setlocale(LC_ALL, ""); srand(time(0));
cout << binary_string2dec("0") << endl; // 0
cout << binary_string2dec("10001") << endl; // 17
cout << binary_string2dec("11111") << endl; // 31
cout << binary_string2dec("0001001101") << endl; // 77

cout << dec2binary_string(0) << endl;


cout << dec2binary_string(17) << endl;
cout << dec2binary_string(31) << endl;
cout << dec2binary_string(77) << endl;

// uniwersalna zmiana uwzględniająca podstawę systemu


cout << str2dec("10001", 2) << endl; // binarne 17
cout << str2dec("61", 8) << endl; // ósemkowe 49
cout << str2dec("ff", 16) << endl; // szesnastkowe 255
cout << str2dec("120", 3) << endl; // trójkowe 15

cout << dec2str(17, 2) << endl; // pokaż 17 w binarnym


cout << dec2str(49, 8) << endl; // pokaż 49 w ósemkowym
cout << dec2str(255, 16) << endl; // pokaż 255 w szesnastkowym
cout << dec2str(15, 3) << endl; // pokaż 15 w trójkowym
}

26589ec988c76404b19a97e88c6609a5
2
92 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Przykładowe rozwiązanie 2.
#include <iostream>
#include <string>
#include <cmath>

int get_decimal_value(char c) {
return isdigit(c) ? c - '0' : c - 'A' + 10;
}

int get_character_from_value(int value) {


return value >= 0 && value <= 9 ? value + '0' : value + 'A' - 10;
}

long long convert_to_decimal(const std::string& value, int base) {


long long result = 0;
for (int i = 0; i < value.size(); ++i)
result += get_decimal_value(value[i]) * pow(base, value.size() - i - 1);

return result;
}

std::string convert_from_decimal(long long value, int base) {


if (base == 10)
return std::to_string(value);

std::string result;
while (value > 0) {
result += get_character_from_value(value % base);
value /= base;
}

result.assign(result.rbegin(), result.rend());
return result;
}

std::string convert(const std::string& value, int from_base, int to_base) {


if (from_base == to_base)
return value;

return convert_from_decimal(convert_to_decimal(value, from_base), to_base);


}

int main() {
std::string value;
int from_base, to_base;
std::cin >> value >> from_base >> to_base;

std::cout << convert(value, from_base, to_base) << std::endl;


}

Zadanie #2.42
#include <iostream>
#include <ctime>
#include <vector>
#include <fstream>

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 93

#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
vector<string> szukajLiczb(string T) {
vector<string> wynik;
string cyfry = "0123456789";
bool nowy_fragment = false;
for (char znak : T) {
bool cyfra = (cyfry.find(znak) != string::npos) ? true : false;
if (nowy_fragment and cyfra) wynik.back() += znak; // istnieje podciąg cyfr
else if (cyfra and !nowy_fragment) { // nowy podciąg cyfr
wynik.push_back("");
wynik.back() += znak;
nowy_fragment = true;
}
else { // nie cyfra
nowy_fragment = false;
}
}
return wynik;
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
string txt = "abd65asd7891das1d";
for (auto e : szukajLiczb(txt)) {
cout << e << endl;
}
}

Zadanie #2.43
#include <iostream>
#include <ctime>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
// funkcja szuka jednego, najdłuższego (pierwszego) podciągu
string szukajNajdluzszyNiemalejacy(string T) {
string cyfry = "0123456789";
L poczatek = -1, dlugosc = 0;
L maxdl = -1, maxpocz = -1;
for (UL i = 0; i <= T.size() - 1; i++) {
char znak = T[i];
bool cyfra = (cyfry.find(znak) == string::npos) ? false : true;
if (cyfra and dlugosc == 0) { // nowy podciąg jednocyfrowy
poczatek = i;
dlugosc = 1;
}
else if (cyfra and dlugosc > 0) { // trwa podciąg
if (T[i - 1] - 48 <= T[i] - 48) { // zachowana niemalejąca kolejność

26589ec988c76404b19a97e88c6609a5
2
94 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

dlugosc++;
if (maxdl < dlugosc) {
maxdl = dlugosc;
maxpocz = poczatek;
}
}
else {
poczatek = i;
dlugosc = 1;
}
}
else { // nie cyfra
dlugosc = 0;
poczatek = i;
}
}
return T.substr(maxpocz, maxdl);
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
string txt = "dfgnqeiut98tna1223v0w3r1233334asdsh";
cout << szukajNajdluzszyNiemalejacy(txt);
}

Zadanie #2.44
#include <iostream>
#include <ctime>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
const int SIZE = 15;
string trzy_generator() {
string znaki = "abcdef";
string wynik = "";
int ile = 3;
while (ile--)
wynik += znaki[rand() % znaki.size()];
return wynik;
}
bool odpowiedni(string s) {
vector<string> szukane = { "abc","bcd","cde","def" };
for (auto e : szukane)
if (s == e) return true;
return false;
}
bool test(vector<vector<string>>& W, int w, int k) {
if (odpowiedni(W[w][k]) and
odpowiedni(W[w + 1][k]) and
odpowiedni(W[w][k + 1]) and
odpowiedni(W[w + 1][k + 1])) return true;
return false;

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 95

}
void zadanie44(vector<vector<string>>& W) {
for (int w = 0; w < SIZE - 1; w++) {
for (int k = 0; k < SIZE - 1; k++) {
if (test(W, w, k)) {
cout << "Znaleziono dla w= " << w << " k=" << k << endl;
cout << W[w][k] << " ";
cout << W[w][k + 1] << "\n";
cout << W[w + 1][k] << " ";
cout << W[w + 1][k + 1] << "\n";
}
}
}
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
cout << "ZAWARTOŚĆ WYGENEROWANA LOSOWO: \n\n";
vector<vector<string>> W;
W.resize(SIZE, {});
for (auto& e : W) {
for (int i = 1; i <= SIZE; i++) {
e.push_back(trzy_generator());
cout << e.back();
if (i < SIZE) cout << ",";
}
cout << endl;
}
cout << endl;
cout << string(60, '#') << endl;
// dane stałe (dla sprawdzenia, czy wszystko działa)
W.clear(); // usuwam losowy zbiór i ustalam niżej sztywny dla testu

W = {
{"ebb","cbe","beb","bdd","fcf","eed","bdd","cfd","cec","fee","ebf","cba","bff","acf","aee"},
{"ddc","eee","cac","cca","daa","cce","cbd","cad","afa","ced","fcc","cdd","cca","cfc","afd"},
{"dad","afb","bae","ffd","dba","efd","bac","dda","cca","beb","add","fba","bbe","fbd","fab"},
{"dfd","bcd","ecc","bfb","efb","cbb","dcf","afb","aaf","fcd","dee","dba","dca","baa","cee"},
{"fab","fba","efc","dad","caf","bad","dba","afa","fbd","cbf","ccb","fda","cff","eac","bde"},
{"efa","eac","ada","edd","fcd","fae","dff","cab","eab","dcc","dbd","bac","bfe","efe","eec"},
{"ccc","bcc","fbf","afa","abc","cde","fec","faa","bfe","cac","acd","dad","eca","bbe","afd"},
{"eba","abb","cfd","ccb","abc","def","ffc","ead","cdd","baf","bef","fbd","afb","bae","bfe"},
{"fcf","acf","bdc","baa","cdf","adf","edb","cab","ebe","faf","dee","ddc","ebd","aad","eaa"},
{"eee","aec","cbc","edd","bcf","fbb","acc","abf","dbc","cab","bcd","bbc","ebc","fee","fcd"},
{"cdc","cef","bfe","def","ede","ade","ade","dea","cbc","bce","bce","cad","fbb","dbb","ccb"},
{"feb","dba","afe","efa","add","aeb","bfc","bee","aca","acc","ebe","ead","ffa","baa","eca"},
{"eea","fcd","bdf","baf","fdb","fdb","ddd","bce","eed","edf","efc","fca","dff","def","abc"},
{"ebc","fcd","fad","cde","daf","eee","dfd","aaf","cff","dcc","aff","cfb","afc","bcd","cde"},
{"cca","afe","daf","ecf","cfd","cdb","bfe","aea","ffe","dae","bae","fce","ade","bbc","fcd"}
};

zadanie44(W);
}

26589ec988c76404b19a97e88c6609a5
2
96 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie #2.45
#include <iostream>
#include <ctime>
#include <vector>
#include <cmath>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
// korzystam z funkcji utworzonej we wcześniejszych zadaniach
bool palindrom(string txt);

int main() {
setlocale(LC_ALL, ""); srand(time(0));
ifstream dane;
dane.open("45_dane.txt");
string wiersz;
vector<string> kolumny;
kolumny.resize(20, "");
// wszystkie wiersze to palindromy
cout << "Wiersze:\n";
while (getline(dane >> std::ws, wiersz)) {
if (palindrom(wiersz)) cout << "(" << wiersz << ")" << endl;
for (int i = 0; i < wiersz.size(); i++) {
kolumny[i] += wiersz[i];
}
}
cout << "\nKolumny:\n";
for (auto kolumna : kolumny) {
if (palindrom(kolumna)) cout << "(" << kolumna << ")" << endl;
}
dane.close();
}

////////////////////////
// funkcje wykorzystane z wcześniejszych zadań
bool palindrom(string txt) {
string nowy;
nowy.assign(txt.rbegin(), txt.rend());
return (nowy == txt); // true lub false
}

Zadanie #2.46
#include <iostream>
#include <ctime>
#include <vector>
#include <cmath>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 97

void zapisz(string txt) {


ofstream zapis;
zapis.open("kod.txt");
for (auto znak : txt) {
zapis << (znak + 0); // kod znaku
zapis << ';';
}
zapis.close();
}
string odczytaj() {
ifstream odczyt;
string odczytane = "", temp;
odczyt.open("kod.txt");
while (getline(odczyt, temp, ';').good()) {
odczytane += char(stoi(temp));
}
odczyt.close();
return odczytane;
}
// uwaga: w przypadku polskich znaków można zauważyć, że znak jest traktowany jak
// dwa znaki (po zamianie na kod są ujemne). Sprawdź, jak wyżej utworzona funkcja zapisze 'ś' czy 'ć'.

// można też użyć typu wstring zamiast string, wofstream zamiast ofstream, wchar_t zamiast
// char, wcin zamiast cin, wcout zamiast cout
void zapisz(wstring txt) { // przeciążona
wofstream zapis;
zapis.open("kod2.txt");
for (auto znak : txt) {
zapis << (znak + 0); // kod znaku
zapis << ';';
}
zapis.close();
}
wstring odczytaj2() {
ifstream odczyt;
wstring odczytane = L""s; // wstring ma literały L"treść"s;
string temp;
odczyt.open("kod2.txt");
while (getline(odczyt, temp, ';').good()) {
odczytane += wchar_t(stoi(temp));
}
odczyt.close();
return odczytane;
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
string txt;
getline(cin, txt);
zapisz(txt);

cout << "Odczyt:" << odczytaj() << endl;

wstring txt2;
getline(wcin, txt2);
zapisz(txt2);

wcout << "Odczyt:" << odczytaj2() << endl;


}

26589ec988c76404b19a97e88c6609a5
2
98 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie #2.47
#include <iostream>
#include <ctime>
#include <vector>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
UL wystapienia(vector<L>& v, L x) {
UL ile = 0;
for (auto e : v) if (e == x) ile++;
return ile;
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
vector<L> v{ 1,2,3,4,5,6,7,6,5,4,3,4,5,6,7 };
cout << wystapienia(v, 7);
}

Zadanie #2.48
#include <iostream>
#include <ctime>
#include <vector>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
bool takie_same(vector<L> v, int pocz, int kon) {
for (int i = pocz; i <= kon - 1; i++)
if (v[i] != v[i + 1]) return false;
return true;
}
void zad48(vector<L> v) {
for (int dlugosc = v.size(); dlugosc >= 2; dlugosc--) { // długości
for (int i = 0; i + dlugosc - 1 < v.size(); i++) {
if (takie_same(v, i, i + dlugosc - 1)) {
for (int s = i; s <= i + dlugosc - 1; s++) cout << v[s] << " ";
cout << "od pozycji " << i << " do pozycji " << i + dlugosc - 1 << endl;
}
}
}
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
zad48({ 3,2,1,1,4,2,4,4,4 });
zad48({ 1,1,2,3,2,2,3,3,1,1,5,3,2,6,7,4,3,3,3,3,3,1,6,9 });
}

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 99

Zadanie #2.49
#include <iostream>
#include <vector>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
bool jest(vector<int> v, int x) {
for (auto e : v) if (x == e) return true;
return false;
}
vector<int> czesc_wspolna_bez_powtorzen(vector<int> A, vector<int> B) {
vector<int> cw;
for (auto e : A) {
for (auto f : B) {
if (e == f and !jest(cw, e)) {
cw.push_back(e);
break;
}
}
}
return cw;
}

int main() {
setlocale(LC_ALL, "");
for (auto e : czesc_wspolna_bez_powtorzen({ 6,1,2,3,4,5,6,6,6,7,7,7 },
´{ 4,5,6,7,7 }))
cout << e << " ";
}

Zadanie #2.50
#include <iostream>
#include <ctime>
#include <vector>
#include <string>
using namespace std;
//////////////////////////////////////////////////////
string zad50(string txt, int usun = 2) {
bool del;
cout << "przed: " << txt << endl;
do {
del = false;
for (int i = 1; i < txt.size(); i++) {
if (txt[i] == txt[i - 1]) {
txt.erase(i - 1, usun);
del = true;
break;
}
}
} while (del);
return txt;
}
int main() {

26589ec988c76404b19a97e88c6609a5
2
100 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

setlocale(LC_ALL, ""); srand(time(0));


cout << zad50("skfuu12m2111flx") << endl;
cout << zad50("npq985yy5vnprr8ettemzp9yamppp98tywnmtvb9q8y4nqp948tydlfaaafld") <<
´endl;
cout << zad50("1abbbbaaccdccdeeddccaeffabcdefa121122") << endl;

cout << zad50("skfuu12m2111flx", 1) << endl;


cout << zad50("npq985yy5vnprr8ettemzp9yamppp98tywnmtvb9q8y4nqp948tydlfaaafld", 1) <<
´endl;
cout << zad50("1abbbbaaccdccdeeddccaeffabcdefa121122", 1) << endl;
}

Zadanie #2.51
#include <iostream>
#include <ctime>
#include <vector>
#include <cmath>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
bool czyPierwsza(UL i) {
if (i <= 1) return false;
for (UL dzielnik = 2; dzielnik <= sqrt(i); dzielnik++)
if (i % dzielnik == 0) return false;
return true;
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
cout << czyPierwsza(10) << " ";
cout << czyPierwsza(13) << " ";
}

Zadanie #2.52
#include <iostream>
#include <vector>
using namespace std;
//////////////////////////////////////////////////////
vector<double> przeplatanka(vector<double> a, vector<double> b) {
vector<double> c;
auto apoz = a.begin();
auto bpoz = b.begin();
do {
if (apoz != a.end()) {
c.push_back(*apoz);
apoz++;
}
if (bpoz != b.end()) {
c.push_back(*bpoz);
bpoz++;
}
} while (apoz != a.end() or bpoz != b.end());
return c;
}

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 101

int main() {
setlocale(LC_ALL, "");
for (auto e : przeplatanka({ 1,2,3,4,5,6,7,8,9,10 }, { 20,30,40,50,60 }))
cout << e << " ";
}

Zadanie #2.53
#include <iostream>
#include <ctime>
#include <vector>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
bool poprawny(string wyr) {
cout << "\nBadam= " << wyr << endl;
string litery = "qazwsxedcrfvtgbyhnujmikolp";
string operacje = "+-*/^%"; // do tego nawiasy () oraz =
string cyfry = "0123456789";
// algorytm oprę na redukcji części poprawnych
// do innych poprawnych, ale krótszych, np.:
// 1+1 zredukuję do 1, a+b do a, (1) do 1 itd.
/* Uwaga! Algorytm wydaje mi się skuteczny. Nie znalazłem jak
do tej pory kontrprzykładu, który wykazuje jego złe działanie. */
////////////////////////////////////////////////////////
// zamieniam każdą cyfrę na 1
for (auto& e : wyr) if (cyfry.find(e) != string::npos) e = '1';
// redukuję wszystkie ciągi cyfr, np. 1111 na 1
size_t poz;
while ((poz = wyr.find("11")) != string::npos)
wyr.replace(poz, 2, "1");
// zamieniam litery na "a"
for (auto& e : wyr) if (litery.find(e) != string::npos) e = 'a';
// zamieniam "1" na "a"
for (auto& e : wyr) if (e == '1') e = 'a';
// zmieniam działania na jedno działanie '-' (nie ruszam =)
for (auto& e : wyr)
if (e != '-' and operacje.find(e) != string::npos) e = '-';
// redukuję do oporu "(a)" oraz "(-a)" do "a" oraz redukuję "a-a" do "a"
string temp;
do {
temp = wyr;
while ((poz = wyr.find("(a)")) != string::npos)
wyr.replace(poz, 3, "a");
while ((poz = wyr.find("(-a)")) != string::npos)
wyr.replace(poz, 4, "a");
while ((poz = wyr.find("a-a")) != string::npos)
wyr.replace(poz, 3, "a");
} while (wyr != temp);
// redukuję a=a do a
while ((poz = wyr.find("a=a")) != string::npos)
wyr.replace(poz, 3, "a");
// wyr musi być "a" lub "-a", jeżeli jest poprawne
cout << "Po redukcji " << wyr << endl;
return (wyr == "a" or wyr == "-a" or wyr == "");

26589ec988c76404b19a97e88c6609a5
2
102 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

int main() {
setlocale(LC_ALL, ""); srand(time(0));
// 1 (true): poprawny, 0 (false): niepoprawny
cout << poprawny("-3*x+781/a=2+(1*a)-3/b%10+(1)-(-a)/100") << endl;
cout << poprawny("a+b-c(") << endl;
cout << poprawny("a+b-c=d*(-1123)") << endl;
cout << poprawny("") << endl; // pusty napis zawierający wyrażenie uznajmy za poprawny
cout << poprawny("-a-a-xx") << endl;
cout << poprawny("--10") << endl; // uznajemy za niepoprawny, nie namnażamy minusów
cout << poprawny("-(-10)") << endl; // ale taki jest już poprawny przez wzgląd na nawias
cout << poprawny("1+(=a=a)") << endl;
cout << poprawny("10^((a+b+43587*4)+(-10/a*b)+(u+i+g%10)/(-7-1/10))") << endl;
cout << poprawny("a/(a=b)") << endl;
cout << poprawny("))a+b((") << endl;
cout << poprawny("a==b") << endl;
}

Zadanie #2.54

Wersja prosta
imiona.txt
Bogdan
Magda
Barbara
Tobiasz
Odorian
Kapustan
Śliwianna
Waldemaria
Wanna
Brytfanka
Pomiar
Bodziomił
Gryczan
Karaczanna
Melisa
Amebon
Mikser

nazwiska.txt
Kowalski
Nowak
Abecadłowski
Brutusowicz
Cebulak

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 103

Dobrodziej
Emulatorski
Fajczyński
Gromosławski
Hamburgerowicz
Iwański
Jabłoński

Kod:
#include <iostream>
#include <ctime>
#include <vector>
#include <cmath>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
string generate() {
ifstream imiona, nazwiska;
imiona.open("imiona.txt");
nazwiska.open("nazwiska.txt");
vector<string> vimiona, vnazwiska;
string temp;
while (getline(imiona, temp).good())
vimiona.push_back(temp);
while (getline(nazwiska, temp).good())
vnazwiska.push_back(temp);
imiona.close();
nazwiska.close();
return string(vimiona[rand() % vimiona.size()]
+ " " + vnazwiska[rand() % vnazwiska.size()]);
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
cout << generate() << endl;
cout << generate() << endl;
cout << generate() << endl;
cout << generate() << endl;
}

Wersja z uwzględnieniem płci


imiona.txt, m,k,mk (męskie lub żeńskie imię)
Bogdan;m
Magda;k
Barbara;k
Tobiasz;m
Odorian;m
Kapustan;m

26589ec988c76404b19a97e88c6609a5
2
104 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Śliwianna;k
Waldemaria;k
Wanna;k
Brytfanka;k
Pomiar;m
Bodziomił;m
Gryczan;m
Karaczanna;k
Melisa;k
Amebon;mk
Mikser;m

nazwiska.txt
Kowalski;Kowalska
Nowak;Nowak
Abecadłowski;Abecadłowska
Brutusowicz;Brutusowicz
Cebulak;Cebulak
Dobrodziej;Dobrodziej
Emulatorski;Emulatorska
Fajczyński;Fajczyńska
Gromosławski;Gromosławska
Hamburgerowicz;Hamburgerowicz
Iwański;Iwańska
Jabłoński;Jabłońska

Kod:
#include <iostream>
#include <ctime>
#include <vector>
#include <cmath>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
string generate() {
ifstream imiona, nazwiska;
imiona.open("imiona.txt");
nazwiska.open("nazwiska.txt");
vector<string> vimiona, vnazwiska;
string temp;
while (getline(imiona, temp).good())
vimiona.push_back(temp);
while (getline(nazwiska, temp).good()) {
vnazwiska.push_back(temp);
}

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 105

imiona.close();
nazwiska.close();

string itemp = vimiona[rand() % vimiona.size()];


string ntemp = vnazwiska[rand() % vnazwiska.size()];

auto poz = itemp.find(";");


string imie = itemp.substr(0, poz); // do średnika
string plec = itemp.substr(poz + 1); // za średnikiem
string nazwisko;

poz = ntemp.find(";");
nazwisko = (plec == "k") ? ntemp.substr(poz + 1) : ntemp.substr(0, poz);

return imie + " " + nazwisko;


}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
cout << generate() << endl;
cout << generate() << endl;
cout << generate() << endl;
cout << generate() << endl;
}

Zadanie #2.55
#include <iostream>
#include <ctime>
#include <vector>
#include <cmath>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
string sylaba_generator(string srodek = "eo",
string prefix = "srjcg",
string postfix = "wrtpsdfghjklzcbnm") {
string sylaba = "";
return ((sylaba += prefix[rand() % prefix.size()])
+= srodek[rand() % srodek.size()])
+= postfix[rand() % postfix.size()];
}
string generuj() {
string imie("");
int sylab = rand() % 4 + 1; // 1-4
if (sylab & 1) { // nieparzysta liczba sylab
vector<string> srodki{ "e","o" };
int poz_srodek = rand() % 2;
for (int i = 1; i <= sylab; i++) {
imie += sylaba_generator(srodki[poz_srodek]);
poz_srodek = (poz_srodek + 1) % 2;
}
}
else { // parzysta liczba sylab

26589ec988c76404b19a97e88c6609a5
2
106 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

string srodek = (rand() % 2) ? "e" : "o";


for (int i = 1; i <= sylab; i++) imie += sylaba_generator(srodek);
}
return imie;
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
int i = 15;
while (i--)
cout << generuj() << endl;
}

Zadanie #2.56
#include <iostream>
#include <ctime>
#include <vector>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
string cyfra_na_string(int c) {
char znak = c + 48; // 0 -> '0'
string wynik;
wynik += znak; // '0' -> "0"
return wynik;
}
string zad56() {
vector<int> cyfry = { 0,1,2,3,4,5,6,7,8,9 };
vector<int> wylosowane;
UL suma = 0;
do {
if (wylosowane.size() < 9) {
// losuję, ale bez pierwszej pozycji czyli od {1, 2, 3, ..., 9}, pomijam 0
int wylosowana_pozycja = rand() % (cyfry.size() - 1) + 1;
// uwaga na parzystą na trzeciej pozycji
if (wylosowane.size() == 2 and cyfry[wylosowana_pozycja] % 2 == 0) continue;
wylosowane.push_back(cyfry[wylosowana_pozycja]);
suma += wylosowane.back();
// teraz zapewniam sobie, że w następnym losowaniu nie zostanie wylosowana ta sama cyfra
cyfry[wylosowana_pozycja] = cyfry[0];
cyfry[0] = wylosowane.back();
}
else { // ostatnia cyfra nie ma znaczenia, może się powtarzać
wylosowane.push_back(cyfry[rand() % cyfry.size()]);
suma += wylosowane.back();
}
if (wylosowane.size() == 10 and suma < 30) {
cout << "Losuję ponownie, za mała suma! (" << suma << ")\n[";
for (auto e : wylosowane) cout << e << " ";
cout << "]\n";
wylosowane.clear(); // od nowa, zła suma
suma = 0;
cyfry = { 0,1,2,3,4,5,6,7,8,9 }; // reset
}

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 107

} while (wylosowane.size() < 10);

string liczba = "";


for (auto e : wylosowane)
liczba += cyfra_na_string(e);
return liczba;
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
cout << "START\n";
for (int i = 100; i--;) cout << zad56() << endl;
}

Zadanie #2.57
#include <iostream>
#include <ctime>
#include <vector>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
struct Punkt {
int x;
int y;
};
bool na_linii(Punkt a, Punkt b, Punkt c) {
// (y−yA)(xB−xA)−(yB−yA)(x−xA)=0 // wzór funkcji dla dwóch punktów. Punkt c spełnia poniższą
// równość, gdy leży na prostej utworzonej z punktów a i b.
return ((c.y - a.y) * (b.x - a.x) - (b.y - a.y) * (c.x - a.x) == 0);
}
bool zad57(Punkt a, Punkt b, Punkt c) {
// Testujemy, czy punkty a i b to linia, a punkt c leży na tej linii. Kombinacje a, c, b oraz b, c, a nie
// są konieczne, zwracają jednak uwagę na fakt, że prostą mogą tworzyć inne dwa punkty.
return (na_linii(a, b, c) or na_linii(a, c, b) or na_linii(b, c, a));
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
cout << zad57 ({ 0,0 }, { 10,10 }, { 5,5 }); // wszystkie leżą na prostej x=y (1)
cout << zad57 ({ 0,0 }, { 10,10 }, { 1,-1 }); // nie leżą (0)
cout << zad57 ({ 0,0 }, { 10,10 }, { -1,-1 }); // leżą (1)
cout << zad57 ({ 0,0 }, { 0,5 }, { 2,0 }); // nie leżą (0)
cout << zad57 ({ 0,0 }, { 0,5 }, { 0,2 }); // leżą (1) (uwaga: te punkty tworzą pionową
// linię, a podany wzór redukuje się do x=0)
}

Zadanie #2.58
#include <iostream>
#include <ctime>
#include <vector>
#include <string>
using namespace std;
//////////////////////////////////////////////////////
struct Punkt {
double x;
double y;

26589ec988c76404b19a97e88c6609a5
2
108 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

};
string liniowa(Punkt a, Punkt b) {
// (y−yA)(xB−xA)−((yB−yA)(x−xA))=0 // wzór funkcji dla dwóch punktów
if (b.x - a.x == 0) return "problem z dzieleniem przez zero\n";
/* po przekształceniu mamy coś takiego:
f(x) = x(yb-ya)/(xb-xa) + ya-xa(yb-ya)/(xb-xa);
*/
string wynik;
wynik = "f(x) = ";
wynik += to_string((b.y - a.y) / (b.x - a.x));
wynik += " * x ";
double bwsp = -a.x * (b.y - a.y) / (b.x - a.x) + a.y;
if (bwsp >= 0) wynik += "+";
wynik += to_string(bwsp);
return wynik;
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
cout << liniowa({ 0,0 }, { 5,5 }) << endl; // f(x) = x
cout << liniowa({ -2,0 }, { 2,-1 }) << endl; // f(x) = -1/4 * x - 1/2
cout << liniowa({ 0,0 }, { 2,4 }) << endl; // f(x) = 2 * x;
cout << liniowa({ 0,0 }, { 0,4 }) << endl; // pionowa linia to w zasadzie nie jest funkcja
}

Zadanie #2.59
#include <iostream>
#include <ctime>
#include <vector>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
vector<int> dni{ 31,28,31,30,31,30,31,31,30,31,30,31 };
vector<int> dnip{ 31,29,31,30,31,30,31,31,30,31,30,31 };
vector<string> mies{ "styczeń","luty","marzec","kwiecień","maj","czerwiec",
"lipiec","sierpień","wrzesień","październik","listopad","grudzień" };
vector<string> dzien{ "poniedziałek","wtorek","środa","czwartek","piątek",
´"sobota","niedziela" };
int STARTOWY = 5; // indeks soboty w vector<string> dzien;
// zasada - kiedy rok jest przestępny?
// gdy rok jest podzielny przez 4, ale nie przez 100, lub gdy jest podzielny przez 400
bool przestepny(UL rok) {
return ((rok % 4 == 0 and rok % 100 != 0) or (rok % 400 == 0));
}
// ile dni w roku?
int ile_dni_ma_rok(UL rok) {
if (przestepny(rok)) return 366;
return 365;
}
// tylko rok 2022
string dzien_roku_2022(int N) {
if (N < 1 or N>365) return "funkcja działa w zakresie N<1;365>";
string d = "";
int m = 0; // początkowy miesiąc to styczeń mies[m]

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 109

int nrd = (STARTOWY + N - 1) % 7; // co to za dzień dzien[nrd]?


for (auto ile : dni) {
if (N <= ile) {
d += to_string(N) + " " + mies[m] + " 2022 " + "(" + dzien[nrd] + ")";
break;
}
else {
N -= ile;
m++;
}
}
return d;
}
// dowolny rok
string dzien_roku(UL rok, int N) {
if (rok < 2022) return "funkcja działa tylko od roku 2022 włącznie";
vector<int> pom;
pom = (przestepny(rok)) ? dnip : dni;
if (N < 1) return "funkcja działa w zakresie N<1;365/366>";
if (przestepny(rok) and N > 366)
return "rok " + to_string(rok) +
", funkcja działa w zakresie N<1;366>";
if (!przestepny(rok) and N > 365)
return "rok " + to_string(rok) +
", funkcja działa w zakresie N<1;365>";

string d = "";
// dla roku 2022 wykorzystam funkcję dzien_roku_2022
if (rok == 2022) return dzien_roku_2022(N);
// dla dalszych lat > 2022 obliczę, ile dni minęło od 2022-01-01 do końca
// roku poprzedzającego rok przekazany do funkcji
UL ile_dni = 0;
for (UL r = rok - 1; r >= 2022; r--) {
ile_dni += ile_dni_ma_rok(r);
}
// dzień zwracany przez funkcję
int nrd = (STARTOWY + ile_dni + N - 1) % 7;

auto dn = (przestepny(rok)) ? dnip : dni;


int m = 0;
for (auto ile : dn) {
if (N <= ile) {
d += to_string(N) + " " + mies[m] + " " + to_string(rok) + " " + "
´(" + dzien[nrd] + ")";
break;
}
else {
N -= ile;
m++;
}
}
return d;
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
cout << dzien_roku_2022(1) << endl;
cout << dzien_roku_2022(3) << endl;

26589ec988c76404b19a97e88c6609a5
2
110 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

cout << dzien_roku_2022(11) << endl;


cout << dzien_roku_2022(54) << endl;
cout << dzien_roku_2022(250) << endl;
cout << dzien_roku_2022(365) << endl;
cout << dzien_roku_2022(366) << endl;
cout << "\n\n\n";
cout << dzien_roku(2022, 1) << endl;
cout << dzien_roku(2022, 365) << endl;
cout << dzien_roku(2023, 1) << endl;
cout << dzien_roku(2023, 365) << endl;
cout << dzien_roku(2024, 1) << endl;
cout << dzien_roku(2024, 31) << endl;
cout << dzien_roku(2024, 366) << endl;
}

Zadanie #2.60
#include <iostream>
#include <ctime>
#include <vector>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
string format2(L v) {
if (v <= 9) return "0" + to_string(v);
return to_string(v);
}
string roznica_czasu(string t1, string t2) {
L t2_sek = stoi(t2.substr(0, 2)) * 3600 + stoi(t2.substr(3, 2)) * 60 +
´stoi(t2.substr(6, 2));
L t1_sek = stoi(t1.substr(0, 2)) * 3600 + stoi(t1.substr(3, 2)) * 60 +
´stoi(t1.substr(6, 2));
L t = abs(t2_sek - t1_sek);
L tg = t / 3600;
L tm = (t - tg * 3600) / 60;
L ts = t - tg * 3600 - tm * 60;
return format2(tg) + ":" + format2(tm) + ":" + format2(ts);
}

int main() {
setlocale(LC_ALL, ""); srand(time(0));
cout << roznica_czasu("09:05:08", "13:10:33") << endl;
cout << roznica_czasu("13:10:33", "09:05:08") << endl;
cout << roznica_czasu("09:35:08", "13:10:33") << endl;
cout << roznica_czasu("24:00:00", "00:00:01") << endl;
cout << roznica_czasu("24:00:00", "00:00:00") << endl; // a może 0? :)
}

Zadanie #2.61
#include <iostream>
#include <ctime>
#include <vector>
#include <cmath>
#include <fstream>

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 111

#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
pair<wstring, wstring> alfabetycznie(wstring t1, wstring t2) {
wstring alfabet = L"aąbcćdeęfghijklłmnńoóprsśtuwxyźż";
// napisy nie mogą być puste
if (t1 == L"" or t2 == L"") {
cout << "napisy nie mogą być puste!\n";
return make_pair(t1, t2);
}
// test czy napis ma właściwe litery (dozwolone)
if (t1.find_first_not_of(alfabet) != wstring::npos) {
wcout << t1 << L": ";
cout << "napis zawiera niedozwolone znaki\n";
return make_pair(t1, t2);
}
if (t2.find_first_not_of(alfabet) != wstring::npos) {
wcout << t2 << L": ";
cout << "napis zawiera niedozwolone znaki\n";
return make_pair(t1, t2);
}
// testy na kolejność alfabetyczną (size_t to typ zwracany przez .size()) (to taki dodatni int)
for (size_t a = 0, b = 0; a < t1.size() and b < t2.size(); ) {
if (alfabet.find(t1[a]) < alfabet.find(t2[b])) {
return make_pair(t1, t2);
}
else if (alfabet.find(t1[a]) > alfabet.find(t2[b])) {
return make_pair(t2, t1);
}
else {
a++;
b++;
}
}
// wszystkie litery się zgadzają, tylko długość pozostaje do sprawdzenia
if (t1.size() <= t2.size()) return make_pair(t1, t2); // t1 krótsze, więc wcześniej
return make_pair(t2, t1); // t2 krótsze
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
// wyłapane błędy
alfabetycznie(L"", L"transformator");
alfabetycznie(L"ko tek", L"pie sek");
cout << endl;

auto p = alfabetycznie(L"wibracje", L"wiadro");


wcout << p.first << " " << p.second << endl;
p = alfabetycznie(L"narracja", L"aberracja");
wcout << p.first << " " << p.second << endl;
p = alfabetycznie(L"dżdżownica", L"dżdżownica");
wcout << p.first << " " << p.second << endl;
p = alfabetycznie(L"łośkowo", L"łoś");
wcout << p.first << " " << p.second << endl;
p = alfabetycznie(L"pałąk", L"pasek");
wcout << p.first << " " << p.second << endl;
}

26589ec988c76404b19a97e88c6609a5
2
112 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie #2.62
#include <iostream>
#include <ctime>
#include <vector>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
UL odwracanie_cyfr(UL n) {
vector<UL> cyfry;
while (n != 0) {
cyfry.push_back(n % 10);
n /= 10;
}
UL r = 0, poz = 1;
for (int i = 0; i < cyfry.size(); i++) {
r += cyfry[i] * pow(10, cyfry.size() - 1 - i);
}
return r;
}

int main() {
setlocale(LC_ALL, ""); srand(time(0));

cout << odwracanie_cyfr(37645) << endl;


cout << odwracanie_cyfr(1233219) << endl;
cout << odwracanie_cyfr(333) << endl;
cout << odwracanie_cyfr(23400) << endl;
cout << odwracanie_cyfr(3410) << endl;

Zadanie #2.63
#include <iostream>
#include <ctime>
#include <vector>
#include <cmath>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////

int main() {
setlocale(LC_ALL, ""); srand(time(0));
// dane z pliku włożymy sobie do vector<vector<L>>
vector<vector<L>> dane;
int kolumna = 0;
ifstream d;
// odczyt
d.open("63_dane.txt");
while (!d.eof()) {

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 113

L temp;
d >> temp;
if (!d.fail()) {
if (kolumna == 0) dane.push_back({});
dane.back().push_back(temp);
}
kolumna = (kolumna + 1) % 6;
}
d.close();
// prezentacja danych z pliku
for (auto e : dane) {
for (auto f : e) {
cout << f << " ";
}
cout << "\n";
}
// jaka jest średnia liczb w pierwszej i ostatniej kolumnie?
double srp = 0, sro = 0;
int np = 0, no = 0;
for (int i = 0; i < dane.size(); i++) {
for (int j = 0; j < dane[i].size(); j++) {
if (j == 0) {
srp += dane[i][j];
np++;
}
else if (j == dane[i].size() - 1) {
sro += dane[i][j];
no++;
}
}
}
cout << "średnia w pierwszej kolumnie = " << srp / np << endl;
cout << "średnia w ostatniej kolumnie = " << sro / no << endl;
// które kolumny (numer) posiadają największą liczbę?
L maks = dane[0][0];
for (int i = 0; i < dane.size(); i++) {
for (int j = 0; j < dane[i].size(); j++) {
if (maks < dane[i][j]) maks = dane[i][j]; // znajdź maksa
}
}
vector<int> kolumny;
for (int i = 0; i < dane.size(); i++) {
for (int j = 0; j < dane[i].size(); j++) {
if (maks == dane[i][j]) kolumny.push_back(j + 1);
}
}
cout << "Największa liczba = " << maks << " znajduje się w kolumnach: ";
for (auto e : kolumny) cout << e << " ";
cout << endl;
// ile jest wierszy, w których nie występuje liczba podzielna przez 10?
int ile_wierszy = 0;
for (int i = 0; i < dane.size(); i++) {
bool nie_wystepuje = true;
for (int j = 0; j < dane[i].size(); j++) {
if (dane[i][j] % 10 == 0) {
nie_wystepuje = false;

26589ec988c76404b19a97e88c6609a5
2
114 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

break;
}
}
if (nie_wystepuje) {
ile_wierszy++;
cout << "wiersz nr:" << i + 1 << ":brak podz. przez 10 (";
for (auto e : dane[i]) cout << e << " ";
cout << ")\n";
}
}
cout << "W " << ile_wierszy << " wierszach nie występuje liczba podzielna przez 10.\n";
// ile jest wierszy, w których pierwsze trzy liczby zachowują niemalejący porządek?
ile_wierszy = 0;
for (int i = 0; i < dane.size(); i++) {
if (dane[i][0] <= dane[i][1] and dane[i][1] <= dane[i][2]) {
cout << "niemalejący porządek: " << dane[i][0] << " " <<
dane[i][1] << " " << dane[i][2] << endl;
ile_wierszy++;
}
}
cout << "W " << ile_wierszy << " wierszach 3 pierwsze liczby mają niemalejący
´porządek.\n";
// ile jest wierszy, w których są dokładnie 3 liczby z zakresu <85;100>?
ile_wierszy = 0;
for (int i = 0; i < dane.size(); i++) {
int trzy = 0;
for (int j = 0; j < dane[i].size(); j++) {
if (dane[i][j] >= 85 and dane[i][j] <= 100) trzy++;
}
if (trzy == 3) {
ile_wierszy++;
cout << "W wierszu " << i + 1 << " dokładnie 3 liczby są <85;100>\n";
}
}
cout << "W " << ile_wierszy << " wierszach dokładnie 3 liczby są między
´<85;100>\n";
}

Zadanie #2.64
#include <iostream>
#include <ctime>
#include <vector>
#include <cmath>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
int main() {
setlocale(LC_ALL, ""); srand(time(0));
string osoby = "ABCDE"; // pozycja osoby to jej numer, np. "A" to 0, "B" to 1 itd.
vector<vector<pair<int, int>>> dane; // pair<dzien, pomiar>
dane.resize(osoby.size()); // każda osoba ma swój wektor z danymi,
// "A" ma dane[0], "B" dane[1] itd.

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 115

ifstream p;
p.open("64_dane.txt");
while (!p.eof()) {
string osoba;
int pomiar;
int dzien;
p >> osoba;
p >> pomiar;
p >> dzien;
if (p.fail()) break;
auto o = osoby.find(osoba);
dane[o].push_back(make_pair(dzien, pomiar));
}
p.close();
// prezentacja posegregowanych pomiarów
for (int i = 0; i < dane.size(); i++) {
cout << "Osoba " << osoby[i] << ":\n";
for (auto wpis : dane[i]) {
cout << "\t dzien=" << wpis.first << " pomiar=" << wpis.second << "\n";
}
}
// odpowiedzi:
// która osoba dokonywała najwięcej pomiarów?
int maks_pomiarow = 0;
int nr_osoby = 0;
for (int i = 0; i < dane.size(); i++) {
cout << osoby[i] << " = " << dane[i].size() << endl;
if (maks_pomiarow < dane[i].size()) {
maks_pomiarow = dane[i].size();
nr_osoby = i;
}
}
cout << "Osoba " << osoby[nr_osoby]
<< " dokonała najwięcej pomiarów. " << maks_pomiarow << "\n";
// policz sumę oraz średnią wszystkich pomiarów dla każdej z osób
for (int i = 0; i < dane.size(); i++) {
cout << "Osoba " << osoby[i] << " ";
L suma = 0;
for (auto e : dane[i]) suma += e.second;
cout << "suma = " << suma << " średnia = " << suma * 1.0 / dane[i].size() <<
´endl;
}
// zakładając, że pierwszy dzień pomiarów to wtorek, drugi środa itd.,
// policz sumę pomiarów ze wszystkich wtorków
L suma = 0;
for (int d = 1; d <= 100; d += 7) { // wtorki
for (int i = 0; i < dane.size(); i++) {
for (pair<int, int> wpis : dane[i]) {
if (wpis.first == d) {
suma += wpis.second;
break;
}
}
}
}
cout << "Suma pomiarów z wtorków to = " << suma << endl;
}

26589ec988c76404b19a97e88c6609a5
2
116 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

Zadanie #2.65
#include <iostream>
#include <ctime>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
/*
W zadaniu wykorzystamy proponowane wcześniej rozwiązania, takie jak str2dec().
*/
// liczba (string) z dowolnego systemu na dziesiętny
UL str2dec(string s, UL podstawa) {
// zwróć uwagę, że pozycja cyfry to jej wartość w systemie dziesiętnym,
// np. 3 ma pozycję 3, a f pozycję 15
string cyfrySystemu = "0123456789abcdef";
UL dec = 0;
UL potega = s.size() - 1;
for (auto cyfra : s) {
UL vpoz = cyfrySystemu.find(cyfra);
dec += vpoz * pow(podstawa, potega--);
}
return dec;
}

int main() {
setlocale(LC_ALL, ""); srand(time(0));
string dane =
"xfac8*1101011*1110100xc8x32xff*1010o7311o1212xabcd*101*1*0x1o0xd*11111";
UL podstawa = 0; // 2, 8, 16
string temp = "";
for (int poz = 0; poz < dane.size(); poz++) {
if (dane[poz] == 'x' or dane[poz] == 'o' or dane[poz] == '*') {
if (temp != "") {
cout << temp << " (" << podstawa << ")= " << str2dec(temp, podstawa) <<
´endl;
}
temp = "";
}
else {
temp += dane[poz];
}
if (dane[poz] == 'x') {
podstawa = 16;
}
else if (dane[poz] == 'o') {
podstawa = 8;
}
else if (dane[poz] == '*') {
podstawa = 2;
}
}
if (temp != "") {
cout << temp << " = " << str2dec(temp, podstawa) << endl;
}
}

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 117

Zadanie #2.66
#include <iostream>
#include <ctime>
#include <vector>
#include <cmath>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
vector<vector<L>> mnozenie_macierzy(L a, vector<vector<L>> m) {
vector<vector<L>> wynik;
wynik.resize(m.size());
for (int wiersz = 0; wiersz < m.size(); wiersz++) {
for (L x : m[wiersz]) {
wynik[wiersz].push_back(a * x);
}
}
return wynik;
}
vector<vector<L>> mnozenie_macierzy(vector<vector<L>>m1, vector<vector<L>> m2) {
if (m1[0].size() != m2.size()) {
cout << "Mnożenie nie może się udać.\n" <<
"Liczba kolumn w macierzy A musi być\n" <<
"równa liczbie wierszy w macierzy B.\n";
return { {} };
}
vector<vector<L>> wynik;
wynik.resize(m1.size());
for (int wiersz = 0; wiersz < m1.size(); wiersz++) {
int kolumn_m2 = m2[0].size();
for (int k = 0; k < kolumn_m2; k++) {
L suma = 0;
int poz = 0;
for (poz = 0; poz < m1[wiersz].size(); poz++) {
suma += m1[wiersz][poz] * m2[poz][k];
}
wynik[wiersz].push_back(suma);
}
}
return wynik;
}
void pokaz_macierz(vector<vector<L>>& m) {
for (auto w : m) {
for (auto e : w) {
cout << e << " ";
}
cout << endl;
}
cout << "\n----------------------------\n";
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));

26589ec988c76404b19a97e88c6609a5
2
118 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

// rozwiązanie
vector<vector<L>> m1 = { {2,4,9,4},{3,0,2,2},{7,3,1,8},{1,2,3,4},{9,6,3,1} };
vector<vector<L>> w = mnozenie_macierzy(7, m1);
pokaz_macierz(w);

// rozwiązanie
vector<vector<L>> m2 = { {5,9,-1},{7,4,0},{-3, 5, 2} };
vector<vector<L>> m3 = { {4,8,2},{11,-2, 0},{3, 5, 3} };
w = mnozenie_macierzy(m2, m3);
pokaz_macierz(w);

// test dla różnych rozmiarów


vector<vector<L>> m4 = { {5,9,-1},{7,4,0},{-3, 5, 2} };
vector<vector<L>> m5 = { {4},{0},{3},{5} };
w = mnozenie_macierzy(m4, m5);
pokaz_macierz(w);

// test dla różnych rozmiarów


vector<vector<L>> m6 = { {5,9,-1},{7,4,0},{-3, 5, 2} };
vector<vector<L>> m7 = { {4},{0},{3} };
w = mnozenie_macierzy(m6, m7);
pokaz_macierz(w);

// test dla różnych rozmiarów


vector<vector<L>> m8 = { {-3, 5, 2} };
vector<vector<L>> m9 = { {4,2,2,2,2,3,1,2,1},{0,2,3,4,6,6,4,2,1},
´{3,0,0,0,0,-1,-1,-1,-1} };
w = mnozenie_macierzy(m8, m9);
pokaz_macierz(w);
}

Zadanie #2.67
#include <iostream>
#include <ctime>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
bool palindrom(string txt) {
for (int s = 0, k = txt.size() - 1; s <= k; s++, k--) {
if (txt[s] != txt[k]) return false;
}
return true;
}
vector<string> palindromy(string baza) {
vector<string> r;
string alfabet = "qazwsxedcrfvtgbyhnujmikolp";
for (int dl = 2; dl <= baza.size() - 1; dl++) {
for (int poz = 0; poz + dl <= baza.size() - 1; poz++) {
string temp = baza.substr(poz, dl);
if (palindrom(temp)) r.push_back(temp);
}
}

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 119

return r;
}

int main() {
setlocale(LC_ALL, ""); srand(time(0));
for (auto e : palindromy("kajakrobbokonstruktorbabajaganogimajakpajakapiraci
´krzyczaaghrrrrhga"))
cout << e << endl;
}

Zadanie #2.68
#include <iostream>
#include <ctime>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
bool podzielna(L N, L p) {
while (N >= p) N -= p;
if (N == 0) return true;
return false;
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
cout << podzielna(100, 10) << endl; // tak
cout << podzielna(100, 12) << endl; // nie
cout << podzielna(153, 51) << endl; // tak
cout << podzielna(1, 10) << endl; // nie
cout << podzielna(10, 1) << endl; // tak
cout << podzielna(7, 7) << endl; // tak
}

Zadanie #2.69
#include <iostream>
#include <ctime>
#include <vector>
#include <fstream>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
vector<int> oddo(int zakres_od, int zakres_do) {
vector<int> w;
int krok = 1;
if (zakres_od > zakres_do) krok = -1;
for (int i = zakres_od; i != zakres_do; i += krok)
w.push_back(i);
w.push_back(zakres_do);
return w;
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
// prezentacja funkcji oddo
for (auto e : oddo(-5, 5)) cout << e << " ";

26589ec988c76404b19a97e88c6609a5
2
120 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

cout << endl;


for (auto e : oddo(3, 12)) cout << e << " ";
cout << endl;
for (auto e : oddo(-3, -12)) cout << e << " ";
cout << endl;
// cd. zadania
vector<vector<int>> dziesiec;
cout << "\n-------------------\n";
for (int i = 1; i <= 10; i++) {
int rand_od = rand() % 21 - 10;
int rand_do = rand() % 21 - 10;
dziesiec.push_back(oddo(rand_od, rand_do));
cout << "Z" << i << ": ";
for (auto e : dziesiec.back()) cout << e << " ";
cout << endl;
}
// zliczanie, ile razy wystąpiła jaka liczba
vector<int> zlicz;
zlicz.resize(21, 0); // pozycje [0...20] traktowane jako [-10, ..., 0, ..., 10]
for (auto e : dziesiec) {
for (auto liczba : e) {
zlicz[liczba + 10]++;
}
}
for (int i = 0; i <= zlicz.size() - 1; i++) {
if (zlicz[i] >= 5) cout << i - 10 << " wystąpiło w " << zlicz[i] <<
´" zbiorach.\n";
}
}

Zadanie #2.70
#include <iostream>
#include <ctime>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
string sgen(int minL, int maxL, string dict) {
string r ="";
int dl = rand() % (maxL - minL + 1) + minL; // długość napisu
for (int i = 1; i <= dl; i++)
r += dict[rand() % dict.size()];
return r;
}
// pokazuje powtarzające się słowa (pierwszy pomysł)
bool pokaz(vector<string> v) {
vector<string> powt;
for (int i = 0; i <= v.size() - 2; i++) {
bool znaleziony = false;
for (int test = i + 1; test <= v.size() - 1; test++) {
if (v[i] == v[test]) {
if (!znaleziony) powt.push_back(v[i]);

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 121

znaleziony = true;
}
}
}
if (powt.size()) {
for (auto e : powt) cout << e << " ";
return true;
}
return false;
}
// inna wersja (pomysł z pewną optymalizacją)
// polega na porównywaniu tylko tych napisów, które mają tę samą długość,
// najpierw jednak trzeba wektor rozbić na fragmenty napisów o odpowiednich
// długościach (nie będę porównywać pięcioznakowych napisów z siedmioznakowymi).
// Ten pomysł skraca czas wykonania. Mimo tego, że korzysta się w nim z wcześniejszej funkcji
// pokaz(), to jednak ogranicza się ilość porównań.
void pokaz2(vector<string>& v) {
vector<vector<string>> segregacja;
segregacja.resize(6); // [0]=5dl, [1]=6dl ... [5]=10dl
for (auto e : v) {
segregacja[e.size() - 5].push_back(e);
}
for (int s = 0; s <= segregacja.size() - 1; s++) { // kolejne wektory
pokaz(segregacja[s]);
}
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));

// generowanie
vector<string> v;
v.resize(25000);
for (auto& e : v) e = sgen(5, 10, "qazwsxedcrfvtgby");

// rozwiązanie 1.
auto pocz = time(0);
pokaz(v);
auto kon = time(0);
cout << "\nprzybliżony czas w sekundach:" << kon - pocz << endl;

// rozwiązanie 2.
pocz = time(0);
pokaz2(v);
kon = time(0);
cout << "\nprzybliżony czas w sekundach:" << kon - pocz << endl;
}

Zadanie #2.71
#include <iostream>
#include <ctime>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;

26589ec988c76404b19a97e88c6609a5
2
122 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

//////////////////////////////////////////////////////
struct Opad {
UL sekunda;
UL sztuk;
};
struct Drzewo {
UL sztuk = 3000;
UL czas_opadania = 0;
vector<Opad> opadanie;
};
// cechy opadania
Opad opad() {
UL sek = rand() % 10 + 1;
int szansa = rand() % 100 + 1;
UL sztuk;
if (szansa <= 50) {
sztuk = rand() % 4; // 0-3
}
else if (szansa <= 80) {
sztuk = rand() % 4 + 4; // 4-7
}
else {
sztuk = rand() % 3 + 8; // 8-10
}
return Opad{ sek,sztuk };
}
// tworzenie historii opadania
void zdarzenie(Drzewo& d) {
d.opadanie.push_back(opad());
if (d.sztuk < d.opadanie.back().sztuk) {
d.opadanie.back().sztuk = d.sztuk;
}
d.sztuk -= d.opadanie.back().sztuk; // tyle liści z drzewa spadło
d.czas_opadania += d.opadanie.back().sekunda; // tyle trwa łącznie proces opadania
}
void symulacja_opadania(Drzewo& d) {
while (d.sztuk > 0) {
zdarzenie(d);
cout << "Po " << d.czas_opadania << " sekundach pozostało " << d.sztuk <<
´" liści.\n";
}
}
int main() {
setlocale(LC_ALL, ""); srand(time(0));
Drzewo D;
symulacja_opadania(D);

// spis wydarzeń (przywróć poniższy komentarz, jeżeli chcesz zobaczyć kolejne wydarzenia)
// for (Opad o: D.opadanie) cout << o.sekunda << "sek " << o.sztuk << "szt\n";

// odpowiedzi do symulacji
// po jakim czasie (podaj w godzinach, minutach i sekundach) drzewo straciło wszystkie liście? [1,]
cout << "OPADANIE: " << D.czas_opadania << "sek, czyli:\n";
UL g;
UL m;
UL s;
g = D.czas_opadania / 3600;

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 123

cout << g << "godz ";


m = (D.czas_opadania - (g * 3600)) / 60;
cout << m << "min ";
s = (D.czas_opadania - g * 3600 - m * 60);
cout << s << "sek\n";

// jaki procent opadania stanowiły opady zawierające od 0 do 3 liści? [1,]


UL maks = D.opadanie.size(); // wszystkie opady
UL ile0_3 = 0;
for (Opad& o : D.opadanie) if (o.sztuk <= 3) ile0_3++;
// jeżeli symulacja jest prawidłowa,
// procent powinien oscylować w okolicach 0.5, czyli 50%
cout << "Procent opadania liści w ilościach od 0 do 3 wynosi "
<< ile0_3 * 1.0 / maks * 100.0 << "%" << endl;

// ile razy w krokach symulacji nie spadł ani jeden liść? (losowało się 0 liści) [1,]
// powinna to być 1/4 z około 50%, czyli w okolicach 12,5% (uruchom symulację kilka razy)
UL ile0 = 0;
for (Opad& o : D.opadanie) if (o.sztuk == 0) ile0++;
cout << "Procent opadania liści w ilościach równych 0 wynosi "
<< ile0 * 1.0 / maks * 100.0 << "%" << endl;

// przyjmij, że ponumerowaliśmy kolejne kroki symulacji (zdarzenie opadania);


// znajdź 10 kolejnych (następujących po sobie) kroków, dla których
// spadło najmniej liści; podaj numery tych kroków

int zakres = 10;


int najmniej = 10 * 10; // w 10 krokach nie mogło spaść więcej
UL start = 0;
for (UL poz = 0; poz <= D.opadanie.size() - zakres; poz++) {
int spadlo = 0;
for (int i = poz; i < poz + zakres; i++) spadlo += D.opadanie[i].sztuk;
if (najmniej > spadlo) {
najmniej = spadlo;
start = poz;
}
}
cout << "Najmniej liści w 10 krokach, bo " << najmniej << " spadło od kroku "
<< start << " do kroku " << start + zakres - 1 << endl;
}

Zadanie #2.72
#include <iostream>
#include <ctime>
#include <string>
#include <bitset>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
bool bitowy_palindrom(UL b, UL p = 8) {
bitset<8> lewo8 = 0b10000000;
bitset<8> prawo8 = 0b00000001;
bitset<16> lewo16 = 0b1000000000000000;
bitset<16> prawo16 = 0b0000000000000001;
bitset<8> b8 = b;

26589ec988c76404b19a97e88c6609a5
2
124 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

bitset<16> b16 = b;
for (int przesuniecie = 1; przesuniecie <= p / 2 - 1; przesuniecie++) {
if (p == 8) {
if ((b8 & lewo8) == 0 xor (b8 & prawo8) == 0) return false;
lewo8 = lewo8 >> 1;
prawo8 = prawo8 << 1;
}
else {
if ((b16 & lewo16) == 0 xor (b16 & prawo16) == 0) return false;
lewo16 = lewo16 >> 1;
prawo16 = prawo16 << 1;
}
}
return true;
}

int main() {
setlocale(LC_ALL, ""); srand(time(0));
cout << bitowy_palindrom(0b11100111) << endl; // tak
cout << bitowy_palindrom(0b01100110) << endl; // tak
cout << bitowy_palindrom(0b10011001) << endl; // tak
cout << bitowy_palindrom(0b10011111) << endl; // nie
cout << bitowy_palindrom(0b10111001) << endl; // nie
cout << bitowy_palindrom(0b01111111) << endl; // nie

cout << bitowy_palindrom(0b1110011111100111, 16) << endl; // tak


cout << bitowy_palindrom(0b0110011001100110, 16) << endl; // tak
cout << bitowy_palindrom(0b1001100110011001, 16) << endl; // tak
cout << bitowy_palindrom(0b1001111110111111, 16) << endl; // nie
cout << bitowy_palindrom(0b1011100110011111, 16) << endl; // nie
cout << bitowy_palindrom(0b0111111110011111, 16) << endl; // nie
}

Zadanie #2.73
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
void bez0(string& b) { // usuwam zbędne 0 z początku
while (b[0] == '0') b.erase(0, 1);
}
// obsługuje przekazywanie "dalej" podczas dodawania
// 0+0 to 0, 1+0 oraz 0+1 to 1, 1+1 to 0 i 1 dalej,
// 1+1+1 to 1 i 1 dalej
string dalej(int& i,int dodaj) {
i += dodaj;
if (i == 0) {
return "0";
}
else if (i == 1) {
i = 0;
return "1";

26589ec988c76404b19a97e88c6609a5
2
ROZWIĄZANIA 125

}
else if (i == 2) {
i = 1;
return "0";
}
else if (i == 3) {
i = 1;
return "1";
}
else {
cout << "Jakiś dramat, źle dodajemy?\n";
return "X";
}
}
string dodaj(string b1, string b2) {
// czyszczę początkowe zera
bez0(b1); bez0(b2);
cout << b1 << endl << "+ " << b2 << endl;
string suma="";
int d = 0;
int s = 0;
L wlewo = 0;
L poz1 = b1.size() - 1;
L poz2 = b2.size() - 1;
while (poz1 >= 0 and poz2 >= 0) {
suma = dalej(d, b1[poz1] - 48 + b2[poz2] - 48) + suma;
if (poz1 >= 0) poz1--;
if (poz2 >= 0) poz2--;
}
while (poz1 >= 0) {
suma = dalej(d, b1[poz1--]-48) + suma;
}
while (poz2 >= 0) {
suma = dalej(d, b2[poz2--] - 48) + suma;
}
while(d) suma = dalej(d,0) + suma;
return suma;
}
bool czy_negacje(string b1, string b2) {
if (b1.size() != b2.size()) return false;
for (auto& e : b1) {
if (e == '0') e = '1';
else e = '0';
}
return (b1 == b2);
}
string wieksza(string b1, string b2) {
bez0(b1); bez0(b2);
if (b1.size() > b2.size()) return b1;
if (b2.size() > b1.size()) return b2;
if (b1 == b2) return b1; // takie same
for (size_t poz = 0; poz < b1.size(); poz++) {
if (b1[poz] > b2[poz]) return b1;
if (b2[poz] > b1[poz]) return b2;
}
}

26589ec988c76404b19a97e88c6609a5
2
126 C++ ZBIÓR ZADAŃ Z ROZWIĄZANIAMI

int main() {
setlocale(LC_ALL, "");
cout << dodaj("00101010111111", "0001111111") << endl << endl;
cout << dodaj("111", "1") << endl << endl;

cout << czy_negacje("10101", "01010") << "\n\n";


cout << czy_negacje("111000", "000111") << "\n\n";
cout << czy_negacje("111000", "111111") << "\n\n";

cout << wieksza("111", "1000") << endl;


cout << wieksza("111", "111") << endl;
cout << wieksza("10111", "10011") << endl;
}

Zadanie #2.74
#include <iostream>
#include <vector>
#include <string>
using namespace std;
typedef long long int L;
typedef unsigned long long int UL;
//////////////////////////////////////////////////////
UL ostatni(UL N=100, int K = 3) {
vector<UL> v;
for (int i = 1; i <= N; i++) v.push_back(i);
UL pozycja = 0;
while (v.size() > 1) {
pozycja = (pozycja + K) % v.size();
v.erase(v.begin() + pozycja);
// zachowanie cykliczności przy skasowaniu ostatniego elementu
if (pozycja == v.size()) pozycja = 0;
}
return v[0];
}
int main() {
setlocale(LC_ALL, "");
UL o;
o = ostatni(100,3);
cout << "\nOstatnia ocalała liczba to: " << o << endl;
o = ostatni(6, 3);
cout << "\nOstatnia ocalała liczba to: " << o << endl;
o = ostatni(8, 3);
cout << "\nOstatnia ocalała liczba to: " << o << endl;
}

Zadanie #2.75
Nie, no jasne, pewnie…

26589ec988c76404b19a97e88c6609a5
2

You might also like