diff options
feat(Week11): Add solutions
15 files changed, 669 insertions, 0 deletions
| -rw-r--r-- | Week11/Exercise01.cpp | 13 | ||||
| -rw-r--r-- | Week11/Exercise02.cpp | 82 | ||||
| -rw-r--r-- | Week11/Exercise03.cpp | 64 | ||||
| -rw-r--r-- | Week11/Exercise04.cpp | 23 | ||||
| -rw-r--r-- | Week11/Exercise05.cpp | 28 | ||||
| -rw-r--r-- | Week11/Exercise06.cpp | 37 | ||||
| -rw-r--r-- | Week11/Exercise07.cpp | 48 | ||||
| -rw-r--r-- | Week11/Exercise08.cpp | 77 | ||||
| -rw-r--r-- | Week11/Exercise09.cpp | 53 | ||||
| -rw-r--r-- | Week11/Exercise10.cpp | 31 | ||||
| -rw-r--r-- | Week11/Exercise11.cpp | 48 | ||||
| -rw-r--r-- | Week11/Exercise12.cpp | 60 | ||||
| -rw-r--r-- | Week11/Exercise13.cpp | 42 | ||||
| -rw-r--r-- | Week11/Exercise14.cpp | 60 | ||||
| -rw-r--r-- | Week11/README.md | 3 |
diff --git a/Week11/Exercise01.cpp b/Week11/Exercise01.cpp new file mode 100644 index 0000000..784c5ac --- /dev/null +++ b/Week11/Exercise01.cpp @@ -0,0 +1,13 @@ +#include <iostream> + +int main() { + const unsigned NAME_LENGTH = 20; + + // 20 букви за името и 1 буква за терминиращата нула + char name[NAME_LENGTH + 1]; + std::cin.getline(name, NAME_LENGTH + 1); + + std::cout << "Hello, " << name << "!" << std::endl; + + return 0; +} diff --git a/Week11/Exercise02.cpp b/Week11/Exercise02.cpp new file mode 100644 index 0000000..9041fab --- /dev/null +++ b/Week11/Exercise02.cpp @@ -0,0 +1,82 @@ +#include <iostream> + +/* Предлагам три решения на тази задача */ + +unsigned countLetters(const char* str) { + unsigned count = 0; + while (*str != '\0') { + count += ('A' <= *str && *str <= 'Z') || + ('a' <= *str && *str <= 'z'); + ++str; + } + return count; +} + +// Избираме си максимален размер за низа +void solution1() { + const unsigned MAX_LENGTH = 1024; + + char sentence[MAX_LENGTH]; + std::cin.getline(sentence, MAX_LENGTH, '.'); + + std::cout << countLetters(sentence) << std::endl; +} + +// Низа може да бъде произволно дълъг +void solution2() { + // Заделяме памет за низа, следим колко букви сме вкарали в низа. + // Ако запълним заделената памет, реоразмеряваме масива (правим + // го по-голям). + + unsigned allocated = 8, size = 0; + char* sentence = new char[allocated]; + + char curr; + std::cin.get(curr); + while (curr != '.') { + sentence[size++] = curr; + std::cin.get(curr); + + // Реоразмеряване + if (size >= allocated) { + allocated *= 2; + char* newSentenceArray = new char[allocated]; + + for (unsigned i = 0; i < size; i++) + newSentenceArray[i] = sentence[i]; + + delete[] sentence; + sentence = newSentenceArray; + } + } + sentence[size] = '\0'; + + std::cout << countLetters(sentence) << std::endl; + + delete[] sentence; +} + +// В тази конкретна задача, не е нужно да запазваме +// целия низ и после да гледаме буквите, можем директно +// да анализираме входа буква по буква +void solution3() { + unsigned count = 0; + + char curr; + std::cin.get(curr); + while (curr != '.') { + count += ('A' <= curr && curr <= 'Z') || + ('a' <= curr && curr <= 'z'); + std::cin.get(curr); + } + + std::cout << count << std::endl; +} + +int main() { + // solution1(); + // solution2(); + solution3(); + + return 0; +} diff --git a/Week11/Exercise03.cpp b/Week11/Exercise03.cpp new file mode 100644 index 0000000..3620061 --- /dev/null +++ b/Week11/Exercise03.cpp @@ -0,0 +1,64 @@ +#include <iostream> + +unsigned fieldsCount(const char* str) { + // Едно поле не съдържа шпации, което реално означава, че + // всяко поле ще бъде заобиколено от шпации (с леко изключение + // на първото и последното поле). + // + // В такъв случай, можем да кажем, че началото на поле се "маркира" + // с първата не-шпация след редица от шпации. Тоест, ако текущия + // знак не е шпация, достатъчно е да погледнем предходния знак, за да + // разберем дали сме започнали поле или сме по средата на поле. + // + // И за нашата задача, остава само да преборим тези начала, което е + // същото като броя полета. Допълнително, ако инициализираме + // предходната буква да е шпация, тогава винаги ще преборим първото + // поле. + // + // Да, задачата може да се реши без запазването на целия низ. + + unsigned count = 0; + + char prev = ' '; + char curr = *(str++); + + while (curr != '\0') { + count += prev == ' ' && curr != ' '; + + prev = curr; + curr = *(str++); + } + + return count; +} + +int main() { + unsigned allocated = 8, size = 0; + char* sentence = new char[allocated]; + + char curr; + std::cin.get(curr); + while (curr != '.') { + sentence[size++] = curr; + std::cin.get(curr); + + // Реоразмеряване + if (size >= allocated) { + allocated *= 2; + char* newSentenceArray = new char[allocated]; + + for (unsigned i = 0; i < size; i++) + newSentenceArray[i] = sentence[i]; + + delete[] sentence; + sentence = newSentenceArray; + } + } + sentence[size] = '\0'; + + std::cout << fieldsCount(sentence) << std::endl; + + delete[] sentence; + + return 0; +} diff --git a/Week11/Exercise04.cpp b/Week11/Exercise04.cpp new file mode 100644 index 0000000..081973b --- /dev/null +++ b/Week11/Exercise04.cpp @@ -0,0 +1,23 @@ +#include <iostream> + +int main() { + char prev = '\0', curr = prev; + std::cin.get(curr); + + // Всеки ред се бележи с \n накрая. Ако имаме празен ред, + // то целия ред ще съдържа само \n. + // Тоест, ако имаме ред с текст, и директно след него "празен" + // ред, то ще имаме две \n в последователност. + + unsigned count = 0; + while (prev != '\n' || curr != '\n') { + count += curr == '\n'; + + prev = curr; + std::cin.get(curr); + } + + std::cout << count << std::endl; + + return 0; +} diff --git a/Week11/Exercise05.cpp b/Week11/Exercise05.cpp new file mode 100644 index 0000000..5177003 --- /dev/null +++ b/Week11/Exercise05.cpp @@ -0,0 +1,28 @@ +#include <iostream> + +int main() { + const unsigned SIZE = 1024; + + char str[SIZE]; + std::cin.getline(str, SIZE, ':'); + double a, b; + std::cin >> a >> b; + + for (unsigned i = 0; str[i] != '\0' && str[i+2] != '\0'; i++) { + if (str[i] == 's' && + str[i+1] == 'u' && + str[i+2] == 'm') + { + std::cout << (a + b) << ' '; + } + else if (str[i] == 's' && + str[i+1] == 'u' && + str[i+2] == 'b') + { + std::cout << (a - b) << ' '; + } + } + std::cout << std::endl; + + return 0; +} diff --git a/Week11/Exercise06.cpp b/Week11/Exercise06.cpp new file mode 100644 index 0000000..82860d1 --- /dev/null +++ b/Week11/Exercise06.cpp @@ -0,0 +1,37 @@ +#include <iostream> + +int main() { + const unsigned MAX_LENGTH = 128; + char num[MAX_LENGTH]; + std::cin.getline(num, MAX_LENGTH); + + const char* digit = num + 2; + unsigned long number = 0; + + while (*digit != '\0') { + // Когато разглеждахме операции с цифри (добавяне/премахване на цифра от число), + // тогава говорехме как с деление на 10 премаваме цифра и с умножение на 10 я + // добавяме в десния край на числото. + // + // Това работи, защото цифрите ни са в десетична бройна система. Ако работехме + // например с двоична, тогава щяхме да делим и умножаваме с 2, за да махаме/добавяме + // "цифри" в края на числото (да се има впредвид, че резултата ще е в 10тична бройна + // система). + // + // Аналогично, понеже работим с 16тична, правим операции с числото 16. + + if ('0' <= *digit && *digit <= '9') { + number = number * 16 + (*digit - '0'); + } + // А e 10, B е 11, ..., F е 15 + else if ('A' <= *digit && *digit <= 'F') { + number = number * 16 + (*digit - 'A' + 10); + } + + ++digit; + } + + std::cout << number << std::endl; + + return 0; +} diff --git a/Week11/Exercise07.cpp b/Week11/Exercise07.cpp new file mode 100644 index 0000000..e434919 --- /dev/null +++ b/Week11/Exercise07.cpp @@ -0,0 +1,48 @@ +#include <iostream> + +int main() { + const unsigned PATTERN_SIZE = 5; + char pattern[PATTERN_SIZE + 1]; + std::cin.getline(pattern, PATTERN_SIZE+1); + + unsigned allocated = 8, size = 0; + char* text = new char[allocated]; + + char curr; + std::cin.get(curr); + while (curr != '\n') { + text[size++] = curr; + std::cin.get(curr); + + // Реоразмеряване + if (size >= allocated) { + allocated *= 2; + char* newSentenceArray = new char[allocated]; + + for (unsigned i = 0; i < size; i++) + newSentenceArray[i] = text[i]; + + delete[] text; + text = newSentenceArray; + } + } + text[size] = '\0'; + + unsigned matches = 0; + for (unsigned i = 0; i < size - PATTERN_SIZE + 1; i++) { + bool allMatch = true; + + // Проверяваме дали от текущата буква в текста, нататък, + // низа съвпада с шаблона. + for (unsigned j = 0; j < PATTERN_SIZE; j++) + allMatch = allMatch && (text[i + j] == pattern[j]); + + matches += allMatch; + } + + std::cout << matches << std::endl; + + delete[] text; + + return 0; +} diff --git a/Week11/Exercise08.cpp b/Week11/Exercise08.cpp new file mode 100644 index 0000000..7807913 --- /dev/null +++ b/Week11/Exercise08.cpp @@ -0,0 +1,77 @@ +#include <iostream> + +bool strneq(const char* str1, const char* str2, unsigned n) { + // Грозно е, но е добро упражнение за реда на операции + while (*str1 != '\0' && *str2 != '\0' && n-- > 0) { + if (*str1++ != *str2++) + return false; + } + return true; +} + +void printField(const char* str) { + while (*str != ' ' && *str != '\0') { + std::cout << *str++; + } +} + +int main() { + // Кодът е написан, допускайки че "end" е единствената + // възможна дума, обозначаваща край. + // Как може да се пренапише, така че да можем да си + // изберем произволен низ, обозначаващ край? + + unsigned allocated = 8, size = 0; + char* text = new char[allocated]; + + std::cin.get(text[size++]); + std::cin.get(text[size++]); + std::cin.get(text[size++]); + + char curr; + while (!strneq(text + size - 3, "end", 3)) { + std::cin.get(curr); + text[size++] = curr; + + // Реоразмеряване + if (size >= allocated) { + allocated *= 2; + char* newSentenceArray = new char[allocated]; + + for (unsigned i = 0; i < size; i++) + newSentenceArray[i] = text[i]; + + delete[] text; + text = newSentenceArray; + } + } + text[size] = '\0'; + + // Обикаляме отзад-напред. В момента в който стигнем началото на поле + // (а именно, не-шпация преди която имаме шпация), тогава изкарваме + // полето. Тоест започваме временно да се движим напред, докато не + // сме изразходили буквите, съставящи полето. + // + // Тази схема очевидно оставя полето от първата буква непринтирано. + + bool prevNonSpace = false; + for (int i = size - 1; i >= 0; i--) { + if (text[i] != ' ') { + prevNonSpace = true; + continue; + } + + if (prevNonSpace) { + printField(text + i + 1); + prevNonSpace = false; + } + + std::cout << text[i]; + } + printField(text); + std::cout << std::endl; + + delete[] text; + + return 0; +} diff --git a/Week11/Exercise09.cpp b/Week11/Exercise09.cpp new file mode 100644 index 0000000..5091b2f --- /dev/null +++ b/Week11/Exercise09.cpp @@ -0,0 +1,53 @@ +#include <iostream> + +char* getField() { + unsigned allocated = 8, size = 0; + char* output = new char[allocated]; + + char curr; + std::cin.get(curr); + + while (curr != ' ' && curr != '\n' && curr != '\0') { + output[size++] = curr; + std::cin.get(curr); + + // Реоразмеряване + if (size >= allocated) { + allocated *= 2; + char* newSentenceArray = new char[allocated]; + + for (unsigned i = 0; i < size; i++) + newSentenceArray[i] = output[i]; + + delete[] output; + output = newSentenceArray; + } + } + output[size] = '\0'; + + return output; +} + +int main() { + char* search = getField(), *pattern = getField(); + + // char е 8 битово, което означава че има 2^^8 = 256 + // на брой различни възможни стойности. + // Знаем, че всяка буква всъщност е едно число, затова + // можем директно да го използваме като индекс. + + unsigned occurrences[256] = { 0 }; + for (const char* ser = search; *ser != '\0'; ser++) + occurrences[*ser]++; + + unsigned sumOccurrences = 0; + for (const char* pat = pattern; *pat != '\0'; pat++) + sumOccurrences += occurrences[*pat]; + + std::cout << sumOccurrences << std::endl; + + delete[] search; + delete[] pattern; + + return 0; +} diff --git a/Week11/Exercise10.cpp b/Week11/Exercise10.cpp new file mode 100644 index 0000000..4f42b06 --- /dev/null +++ b/Week11/Exercise10.cpp @@ -0,0 +1,31 @@ +#include <iostream> + +int main() { + const unsigned LINE_SIZE = 1024; + + char line[LINE_SIZE]; + std::cin.getline(line, LINE_SIZE); + + // char е 8 битово, което означава че има 2^^8 = 256 + // на брой различни възможни стойности. + // Знаем, че всяка буква всъщност е едно число, затова + // можем директно да го използваме като индекс. + + bool encountered[256] = { 0 }; + for (unsigned i = 0; line[i] != '\0'; i++) + encountered[line[i]] = true; + + // Всички малки букви са отместени с 32 спрямо главните. + // Тоест, главна буква + 32 = съответната малка буква + + bool isPangram = true; + for (char ch = 'A'; isPangram && ch <= 'Z'; ch++) + isPangram = encountered[ch] || encountered[ch + 32]; + + if (isPangram) + std::cout << "Pangram" << std::endl; + else + std::cout << "Not a pangram" << std::endl; + + return 0; +} diff --git a/Week11/Exercise11.cpp b/Week11/Exercise11.cpp new file mode 100644 index 0000000..988bea6 --- /dev/null +++ b/Week11/Exercise11.cpp @@ -0,0 +1,48 @@ +#include <iostream> + +bool streq(const char* str1, const char* str2) { + while (*str1 != '\0' && *str2 != '\0') { + if (*str1++ != *str2++) + return false; + } + return true; +} + +unsigned strlen(const char* str) { + unsigned len = 0; + while (*str++ != '\0') + len++; + return len; +} + +int main() { + const unsigned MAX_LINE_LENGTH = 1024; + char first[MAX_LINE_LENGTH], second[MAX_LINE_LENGTH]; + + std::cin.getline(first, MAX_LINE_LENGTH); + std::cin.getline(second, MAX_LINE_LENGTH); + + // Как премахваме букви? Най-лесния начин е просто да ги презапишем. + // Все едно отместваме частта от низа след буквата, така че да се + // застъпи с това, което премахваме. + // + // Например, ако в "abcde" искаме да премахнем c, тогава просто + // на позицията на c ще запишем d, на позицията на d ще запишем е + // и на позицията на e ще запишем терминираща нула. + + unsigned secondLen = strlen(second); + + for (unsigned readIndex = 0, writeIndex = 0; first[readIndex] != '\0'; readIndex++, writeIndex++) { + if (streq(first + readIndex, second)) + readIndex += secondLen; + + if (readIndex != writeIndex) { + first[writeIndex] = first[readIndex]; + first[writeIndex + 1] = '\0'; + } + } + + std::cout << first << std::endl; + + return 0; +} diff --git a/Week11/Exercise12.cpp b/Week11/Exercise12.cpp new file mode 100644 index 0000000..3ebb947 --- /dev/null +++ b/Week11/Exercise12.cpp @@ -0,0 +1,60 @@ +#include <iostream> + +unsigned passwordGrade(const char* password) { + unsigned charCount = 0; + bool containsLetter = false, containsDigit = false, containsSpecial = false, noNeighbouring = true; + + while (*password != '\0') { + if (('a' <= *password && *password <= 'z') || + ('A' <= *password && *password <= 'Z')) + { + containsLetter = true; + } + else if ('0' <= *password && *password <= '9') { + containsDigit = true; + } + else { + containsSpecial = true; + } + + if (password[0] == password[1]) { + noNeighbouring = false; + } + + charCount++; + password++; + } + + return (charCount >= 15) + containsLetter + containsDigit + containsSpecial + noNeighbouring; +} + +int main() { + unsigned allocated = 8, size = 0; + char* password = new char[allocated]; + + char curr; + std::cin.get(curr); + while (curr != '\n') { + password[size++] = curr; + std::cin.get(curr); + + // Реоразмеряване + if (size >= allocated) { + allocated *= 2; + char* newSentenceArray = new char[allocated]; + + for (unsigned i = 0; i < size; i++) + newSentenceArray[i] = password[i]; + + delete[] password; + password = newSentenceArray; + } + } + password[size] = '\0'; + + std::cout << passwordGrade(password) << std::endl; + + delete[] password; + + return 0; +} diff --git a/Week11/Exercise13.cpp b/Week11/Exercise13.cpp new file mode 100644 index 0000000..ee7f57f --- /dev/null +++ b/Week11/Exercise13.cpp @@ -0,0 +1,42 @@ +#include <iostream> + +unsigned fnvHash(const char* str) { + unsigned hash = 2166136261; + while (*str != '\0') { + hash *= 16777619; + hash ^= *str; + str++; + } + return hash; +} + +int main() { + unsigned allocated = 8, size = 0; + char* sentence = new char[allocated]; + + char curr; + std::cin.get(curr); + while (curr != '\n') { + sentence[size++] = curr; + std::cin.get(curr); + + // Реоразмеряване + if (size >= allocated) { + allocated *= 2; + char* newSentenceArray = new char[allocated]; + + for (unsigned i = 0; i < size; i++) + newSentenceArray[i] = sentence[i]; + + delete[] sentence; + sentence = newSentenceArray; + } + } + sentence[size] = '\0'; + + std::cout << fnvHash(sentence) << std::endl; + + delete[] sentence; + + return 0; +} diff --git a/Week11/Exercise14.cpp b/Week11/Exercise14.cpp new file mode 100644 index 0000000..4b62d3a --- /dev/null +++ b/Week11/Exercise14.cpp @@ -0,0 +1,60 @@ +#include <iostream> + +char* getLine() { + unsigned allocated = 8, size = 0; + char* sentence = new char[allocated]; + + char curr; + std::cin.get(curr); + while (curr != '\n') { + sentence[size++] = curr; + std::cin.get(curr); + + // Реоразмеряване + if (size >= allocated) { + allocated *= 2; + char* newSentenceArray = new char[allocated]; + + for (unsigned i = 0; i < size; i++) + newSentenceArray[i] = sentence[i]; + + delete[] sentence; + sentence = newSentenceArray; + } + } + sentence[size] = '\0'; + + return sentence; +} + +int main() { + char* first = getLine(), *second = getLine(); + + bool foundCharacters[256] = { 0 }; + for (char* f = first; *f != '\0'; f++) + foundCharacters[*f] = true; + + bool isAnagram = true; + for (char* s = second; *s != '\0' && isAnagram; s++) { + // Малките букви са отместени от главните с 32, + // тоест всяка главна буква + 32 прави съответната малка буква + // (и обратно). + + if ('A' <= *s && *s <= 'Z') { + isAnagram = foundCharacters[*s] || foundCharacters[*s + 32]; + } + else if ('a' <= *s && *s <= 'z') { + isAnagram = foundCharacters[*s] || foundCharacters[*s - 32]; + } + } + + if (isAnagram) + std::cout << "Anagram" << std::endl; + else + std::cout << "Not an anagram" << std::endl; + + delete[] first; + delete[] second; + + return 0; +} diff --git a/Week11/README.md b/Week11/README.md new file mode 100644 index 0000000..c42057c --- /dev/null +++ b/Week11/README.md @@ -0,0 +1,3 @@ +# Задачи + +<https://syndamia.com/teaching/upp-2025/week11/> |
