Created
April 4, 2025 21:44
-
-
Save Ruthenus/9ecb7566edaf417256c95ec29ae0f9de to your computer and use it in GitHub Desktop.
Week 15 Homework in IT STEP Academy (arrays tasks)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <iostream> // для роботи з потоками вводу/виводу | |
| #include <windows.h> // щоб використати функцію SetConsoleOutputCP | |
| #include <cstdlib> // для роботи з генерацією випадкових чисел | |
| #include <ctime> // те саме | |
| #include <algorithm> // зокрема, функції для роботи з масивом | |
| #include <cmath> // математична бібліотека | |
| #include <iomanip> // для налаштування вирівнювання | |
| #include <string> // щоб застосувати рядковий тип | |
| using namespace std; | |
| // Завдання на одновимірні масиви (4 задачі) | |
| // ПОЧАТОК КОДУ ЗАДАЧІ | |
| // 7. Створити масив із 20 випадкових чисел у діапазоні від -30 до 10. | |
| // Визначити суму елементів масиву, що знаходяться ДО | |
| // першого додатного елемента. | |
| int main() | |
| { | |
| SetConsoleOutputCP(1251); | |
| cout << "\tЗАВДАННЯ I.7\n\n"; | |
| // Безпечна ініціалізація масиву | |
| const short SIZE = 20; | |
| short array[SIZE]{}; // створення масиву нулів | |
| // Ініціалізація генератора випадкових чисел | |
| srand(time(0)); | |
| // Заповнення масиву випадковими числами в заданому діапазоні: | |
| for (short i = 0; i < SIZE; ++i) { | |
| array[i] = rand() % 41 - 30; // від -30 до 10; | |
| } | |
| // Шукаємо перший додатний елемент. Якщо знайдено додатний елемент, | |
| // визначаємо суму елементів, які розташовані до нього в масиві. | |
| short firstPositiveIndex = -1; // ініціалізація індексу! | |
| short sumBeforeFirstPositive = 0; // сума попередніх елементів | |
| for (short i = 0; i < SIZE; ++i) { | |
| if (array[i] > 0) { | |
| firstPositiveIndex = i; | |
| break; | |
| } | |
| sumBeforeFirstPositive += array[i]; | |
| } | |
| // Виведення масиву та відповіді | |
| // https://acode.com.ua/urok-95-tsykl-foreach/ | |
| cout << "Значить так, маємо масив із 20 випадкових чисел "; | |
| cout << "в діапазоні від -30 до 10:\n\n"; | |
| for (const auto& element : array) { | |
| cout << element << " "; | |
| } | |
| cout << "\n"; | |
| if (firstPositiveIndex != -1) { | |
| cout << "\nСума елементів до першого додатного елемента дорівнює "; | |
| cout << sumBeforeFirstPositive << ". Уявляєте?\n"; | |
| } | |
| else { | |
| cout << "Додатний елемент не знайдений у масиві, "; | |
| cout << "тому нічого не рахуємо.\n"; | |
| } | |
| cout << "\n" << string(80, '-') << "\n"; | |
| return 0; | |
| } | |
| // КІНЕЦЬ КОДУ ЗАДАЧІ | |
| // ПОЧАТОК КОДУ ЗАДАЧІ | |
| // 9. Створити масив на 100 дійсних чисел. Визначити, | |
| // скільки елементів масиву не мають дробової частини. | |
| int main() | |
| { | |
| SetConsoleOutputCP(1251); | |
| cout << "\tЗАВДАННЯ I.9\n\n"; | |
| const int SIZE = 100; // відповідно до завдання! | |
| double array[SIZE]; | |
| int count = 0; // лічильник чисел без дробової частини | |
| const double EPS = 1E-9; // допустима похибка для порівняння | |
| // Ініціалізація генератора випадкових чисел | |
| srand(time(0)); | |
| // Заповнення масиву випадковими дійсними числами: | |
| for (int i = 0; i < SIZE; ++i) { | |
| if (rand() % 2 == 0) { // 50% шанс на ціле число | |
| array[i] = rand() % 101; // лише ціла частина | |
| } | |
| else { // 50% шанс на дробове число | |
| array[i] = rand() % 101 + ((double)(rand()) / RAND_MAX); | |
| } // https://learn.microsoft.com/ru-ru/cpp/c-runtime-library/rand-max?view=msvc-170 | |
| } | |
| // Підрахунок чисел без дробової частини! | |
| // Якщо модуль остачі від ділення на 1 менше ніж похибка округлення | |
| // EPS, вважаємо, що дробова частина відсутня | |
| for (int i = 0; i < SIZE; ++i) { | |
| if (fabs(fmod(array[i], 1.0)) < EPS) { | |
| // https://learn.microsoft.com/ru-ru/cpp/c-runtime-library/reference/fabs-fabsf-fabsl?view=msvc-170 | |
| // https://learn.microsoft.com/ru-ru/cpp/c-runtime-library/reference/fmod-fmodf?view=msvc-170 | |
| count++; | |
| } | |
| } | |
| cout << "Генерую масив на " << SIZE << " дійсних чисел.\n"; | |
| cout << "Кількість елементів без дробової частини: " << count << "\n"; | |
| cout << "\n" << string(80, '-') << "\n"; | |
| return 0; | |
| } | |
| // КІНЕЦЬ КОДУ ЗАДАЧІ | |
| // ПОЧАТОК КОДУ ЗАДАЧІ | |
| // 11. Створити масив із 10 цілих випадкових чисел. Змінити порядок | |
| // слідування елементів масиву на протилежний (1-й елемент змінюється | |
| // з 10-м, 2-й — з 9-м і т. д.). | |
| int main() | |
| { | |
| SetConsoleOutputCP(1251); | |
| cout << "\tЗАВДАННЯ I.11\n\n"; | |
| srand(time(0)); | |
| // Створюємо масив із 10 випадкових цілих чисел від -44 до 44: | |
| const short SIZE = 10; | |
| short array[SIZE]; | |
| cout << "Випадковий масив із парної кількості цілих чисел: "; | |
| for (short i = 0; i < SIZE; ++i) { | |
| array[i] = rand() % 89 - 44; | |
| cout << array[i] << " "; | |
| } | |
| cout << "\n"; | |
| // Переставляємо елементи місцями: 1-й та 10-й, 2-й та 9-й, | |
| // 3-й та 8-й, 4-й та 7-й, 5-й та 6-й – ПРАКТИЧНО ВРУЧНУ | |
| for (short i = 0; i < SIZE / 2; ++i) { | |
| short a = array[i]; | |
| array[i] = array[SIZE - i - 1]; | |
| array[SIZE - i - 1] = a; // SIZE / 2, тому що вже переставлено | |
| } | |
| cout << "\nЦей масив у зворотному порядку: "; | |
| for (const short element : array) { | |
| cout << element << " "; | |
| } | |
| cout << "\n"; | |
| cout << "\n" << string(80, '-') << "\n"; | |
| return 0; | |
| } | |
| // КІНЕЦЬ КОДУ ЗАДАЧІ | |
| // ПОЧАТОК КОДУ ЗАДАЧІ | |
| // 12. Дано 2 масиви розміру M і N відповідно. Переписати в | |
| // третій масив спільні елементи перших двох масивів без повторень. | |
| int main() | |
| { | |
| SetConsoleOutputCP(1251); | |
| cout << "\tЗАВДАННЯ I.12\n\n"; | |
| // Розміри масивів | |
| const short M = 50; | |
| const short N = 70; | |
| // Створення масивів випадкових цілих чисел розміру M і N відповідно: | |
| srand(time(0)); | |
| int arrayM[M]; | |
| for (short i = 0; i < M; ++i) { | |
| // arrayM[i] = rand() % (2 * M * 1000 + 1) - M * 1000; | |
| arrayM[i] = rand() % (2 * M + 1) - M; | |
| } // M випадкових чисел у діапазоні -M, M | |
| int arrayN[N]; | |
| for (short j = 0; j < N; ++j) { | |
| // arrayN[j] = rand() % (2 * N * 1000 + 1) - N * 1000; | |
| arrayN[j] = rand() % (2 * N + 1) - N; | |
| } // N випадкових чисел у діапазоні -N, N | |
| // Відсортуємо обидва масиви за допомогою стандартної функції | |
| sort(arrayM, arrayM + M); | |
| sort(arrayN, arrayN + N); | |
| // https://stackoverflow.com/questions/5897319/how-to-use-stdsort-to-sort-an-array-in-c | |
| // Створимо масив для зберігання спільних елементів без повторень | |
| int arrayCommon[min(M, N)]; | |
| short common = 0; // ініціалізація кількості елементів у масиві | |
| // Див. реалізацію методу подвійного вказівника мовою PYTHON тут: | |
| // https://gist.github.com/Ruthenus/63d013593373e3609f289b0c6896f7bb | |
| short i = 0; | |
| short j = 0; | |
| while (i < M && j < N) { | |
| if (arrayM[i] == arrayN[j]) { | |
| if (common == 0 || arrayCommon[common - 1] != arrayM[i]) { | |
| arrayCommon[common++] = arrayM[i]; | |
| } // уникаємо додавання повторюваних елементів | |
| i++; | |
| j++; | |
| } | |
| else if (arrayM[i] < arrayN[j]) { | |
| i++; | |
| } | |
| else { | |
| j++; | |
| } | |
| } | |
| cout << "Дано два масиви: \n\n"; | |
| for (const auto& element : arrayM) { | |
| cout << element << " "; | |
| } | |
| cout << "\n\n"; | |
| for (const auto& element : arrayN) { | |
| cout << element << " "; | |
| } | |
| cout << "\n\nПерепишемо в третій масив спільні елементи перших двох "; | |
| cout << "масивів без повторень\n\n"; | |
| for (short k = 0; k < common; ++k) { | |
| cout << arrayCommon[k] << " "; | |
| } | |
| cout << "\n\nКількість спільних елементів: " << common << "\n"; | |
| // ПРОБЛЕМЫ НЕ НАЙДЕНЫ | |
| // БУЛО І ТАКЕ для M = 50'000 та N = 70'000: | |
| // Функция использует байты стека "1360028". | |
| // Рассмотрите возможность перемещения некоторых данных в кучу. | |
| cout << "\n" << string(80, '-') << "\n"; | |
| return 0; | |
| } | |
| // КІНЕЦЬ КОДУ ЗАДАЧІ | |
| // Завдання на двовимірні масиви (3 задачі) | |
| // ПОЧАТОК КОДУ ЗАДАЧІ | |
| // 9. Заповнити тривимірний масив N x N x N нулями. У отриманий куб | |
| // вписати кулю, що складається з одиниць. Після цього розрізати куб | |
| // на N шарів і показати кожен шар у вигляді двовимірного масиву | |
| // N x N на екрані консолі. | |
| int main() | |
| { | |
| SetConsoleOutputCP(1251); | |
| cout << "\tЗАВДАННЯ II.9\n\n"; | |
| // Створюємо тривимірний масив нулів типорозміру "куб": | |
| const int N = 50; // щось здається, більше С++ не витримає... | |
| int kub[N][N][N]{}; | |
| // Оголошуємо відповідно центр куба та радіус кулі, вписаної в куб: | |
| float o; | |
| float r; | |
| // Розташування центра куба залежить від парності N: | |
| if (N % 2 == 0) { | |
| // Для парного N геометричний центр знаходиться поміж двома | |
| // центральними елементами (24 і 25 в разі нумерації від нуля): | |
| o = (N / 2.0) - 0.5; // для N = 50 буде center = 24,5 | |
| } | |
| else { | |
| // Для непарного N центр співпадає з центральним елементом: | |
| o = N / 2.0; // для масива з N = 49 center = 24 | |
| } | |
| // Оскільки нумерація від нуля, то радіус кулі | |
| r = o; | |
| // Для кожної точки куба перевіряємо, чи належить вона кулі, | |
| // https://ua.onlinemschool.com/math/formula/sphere/ | |
| // застосовуючи відоме зі школи рівняння сфери: | |
| for (int x = 0; x < N; ++x) { | |
| for (int y = 0; y < N; ++y) { | |
| for (int z = 0; z < N; ++z) { | |
| if (pow(x - o, 2) + pow(y - o, 2) + pow(z - o, 2) <= r * r) { | |
| kub[x][y][z] = 1; // щодо { 1 } див. умову задачі | |
| } | |
| } | |
| } | |
| } | |
| // Розрізаємо куб на N шарів вздовж осі x, виводимо на консоль: | |
| for (int x = 0; x < N; ++x) { | |
| cout << "\nШар " << x + 1 << "\t\tБАНЗАЙ!\n\n"; | |
| for (int y = 0; y < N; ++y) { | |
| for (int z = 0; z < N; ++z) { | |
| cout << kub[x][y][z] << " "; | |
| } | |
| cout << "\n"; | |
| } | |
| cout << "\n"; | |
| } | |
| cout << "\n" << string(80, '-') << "\n"; | |
| return 0; | |
| } | |
| // Функция использует байты стека "500036". Рассмотрите возможность | |
| // перемещения некоторых данных в кучу. ЗАТЕ ХАЙ ЖИВЕ ЯПОНІЯ! | |
| // КІНЕЦЬ КОДУ ЗАДАЧІ | |
| // ПОЧАТОК КОДУ ЗАДАЧІ | |
| // 10. Реалізувати перетворення двовимірного масиву в одновимірний | |
| // і навпаки. | |
| int main() | |
| { | |
| SetConsoleOutputCP(1251); | |
| cout << "\tЗАВДАННЯ II.10\n\n"; | |
| // Ініціалізація двовимірного та одновимірного масивів: | |
| const int ROWS = 23; | |
| const int COLUMNS = 14; | |
| int array2D[ROWS][COLUMNS]{}; | |
| int array1D[ROWS * COLUMNS]{}; | |
| int arrayAgain2D[ROWS][COLUMNS]; // Make Array 2Dimensions Again | |
| // Наповнюємо вихідний двовимірний масив випадковими цілими | |
| // числами від 0 до 99, використовуючи вирівнювання під час виводу: | |
| srand(time(0)); | |
| cout << "Дано двовимірний масив: \n\n"; | |
| for (int i = 0; i < ROWS; ++i) { | |
| for (int j = 0; j < COLUMNS; ++j) { | |
| array2D[i][j] = rand() % 100; | |
| cout << setw(5) << array2D[i][j]; | |
| } | |
| cout << "\n"; | |
| } | |
| cout << "\n\n"; | |
| // У двовимірному масиві ROWS * COLUMNS елементів. | |
| // В одновимірному масиві елементи будуть слідувати рядок за рядком, | |
| // вони матимуть індексацію від 0 до ROWS * COLUMNS - 1. Припустимо. | |
| // Номер рядка двовимірного масиву, звідки береться i-й елемент | |
| // одновимірного, має свідчити скільки рядків заповнено повністю. | |
| // Тоді номер стовпця – це кількість елементів, розташованих після | |
| // крайнього повністю заповненого рядка, мінус один. | |
| // Перетворення двовимірного масиву в одновимірний за один цикл! | |
| cout << "Перетворимо в одновимірний масив рядок за рядком: \n\n"; | |
| for (int i = 0; i < ROWS * COLUMNS; ++i) { | |
| array1D[i] = array2D[i / COLUMNS][i % COLUMNS]; | |
| cout << setw(4) << array1D[i]; | |
| } | |
| // А якщо перетворення стовпець за стовпцем, то | |
| // array1D[i] = array2D[i % ROWS][i / ROWS]; | |
| cout << "\n\n\n"; | |
| // Відновлення двовимірного масиву з одновимірного: | |
| cout << "Зробимо масив двовимірним знову : \n\n"; | |
| for (int i = 0; i < ROWS * COLUMNS; ++i) { | |
| arrayAgain2D[i / COLUMNS][i % COLUMNS] = array1D[i]; | |
| } | |
| for (int i = 0; i < ROWS; ++i) { | |
| for (int j = 0; j < COLUMNS; ++j) { | |
| cout << setw(5) << arrayAgain2D[i][j]; | |
| } | |
| cout << "\n"; | |
| } | |
| cout << "\n" << string(80, '-') << "\n"; | |
| return 0; | |
| } | |
| // КІНЕЦЬ КОДУ ЗАДАЧІ | |
| // ПОЧАТОК КОДУ ЗАДАЧІ | |
| // 8. Заповнити квадратну матрицю розміром N x N по спіралі. | |
| // Число 1 ставиться в центр матриці, а потім масив заповнюється по | |
| // спіралі проти годинникової стрілки значеннями за зростанням. | |
| int main() | |
| { | |
| SetConsoleOutputCP(1251); | |
| cout << "\tЗАВДАННЯ II.8\n\n"; | |
| // Цікаво, чи можна задавати розмір матриці випадковим числом... | |
| const int N = 29; // краще задати непарне N | |
| int matrix[N][N]{}; // матриця квадратна, заповнена нулями | |
| int x; // номер стовпця | |
| int y; // номер рядка | |
| // Напрямки руху за спіраллю проти годинникової стрілки: | |
| // Кожен елемент задає пару змін {dy, dx}, де dy – зсув по рядку, | |
| // а dx – зсув по стовпцю. | |
| int counterClockWise[4][2]{ | |
| {-1, 0}, // Вгору: рядок (y) зменшується на одиницю, | |
| // стовпець (x) залишається незмінним. | |
| {0, -1}, // Ліворуч: стовпець (x) зменшується на одиницю, | |
| // рядок (y) незмінний. | |
| {1, 0}, // Вниз: рядок (y) збільшується на одиницю, | |
| // стовпець (x) незмінний. | |
| {0, 1} // Праворуч: стовпець (x) збільшується | |
| // на одиницю, рядок (y) незмінний. | |
| }; | |
| // За умовою задачі число 1 розміщуємо в центрі матриці: | |
| x = N / 2; // звісно, виникає питання парності або непарності N | |
| y = N / 2; | |
| matrix[y][x] = 1; | |
| // У разі парного N центр матриці не визначено однозначно, тому | |
| // застосовуємо цілочисельне ділення, що вибирає один із центрів. | |
| // Ініціалізація поточного напрямку руху: 0 – вгору (12 година) | |
| int direction = 0; // 1: вліво, 2: вниз, 3: праворуч | |
| // Наступне число, яке буде заповнювати матрицю: | |
| int number = 2; | |
| // Поточна кількість кроків у заданому напрямку перед поворотом | |
| int steps = 1; | |
| // Кількість вже заповнених клітинок (спочатку лише центральна) | |
| int filled = 1; | |
| // Заповнюємо матрицю числами від 2 до N * N – квадрата її розміру: | |
| while (filled < N * N) { | |
| // Виконуємо задану кількість кроків у поточному напрямку | |
| for (int i = 0; i < steps && filled < N * N; ++i) { | |
| // Координати наступної позиції за поточним напрямком | |
| x += counterClockWise[direction][1]; | |
| y += counterClockWise[direction][0]; | |
| // Перевіряємо, чи наступна позиція існує в межах матриці | |
| if (x >= 0 && x < N && y >= 0 && y < N) { | |
| matrix[y][x] = number++; // Записуємо наступне число | |
| filled++; // Збільшуємо лічильник заповнених клітинок | |
| } | |
| } | |
| // Змінюємо напрямок руху на наступний, обертаючи | |
| // проти годинникової стрілки | |
| direction = (direction + 1) % 4; | |
| // І НАЙГОЛОВНІШЕ! | |
| // Збільшуємо кількість кроків після кожних двох поворотів | |
| // (щоб спіраль рівномірно розширювалась!) | |
| if (direction % 2 == 0) { | |
| steps++; | |
| } | |
| } | |
| // Врешті-решт, виводимо отриману матрицю з вирівнюванням: | |
| for (int i = 0; i < N; ++i) { | |
| for (int j = 0; j < N; ++j) { | |
| cout << setw(4) << matrix[i][j]; | |
| } | |
| cout << "\n"; | |
| } | |
| cout << "\n" << string(80, '-') << "\n"; | |
| return 0; | |
| } | |
| // КІНЕЦЬ КОДУ ЗАДАЧІ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment