diff options
| author | Syndamia <kamen@syndamia.com> | 2024-02-29 16:43:04 +0200 |
|---|---|---|
| committer | Syndamia <kamen@syndamia.com> | 2024-02-29 16:43:04 +0200 |
| commit | 4d7764f709f713460d1e3159d7fdba7b1374b64c (patch) | |
| tree | 0646f67e9cec89a11427d491fc88cfd735fa3676 | |
| parent | bb132c2191dc7ad62c74c40d5e39cf673d621998 (diff) | |
| download | oop-2023-solutions-4d7764f709f713460d1e3159d7fdba7b1374b64c.tar oop-2023-solutions-4d7764f709f713460d1e3159d7fdba7b1374b64c.tar.gz oop-2023-solutions-4d7764f709f713460d1e3159d7fdba7b1374b64c.zip | |
[w2/ex0] Added exercise descriptions and solution to exercise zero
| -rw-r--r-- | week02/Exercise0.cpp | 307 | ||||
| -rw-r--r-- | week02/README.md | 176 |
2 files changed, 483 insertions, 0 deletions
diff --git a/week02/Exercise0.cpp b/week02/Exercise0.cpp new file mode 100644 index 0000000..764ed85 --- /dev/null +++ b/week02/Exercise0.cpp @@ -0,0 +1,307 @@ +#include <iostream> + +/* + * а) подточка + */ + +void boardCounts(char** board, int N, int& totalX, int& totalO, int& longestX, int& longestO) { + totalX = totalO = longestX = longestO = 0; + + // Обща бройка Х и О + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + if (board[i][j] == 'X') + totalX++; + else + totalO++; + } + } + + for (int i = 0; i < N; i++) { + int rowXs = 0, rowOs = 0; + for (int j = 0; j < N; j++) { + // Когато редицата от Х е прекъсната, запазваме ако е най-дългата и връщаме + if (board[i][j] == 'X') + rowXs++; + else { + if (rowXs > longestX) { + longestX = rowXs; + } + rowXs = 0; + } + + // Когато редицата от О е прекъсната, запазваме ако е най-дългата и връщаме + if (board[i][j] == 'O') + rowOs++; + else { + if (rowOs > longestX) { + longestX = rowOs; + } + rowOs = 0; + } + } + if (rowXs > longestX) longestX = rowXs; + if (rowOs > longestO) longestO = rowOs; + } +} + +void printResult(const char* nameX, const char* nameO, int totalX, int totalO, int longestX, int longestO) { + std::cout << nameX << ": Total - " << totalX << ", Longest - " << longestX << std::endl; + std::cout << nameO << ": Total - " << totalO << ", Longest - " << longestO << std::endl; +} + +void mainA() { + char nameX[1024]; + char nameO[1024]; + std::cin.getline(nameX, 1024); + std::cin.getline(nameO, 1024); + + std::cin.clear(); + + int N; + std::cin >> N; + + char** board = new char*[N]; + for (int i = 0; i < N; i++) { + board[i] = new char[N]; + } + + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + std::cin >> board[i][j]; + } + } + + int totalX, totalO, longestX, longestO; + boardCounts(board, N, totalX, totalO, longestX, longestO); + printResult(nameX, nameO, totalX, totalO, longestX, longestO); + + for (int i = 0; i < N; i++) { + delete[] board[i]; + } + delete[] board; +} + +/* + * б) подточка + * Почти същото е, намерете разликите + */ + +struct GameBoard { + char** board; + int N; +}; + +void boardCounts(GameBoard gb, int& totalX, int& totalO, int& longestX, int& longestO) { + totalX = totalO = longestX = longestO = 0; + + // Обща бройка Х и О + for (int i = 0; i < gb.N; i++) { + for (int j = 0; j < gb.N; j++) { + if (gb.board[i][j] == 'X') + totalX++; + else + totalO++; + } + } + + for (int i = 0; i < gb.N; i++) { + int rowXs = 0, rowOs = 0; + for (int j = 0; j < gb.N; j++) { + // Когато редицата от Х е прекъсната, запазваме ако е най-дългата и връщаме + if (gb.board[i][j] == 'X') + rowXs++; + else { + if (rowXs > longestX) { + longestX = rowXs; + } + rowXs = 0; + } + + // Когато редицата от О е прекъсната, запазваме ако е най-дългата и връщаме + if (gb.board[i][j] == 'O') + rowOs++; + else { + if (rowOs > longestX) { + longestX = rowOs; + } + rowOs = 0; + } + } + if (rowXs > longestX) longestX = rowXs; + if (rowOs > longestO) longestO = rowOs; + } +} + +void mainB() { + char nameX[1024]; + char nameO[1024]; + std::cin.getline(nameX, 1024); + std::cin.getline(nameO, 1024); + + std::cin.clear(); + + GameBoard gb; + std::cin >> gb.N; + + gb.board = new char*[gb.N]; + for (int i = 0; i < gb.N; i++) { + gb.board[i] = new char[gb.N]; + } + + for (int i = 0; i < gb.N; i++) { + for (int j = 0; j < gb.N; j++) { + std::cin >> gb.board[i][j]; + } + } + + int totalX, totalO, longestX, longestO; + boardCounts(gb, totalX, totalO, longestX, longestO); + printResult(nameX, nameO, totalX, totalO, longestX, longestO); + + for (int i = 0; i < gb.N; i++) { + delete[] gb.board[i]; + } + delete[] gb.board; +} + +/* + * в) подточка + */ + +struct BoardCounts { + int totalX; + int totalO; + int longestX; + int longestO; +}; + +BoardCounts boardCounts(GameBoard gb) { + BoardCounts bc = { 0, 0, 0, 0 }; + + // Обща бройка Х и О + for (int i = 0; i < gb.N; i++) { + for (int j = 0; j < gb.N; j++) { + if (gb.board[i][j] == 'X') + bc.totalX++; + else + bc.totalO++; + } + } + + for (int i = 0; i < gb.N; i++) { + int rowXs = 0, rowOs = 0; + for (int j = 0; j < gb.N; j++) { + // Когато редицата от Х е прекъсната, запазваме ако е най-дългата и връщаме + if (gb.board[i][j] == 'X') + rowXs++; + else { + if (rowXs > bc.longestX) { + bc.longestX = rowXs; + } + rowXs = 0; + } + + // Когато редицата от О е прекъсната, запазваме ако е най-дългата и връщаме + if (gb.board[i][j] == 'O') + rowOs++; + else { + if (rowOs > bc.longestX) { + bc.longestX = rowOs; + } + rowOs = 0; + } + } + if (rowXs > bc.longestX) bc.longestX = rowXs; + if (rowOs > bc.longestO) bc.longestO = rowOs; + } + return bc; +} + +void printResult(const char* nameX, const char* nameO, const BoardCounts& bc) { + std::cout << nameX << ": Total - " << bc.totalX << ", Longest - " << bc.longestX << std::endl; + std::cout << nameO << ": Total - " << bc.totalO << ", Longest - " << bc.longestO << std::endl; +} + +void mainC() { + char nameX[1024]; + char nameO[1024]; + std::cin.getline(nameX, 1024); + std::cin.getline(nameO, 1024); + + std::cin.clear(); + + GameBoard gb; + std::cin >> gb.N; + + gb.board = new char*[gb.N]; + for (int i = 0; i < gb.N; i++) { + gb.board[i] = new char[gb.N]; + } + + for (int i = 0; i < gb.N; i++) { + for (int j = 0; j < gb.N; j++) { + std::cin >> gb.board[i][j]; + } + } + + BoardCounts bc = boardCounts(gb); + printResult(nameX, nameO, bc); + + for (int i = 0; i < gb.N; i++) { + delete[] gb.board[i]; + } + delete[] gb.board; +} + +/* + * г) + */ + +struct Game { + char nameX[1024]; + char nameO[1024]; + GameBoard gb; + BoardCounts bc; +}; + +void printResult(const Game& game) { + std::cout << game.nameX << ": Total - " << game.bc.totalX << ", Longest - " << game.bc.longestX << std::endl; + std::cout << game.nameO << ": Total - " << game.bc.totalO << ", Longest - " << game.bc.longestO << std::endl; +} + +void mainD() { + Game game; + std::cin.getline(game.nameX, 1024); + std::cin.getline(game.nameO, 1024); + + std::cin.clear(); + + std::cin >> game.gb.N; + + game.gb.board = new char*[game.gb.N]; + for (int i = 0; i < game.gb.N; i++) { + game.gb.board[i] = new char[game.gb.N]; + } + + for (int i = 0; i < game.gb.N; i++) { + for (int j = 0; j < game.gb.N; j++) { + std::cin >> game.gb.board[i][j]; + } + } + + game.bc = boardCounts(game.gb); + printResult(game); + + for (int i = 0; i < game.gb.N; i++) { + delete[] game.gb.board[i]; + } + delete[] game.gb.board; +} + +int main() { + mainA(); + mainB(); + mainC(); + mainD(); +} diff --git a/week02/README.md b/week02/README.md new file mode 100644 index 0000000..0424c71 --- /dev/null +++ b/week02/README.md @@ -0,0 +1,176 @@ +# Задачи - ООП, Седмица 2, 29.02.2024 + +*Този файл е копие на задачите от: [syndamia.com/teaching/oop-2023/week2](https://syndamia.com/teaching/oop-2023/week2)* + +## Задача 0 - Преговорна + +Ще работим върху N-мерен [морски шах](https://en.wikipedia.org/wiki/Tic-tac-toe), тоест ще имаме дъска за морски шах, която може да е по-голяма от 3 на 3 (примерно 5 на 5, 7 на 7 и т.н.). +Няма да се занимаваме с проверки дали (и кой) е спечелил след даден ход, интересуваме се само от запазването на данни. + +Основната логика е следната, като във всяка подточка правила по имплементацията са зададени. + +&:warn Не почвайте веднага да имплементирайте, погледнете подточките! + +В началото от входа се въвеждат два реда, всеки съответстващ на имената на даден играч (в тези имена може да има шпации). +Първият играч винаги играе като X, вторият винаги като O. + +След това се въвежда цяло число N, това е размерът на дъската. +Накрая се въвеждат NxN на брой X-ове и O-та. + +За всеки играч трябва съответно да изкарате общия брой X-ове или броя O-та в цялата дъска, както и дължината на най-дългата последователност от Х-ове или О-та в един реда на дъската (примерно за първия играч, търсим реда с най-много последователни X-ове, и изкарваме тяхната бройка). + +**Пример:** + +|Вход|Изход| +|----|-----| +|Emil Petkov<br>BoburaBG<br>5<br>X X O O O<br>O X O X X<br>O X X X O<br>O X X X X<br>O X O O O<br>|Emil Petkov: Total - 13, Longest - 4<br>BoburaBG: Total - 12, Longest - 3| + +### а) без структури + +&:important Решете подточката **без** структури, тоест без знания по ООП + +Имплементирайте **функция** `boardCounts`, която приема дъската и връща по някакъв начин нужните бройки: общ брой X-ове, общ брой O-та, брой X-ове в най-дългата последователност от X-ове в ред, брой O-та в най-дългата последователност от O-та в ред. + +След това имплементирайте фукция `printResult`, която приема имената на двата играча, както и бройките, върнати от `boardCounts`, и изкарва на екрана съобщенията във формата от примера. + +### б) структура за board + +"Слепете" в една съвкупност (структура) указателя към самата дъска за морски шах, както и нейния размер N. +Нека името на структурата да бъде `GameBoard`. + +Обновете `boardCounts`, така че вместо да приема дъската и размера ѝ чрез две променливи, да ги приема чрез една променлива от тип `GameBoard`. + +### в) структура за числата + +"Слепете" в една съвкупност (структура) на име `BoardCounts` четирите променливи, които `boardCounts` връща. + +Обновете `boardCounts` да връща една стойност от тип `BoardCounts`, вместо да връща четирите бройки като отделни числа. +Обновете `printResult` да приема стойност от тип `BoardCounts`, вместо да приема четирите бройки като отделни числа. + +### г) структура за цялата игра + +Сега "слепете" предходните две структури, заедно с имената на нашите играчи, в една голяма обща структура за цялата игра на име `Game`. +Тоест, всичките ни данни: дъската, бройките и имената на играчите, да се намират в `Game`. + +&:important Искам да *композирате*, тоест искам да използвате `GameBoard` и `BoardCounts` структурите в `Game` структурата. + +Обновете `boardCounts` и `printResult`, така че да използват тази структура. + +## Задача 1 - Основи от материала + +Работите върху система за инвентар на книжарница. + +&:warn Не е задължително, но е препоръчително да си направите и една структура `String` с конструктор и деструктор + +Създайте структура `Book` със скрити (private) данни за: + +- заглавие, като един низ +- автори, като масив от низове +- година на публикация, като целочислено число +- цена, като число с плаваща запетая + +За всяка от тях създайте съответните публични селектор (get-ър) и мутатор (set-ър) член-функции (методи). +Set-ърите трябва да записват стойности в данните, само когато съответните проверки са изпълнени: + +- заглавието не може да бъде празния низ +- трябва да има поне един автор, името на даден автор не може да бъде празния низ +- годината на публикация не може да надвишава 2024, не може да е по-малка от -2100 (2100 п.н.е.) и не може да бъде нула +- цената не може да е отрицателна + +Всеки от мутаторите трябва да връща булева стойност, `true` ако проверките са изпълнени (и запазването на данни е извършено) и `false` ако съответната проверка не е изпълнена (и няма промяна в данните). +Създайте съответните конструктори и деструктори. + +След това направете структура `Library`, която държи масив от книги и бройката за всяка книга (отново като скрити данни). +Най-лесния вариант е да имате втори масив, като за всеки индекс в масива с книги, на същия индекс в масива за бройки се намира съответната бройка. +Можете и да го направите чрез структура `Pair` и да имате един масив. + +Като публични методи на `Library` имплементирайте `AddBook`, която вмъква нова книга в масива, и `RemoveBook` която съответно "премахва" книга по заглавие и година. +Допълнително направете член-функция `StockBook`, която приема заглавие на книга, годината ѝ, и цяло число с което наличната бройка се увеличава. +Аналогично направете и `SellBook`. +За всики тези методи трябва да имате съответните проверки: + +- ако напълно идентична книга вече съществува, `AddBook` не трябва да я добавя на ново +- `RemoveBook` не трябва да "гърми" ако книгата не съществува +- бройката на добавени/продадени книги, подадени на `SellBook` и `StockBook`, трябва да бъдат положителни, както и книгите да съществуват + +Аналогично като при `Book`, тези функции трябва да връщат булева стойност, дали проверките са изпълнени. +Не забравяйте за конструктор и деструктор! + +&:question Можете ли да си улесните работата, ако използвате скрити член-функции? + +Не е нужно да правите потребителски вход/изход, но тествайте ръчно кода си в `main`. + +## Задача 2 + +Работите върху система за Excel-ски таблици. +Една клетка може да съдържа някаква числена стойност, или проста формула която определя тази стойност. + +Създайте структура `Cell`, която запазва (скрито) целочислена стойност, знак, който определя опреацията във формулата, и два указателя на `Cell` към двете страни на оператора. +Оператора (знака) може да бъде `+`, `-`, `*` или `/`. + +Идеята е, че ако клетката само запазва стойност, тогава оператора ще бъде нещо празно (терминираща нула например). +Обаче ако се определя от формула, тогава оператора и указателите също ще са попълнени, а запазената стойност ще действа като кеш, тоест вместо всеки път да преизчисляваме стойността когато я искаме, преизчислили сме я веднъж и я запазваме. + +За тази цел имплементирайте публична член-функция `evaluate`, ако не е запазена формула, тя не прави нищо, ако е, прави съответното изчисление и запазва резултата. +Разбира се, направете и мутатори `setValue` и `setFormula`, със съответните проверки. +Не забравяйте за конструктор и деструктор. + +Сега направете структура `Table`, която пази (скрито) двумерен масив от клетки. +Имплементирайте селектор `getCell`, който връща указател на клетка по координати и мутатор `setCell`, който приема клетка и координати в масива. + +&:question Какъв ще е типа на подадената клетка и стойностите в масива? + +Направете метод `updateCell`, чрез която стойностите на клетка по координати могат да бъдат променени, и след това всички клетки в таблицата се преизчисляват. + +Последно, имплементирайте и член-функция `printTable`, която изкарва на екрана цялата таблица, като клетката на индекси 0,0 се намира в горния ляв ъгъл, всички клетки са разделени с `|`. + +Не е нужно да правите потребителски вход/изход, но тествайте ръчно кода си в `main`. + +## Задача 3 + +Изграждате "симулация" за трафик върху секция от магистрала. + +Самата магистрала се характеризира от брой платна (ширина) и дължина. + +Върху магистралата се слагат произволен брой коли. +Всяка кола се определя с координатите си върху магистралата и своета скорост. +Всички коли се движат от "ляво" на "дясно" по магистралата, винаги в едно и също платно, без да могат да се надминават или заобикалят. +Една кола има скорост: число между 0 и 8 включително. + +В началото на симулацията, всяка кола се разпределя по случаен начин върху магистралата, и всяка кола има случайна скорост между 4 и 6 включително. +Разглеждайки от най-десните към най-левите, всяка кола се опитва да се придвижи, като нейната скорост определя с колко клетки надясно ще се мръдне. + +Ако по пътя ѝ няма други коли, тя се премества спокойно. +Ако има, тогава нейната скорост се намалява на половина, и пробва да се придвижи пак. +Ако и с намалената скорост има кола на пътя ѝ, двете коли се удрят, "предната" кола застава на място, "задната" застава директно зад нея и двете получават скорост 0. + +След като една кола успешно се е придвижила напред, тя увеличва своета скорост със случайно количество между 0 и 3. +Ако една кола се е блъснала или просто е спряла (има скорост 0), тогава увеличава своета скорост на единица, и след това продължава както нормално. + +Ако една кола успешно "излиза" от участака на магистралата, тоест тя се опитва да се придвижи някъде след края ѝ, зачитаме че успешно е минала пътя и спираме да я разглеждаме. + +Сами определете как ще изглеждат структурите за колата и магистралата, както и нужните методи. +Имайте предвид, че трябва цялата логика да присъства в тези структури, тоест в `main` трябва да присъства само някакъв инициализиращ код. + +&:important Не е позволено магистралата да бъде двумерна матрица, координатите на всяка кола се пазят в самата кола. + +Накрая пуснете симулацията няколко пъти, на всяко извикване трябва да изкарате на екрана брой получили се сблъсаци, както и броя нужни итерации с които сте обходили всички коли на пътя, докато всички те излязат от магистралата. +Симулации се различават с позиции и началните скорости на колите, бройката коли и размерите на магистралата си стоят. + +## Задача 4 + +Имате фабрика, цялата ѝ структура се разглежда като един конвейер, тоест като една редица машини, всяка от които приема някакъв материал и връща този материал преобразуван. + +Един материал се определя с три целочислени стойности: идентификационен номер, начален тип (тоест като какво се подава) и краен тип (тоест в какво се очаква да се преобразува). + +Една машина се характеризира с ефикасност спрямо материали: представете си една таблица, от едната колона има идентификационни номера на материали, от друга има числа с плаваща запетая, определящи процент ефикасност. +Допълнително за нея знаем колко материал може да преобразува, преди да се нуждае от ремонт. + +Когато даден материал е подаден на машината, тя го преобразува в материал от дадения краен тип. +Типовете на материалите са отделни стойности от идентификационните номера, тоест като е подаден материал, той се превръща в крайния тип, и трябва да намерите на кой материал точва число е началния тип. + +Всички тези данни трябва да са скрити, трябва за съответните структури да присъстват конструктори и деструктори. +Допълнително при машините трябва да има член-функция `convertMaterial`, която получава идентификационен номер на материал и бройка, и връща колко от резултатния материал е успяла да създаде (спрямо ефикасността, закръглена надолу, и дали се нуждае от ремонт по средата на работата). + +Ще получите данни за всички материали и машини, както и задачи, тоест идентификационни номера на начален и краен материал, както и бройката на началния материал. +Трябва да намерите редицата от машини, които ще създадат възможно най-много краен материал. |
