From 1f07f72216dda85ff97134f6d012940a19e507f5 Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Wed, 25 Sep 2024 23:53:28 +0300 Subject: [PATCH 01/23] Homework 3 task 1 --- .gitignore | 2 + .gitmodules | 3 ++ .vscode/settings.json | 7 ++- build.sh | 65 ++++++++++++++++++++++ ctest | 1 + homework_3/task_1/CMakeLists.txt | 10 ++++ homework_3/task_1/frequencySearch.c | 84 +++++++++++++++++++++++++++++ homework_3/task_1/frequencySearch.h | 5 ++ homework_3/task_1/main.c | 36 +++++++++++++ homework_3/task_1/test.c | 47 ++++++++++++++++ 10 files changed, 258 insertions(+), 2 deletions(-) create mode 100644 .gitmodules create mode 100644 build.sh create mode 160000 ctest create mode 100644 homework_3/task_1/CMakeLists.txt create mode 100644 homework_3/task_1/frequencySearch.c create mode 100644 homework_3/task_1/frequencySearch.h create mode 100644 homework_3/task_1/main.c create mode 100644 homework_3/task_1/test.c diff --git a/.gitignore b/.gitignore index ced2ef2..efc4663 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ *.out .vscode/launch.json .vscode/tasks.json +build/ +config.txt diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..ca6f5a2 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ctest"] + path = ctest + url = https://github.com/bvdberg/ctest.git diff --git a/.vscode/settings.json b/.vscode/settings.json index 772ea16..94bc40c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,7 +9,10 @@ "**/CVS": true, "**/.DS_Store": true, "**/Thumbs.db": true, - "**/*.exe": true, "**/*.out": true, - } + }, + "C_Cpp.formatting": "vcFormat", + "C_Cpp.vcFormat.newLine.beforeElse": false, + "C_Cpp.vcFormat.newLine.beforeOpenBrace.block": "ignore", + "C_Cpp.vcFormat.space.pointerReferenceAlignment": "ignore", } diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..16ce916 --- /dev/null +++ b/build.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +cmake='undefined_cmake' +compiler='undefined_compiler' +generator='undefined_generator' +executable_extension='undefined_executable_extension' + +while IFS="=" read -r var value; do + case $var in + cmake) + cmake=$value + ;; + compiler) + compiler=$value + ;; + generator) + generator=$value + ;; + executable_extension) + executable_extension=$value + ;; + esac +done < config.txt +unset IFS + +function build { + echo "dir: $1" + echo "target: $2" + $cmake -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_C_COMPILER:FILEPATH=$compiler -S$1 -B./build -G "$generator" + $cmake --build ./build --config Debug --target $2 -j 14 +} + +function run { + build $1 $(basename -- "$1") + ./build/$(basename -- "$1")$executable_extension +} + +function buildTest { + target=$(basename -- "$1")_test + build $1 $target +} + +function test { + target=$(basename -- "$1")_test + build $1 $target + ./build/$target$executable_extension +} + +case $1 in + build) + build $2 + ;; + run) + run $2 + ;; + buildTest) + buildTest $2 + ;; + test) + test $2 + ;; + clear) + rm -rf ./build + ;; +esac diff --git a/ctest b/ctest new file mode 160000 index 0000000..718717c --- /dev/null +++ b/ctest @@ -0,0 +1 @@ +Subproject commit 718717ccded8b1a7a96283df9d902f46c9a16d1d diff --git a/homework_3/task_1/CMakeLists.txt b/homework_3/task_1/CMakeLists.txt new file mode 100644 index 0000000..9177d45 --- /dev/null +++ b/homework_3/task_1/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.20) +project(task_1) + +add_library(frequencySearch frequencySearch.c) + +add_executable(${PROJECT_NAME} main.c) +target_link_libraries(${PROJECT_NAME} frequencySearch) + +add_executable(${PROJECT_NAME}_test test.c) +target_link_libraries(${PROJECT_NAME}_test PRIVATE frequencySearch) diff --git a/homework_3/task_1/frequencySearch.c b/homework_3/task_1/frequencySearch.c new file mode 100644 index 0000000..2d457ad --- /dev/null +++ b/homework_3/task_1/frequencySearch.c @@ -0,0 +1,84 @@ +#include "frequencySearch.h" + +#include +#include + +int partition(int *array, int left, int right) { + int first = array[left], middle = array[(left + right) / 2], last = array[right]; + + int pivot = first; + if (first <= middle && middle <= last) { + pivot = middle; + } else if (middle <= first && first <= last) { + pivot = first; + } else { + pivot = last; + } + + --left; + ++right; + + while (true) { + do { + ++left; + } while (array[left] < pivot); + do { + --right; + } while (array[right] > pivot); + + if (left >= right) break; + + int t = array[left]; + array[left] = array[right]; + array[right] = t; + } + + return right; +} + +void quickSort(int *array, int left, int right) { + if (left >= right) { + return; + } + + int part = partition(array, left, right); + quickSort(array, left, part); + quickSort(array, part + 1, right); +} + +bool findMostFrequentElement(int *array, int arrayLength, int *mostFrequentElement, int *occurrences) { + if (arrayLength == 0) { + return false; + } + + quickSort(array, 0, arrayLength - 1); + + int element = array[0], count = 0; + int maxCountElement = element, maxCount = count; + + for (int i = 0; i < arrayLength; ++i) { + if (array[i] != element) { + if (count > maxCount) { + maxCount = count; + maxCountElement = element; + } + count = 0; + element = array[i]; + } + ++count; + } + + if (count > maxCount) { + maxCount = count; + maxCountElement = element; + } + + if (mostFrequentElement != NULL) { + *mostFrequentElement = maxCountElement; + } + if (occurrences != NULL) { + *occurrences = maxCount; + } + + return true; +} diff --git a/homework_3/task_1/frequencySearch.h b/homework_3/task_1/frequencySearch.h new file mode 100644 index 0000000..f087b91 --- /dev/null +++ b/homework_3/task_1/frequencySearch.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +bool findMostFrequentElement(int *array, int arrayLength, int *mostFrequentElement, int *occurrences); diff --git a/homework_3/task_1/main.c b/homework_3/task_1/main.c new file mode 100644 index 0000000..0426d61 --- /dev/null +++ b/homework_3/task_1/main.c @@ -0,0 +1,36 @@ +#include +#include +#include + +#include "frequencySearch.h" + +void randomizeArray(int *array, int arrayLength, int minValue, int maxValue) { + for (int i = 0; i < arrayLength; ++i) { + array[i] = rand() * (maxValue - minValue) / RAND_MAX + minValue; + } +} + +int readValue(const char *prompt, const char *incorrectValueMessage) { + int value; + printf(prompt); + while ((scanf("%d", &value) != 1) || value < 0) { + while (getchar() != '\n') {} + printf(incorrectValueMessage); + } +} + +int main(void) { + int arrayLength = readValue("enter array length: ", "incorrect value: array length cannot be less than zero; try again: "); + + int *array = calloc(arrayLength, sizeof(int)); + + srand(time(NULL)); + randomizeArray(array, arrayLength, 0, 128); + + int mostFrequentElement = 0, occurrences = 0; + if (findMostFrequentElement(array, arrayLength, &mostFrequentElement, &occurrences)) { + printf("most frequent element is %d; it appears %d times in array", mostFrequentElement, occurrences); + } else { + printf("unknown error\n"); + } +} diff --git a/homework_3/task_1/test.c b/homework_3/task_1/test.c new file mode 100644 index 0000000..8156978 --- /dev/null +++ b/homework_3/task_1/test.c @@ -0,0 +1,47 @@ +#define CTEST_MAIN +#define CTEST_SEGFAULT +#include "../../ctest/ctest.h" + +#include + +#include "frequencySearch.h" + +int main(int argc, const char *argv[]) { + return ctest_main(argc, argv); +} + +CTEST(frequencySearchTests, emptyArrayTest) { + ASSERT_FALSE(findMostFrequentElement(NULL, 0, NULL, NULL)); +} + +CTEST(frequencySearchTests, oneElementArrayTest) { +#define size 1 + int array[size] = { 42 }; + int mostFrequentExpected = 42; + int mostFrequentResult = 0; + ASSERT_TRUE(findMostFrequentElement(array, size, &mostFrequentResult, NULL)); + ASSERT_EQUAL(mostFrequentResult, mostFrequentExpected); +#undef size +} + +CTEST(frequencySearchTests, sameElementsArrayTest) { +#define size 8 + int array[size] = { 42, 42, 42, 42, 42, 42, 42, 42 }; + int mostFrequentExpected = 42, occurrencesExpected = size; + int mostFrequentResult = 0, occurrencesResult = 0; + ASSERT_TRUE(findMostFrequentElement(array, size, &mostFrequentResult, &occurrencesResult)); + ASSERT_EQUAL(mostFrequentResult, mostFrequentExpected); + ASSERT_EQUAL(occurrencesResult, occurrencesExpected); +#undef size +} + +CTEST(frequencySearchTests, constantArrayTest) { +#define size 10 + int array[size] = { 1, 2, 3, 3, 3, 7, 9, 12, 8, 3 }; + int mostFrequentExpected = 3, occurrencesExpected = 4; + int mostFrequentResult = 0, occurrencesResult = 0; + ASSERT_TRUE(findMostFrequentElement(array, size, &mostFrequentResult, &occurrencesResult)); + ASSERT_EQUAL(mostFrequentResult, mostFrequentExpected); + ASSERT_EQUAL(occurrencesResult, occurrencesExpected); +#undef size +} From 4600352bf2f56a40fd2c341671312c696f2a377d Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Thu, 26 Sep 2024 18:12:08 +0300 Subject: [PATCH 02/23] Fixed build script --- build.sh | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/build.sh b/build.sh index 16ce916..02f97cd 100644 --- a/build.sh +++ b/build.sh @@ -23,26 +23,28 @@ while IFS="=" read -r var value; do done < config.txt unset IFS -function build { - echo "dir: $1" - echo "target: $2" +function buildInternal { $cmake -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_C_COMPILER:FILEPATH=$compiler -S$1 -B./build -G "$generator" $cmake --build ./build --config Debug --target $2 -j 14 } +function build { + buildInternal $1 $(basename -- "$1") +} + function run { - build $1 $(basename -- "$1") + buildInternal $1 $(basename -- "$1") ./build/$(basename -- "$1")$executable_extension } function buildTest { target=$(basename -- "$1")_test - build $1 $target + buildInternal $1 $target } function test { target=$(basename -- "$1")_test - build $1 $target + buildInternal $1 $target ./build/$target$executable_extension } From d81ef994577ab223afec9fccbd015b437256fe85 Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Thu, 26 Sep 2024 18:15:00 +0300 Subject: [PATCH 03/23] Homework 3 task 2 --- homework_3/task_2/CMakeLists.txt | 10 +++++ homework_3/task_2/main.c | 47 ++++++++++++++++++++ homework_3/task_2/sortAndSearch.c | 74 +++++++++++++++++++++++++++++++ homework_3/task_2/sortAndSearch.h | 8 ++++ homework_3/task_2/test.c | 47 ++++++++++++++++++++ 5 files changed, 186 insertions(+) create mode 100644 homework_3/task_2/CMakeLists.txt create mode 100644 homework_3/task_2/main.c create mode 100644 homework_3/task_2/sortAndSearch.c create mode 100644 homework_3/task_2/sortAndSearch.h create mode 100644 homework_3/task_2/test.c diff --git a/homework_3/task_2/CMakeLists.txt b/homework_3/task_2/CMakeLists.txt new file mode 100644 index 0000000..bdeb9ad --- /dev/null +++ b/homework_3/task_2/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.20) +project(task_2) + +add_library(sortAndSearch sortAndSearch.c) + +add_executable(${PROJECT_NAME} main.c) +target_link_libraries(${PROJECT_NAME} sortAndSearch) + +add_executable(${PROJECT_NAME}_test test.c) +target_link_libraries(${PROJECT_NAME}_test PRIVATE sortAndSearch) diff --git a/homework_3/task_2/main.c b/homework_3/task_2/main.c new file mode 100644 index 0000000..38246f3 --- /dev/null +++ b/homework_3/task_2/main.c @@ -0,0 +1,47 @@ +#include +#include +#include + +#include "sortAndSearch.h" + +int getRandom(int minValue, int maxValue) { + int r = rand(); + return r * (maxValue - minValue) / RAND_MAX + minValue; +} + +int readValue(const char *prompt, const char *incorrectValueMessage) { + int value; + printf(prompt); + while ((scanf("%d", &value) != 1) || value < 0) { + while (getchar() != '\n') {} + printf(incorrectValueMessage); + } +} + +int main(void) { + int arrayLength = readValue("enter array length: ", "incorrect value: array length cannot be less than zero; try again: "); + int numbersToCheckCount = readValue("enter amount of numbers to check: ", "incorrect value: amount cannot be less than zero; try again: "); + + int *array = calloc(arrayLength, sizeof(int)); + + int minRandom = 0, + maxRandom = 128; + + srand(time(NULL)); + + for (int i = 0; i < arrayLength; ++i) { + array[i] = getRandom(minRandom, maxRandom); + } + + quickSort(array, arrayLength); + + int foundNumbers = 0; + for (int i = 0; i < numbersToCheckCount; ++i) { + int number = getRandom(minRandom, maxRandom); + if (containsElement(array, arrayLength, number)) { + ++foundNumbers; + } + } + + printf("out of %d randomly generated numbers %d %s in the array\n", numbersToCheckCount, foundNumbers, foundNumbers == 1 ? "was" : "were"); +} diff --git a/homework_3/task_2/sortAndSearch.c b/homework_3/task_2/sortAndSearch.c new file mode 100644 index 0000000..ce55731 --- /dev/null +++ b/homework_3/task_2/sortAndSearch.c @@ -0,0 +1,74 @@ +#include "sortAndSearch.h" + +#include +#include + +int partition(int *array, int left, int right) { + int first = array[left], middle = array[(left + right) / 2], last = array[right]; + + int pivot = first; + if (first <= middle && middle <= last) { + pivot = middle; + } else if (middle <= first && first <= last) { + pivot = first; + } else { + pivot = last; + } + + --left; + ++right; + + while (true) { + do { + ++left; + } while (array[left] < pivot); + do { + --right; + } while (array[right] > pivot); + + if (left >= right) break; + + int t = array[left]; + array[left] = array[right]; + array[right] = t; + } + + return right; +} + +void quickSortInternal(int *array, int left, int right) { + if (left >= right) { + return; + } + + int part = partition(array, left, right); + quickSortInternal(array, left, part); + quickSortInternal(array, part + 1, right); +} + +void quickSort(int *array, int arrayLength) { + quickSortInternal(array, 0, arrayLength - 1); +} + +bool containsElement(int *array, int arrayLength, int value) { + if (arrayLength == 0) { + return false; + } + + int left = 0, right = arrayLength - 1; + + while (left <= right) { + int middlePoint = (left + right) / 2, + middleElement = array[middlePoint]; + + if (value < middleElement) { + right = middlePoint - 1; + } else if (value > middleElement) { + left = middlePoint + 1; + } else { + return true; + } + } + + return array[left] == value; +} diff --git a/homework_3/task_2/sortAndSearch.h b/homework_3/task_2/sortAndSearch.h new file mode 100644 index 0000000..274dd08 --- /dev/null +++ b/homework_3/task_2/sortAndSearch.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +void quickSort(int *array, int arrayLength); + +/// array must be sorted before calling this function +bool containsElement(int *array, int arrayLength, int value); diff --git a/homework_3/task_2/test.c b/homework_3/task_2/test.c new file mode 100644 index 0000000..ef69a27 --- /dev/null +++ b/homework_3/task_2/test.c @@ -0,0 +1,47 @@ +#define CTEST_MAIN +#define CTEST_SEGFAULT +#include "../../ctest/ctest.h" + +#include + +#include "sortAndSearch.h" + +int main(int argc, const char *argv[]) { + return ctest_main(argc, argv); +} + +CTEST(binSearchTests, emptyArrayTest) { + ASSERT_FALSE(containsElement(NULL, 0, 0)); +} + +CTEST(binSearchTests, oneElementArrayTest) { +#define size 1 + int array[size] = { 42 }; + ASSERT_TRUE(containsElement(array, size, 42)); + ASSERT_FALSE(containsElement(array, size, 21)); +#undef size +} + +CTEST(binSearchTests, sameElementsArrayTest) { +#define size 8 + int array[size] = { 42, 42, 42, 42, 42, 42, 42, 42 }; + + ASSERT_TRUE(containsElement(array, size, 42)); + ASSERT_FALSE(containsElement(array, size, 21)); +#undef size +} + +CTEST(binSearchTests, constantArrayTest) { +#define size 10 + int array[size] = { 1, 2, 3, 7, 10, 13, 15, 16, 19, 20 }; + for (int i = 0; i < size; ++i) { + ASSERT_TRUE(containsElement(array, size, array[i])); + } + ASSERT_FALSE(containsElement(array, size, 0)); + ASSERT_FALSE(containsElement(array, size, -1)); + ASSERT_FALSE(containsElement(array, size, -4)); + ASSERT_FALSE(containsElement(array, size, 40)); + ASSERT_FALSE(containsElement(array, size, 50)); + ASSERT_FALSE(containsElement(array, size, 70)); +#undef size +} From 83ce46616c261d1230a5d929959186379f39f8fb Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Thu, 26 Sep 2024 19:13:12 +0300 Subject: [PATCH 04/23] Homework 3 task 3 --- homework_3/task_3/CMakeLists.txt | 10 +++++ homework_3/task_3/main.c | 45 +++++++++++++++++++ homework_3/task_3/smartQSort.c | 77 ++++++++++++++++++++++++++++++++ homework_3/task_3/smartQSort.h | 6 +++ homework_3/task_3/test.c | 67 +++++++++++++++++++++++++++ 5 files changed, 205 insertions(+) create mode 100644 homework_3/task_3/CMakeLists.txt create mode 100644 homework_3/task_3/main.c create mode 100644 homework_3/task_3/smartQSort.c create mode 100644 homework_3/task_3/smartQSort.h create mode 100644 homework_3/task_3/test.c diff --git a/homework_3/task_3/CMakeLists.txt b/homework_3/task_3/CMakeLists.txt new file mode 100644 index 0000000..6e25c06 --- /dev/null +++ b/homework_3/task_3/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.20) +project(task_3) + +add_library(smartQSort smartQSort.c) + +add_executable(${PROJECT_NAME} main.c) +target_link_libraries(${PROJECT_NAME} smartQSort) + +add_executable(${PROJECT_NAME}_test test.c) +target_link_libraries(${PROJECT_NAME}_test PRIVATE smartQSort) diff --git a/homework_3/task_3/main.c b/homework_3/task_3/main.c new file mode 100644 index 0000000..fe3900c --- /dev/null +++ b/homework_3/task_3/main.c @@ -0,0 +1,45 @@ +#include +#include +#include + +#include "smartQSort.h" + +void randomizeArray(int *array, int arrayLength, int minValue, int maxValue) { + for (int i = 0; i < arrayLength; ++i) { + array[i] = rand() * (maxValue - minValue) / RAND_MAX + minValue; + } +} + +int readValue(const char *prompt, const char *incorrectValueMessage) { + int value; + printf(prompt); + while ((scanf("%d", &value) != 1) || value < 0) { + while (getchar() != '\n') {} + printf(incorrectValueMessage); + } +} + +long long measureTime(void (*sort)(int *, int), int *array, int arrayLength) { + struct timespec startTime, endTime; + clock_gettime(CLOCK_MONOTONIC, &startTime); + sort(array, arrayLength); + clock_gettime(CLOCK_MONOTONIC, &endTime); + return (endTime.tv_nsec - startTime.tv_nsec) + (endTime.tv_sec - startTime.tv_sec) * 1000 * 1000 * 1000; +} + +int main(void) { + int arrayLength = readValue("enter array length: ", "incorrect value: array length cannot be less than zero; try again: "); + + int *array = calloc(arrayLength, sizeof(int)); + + srand(time(NULL)); + randomizeArray(array, arrayLength, 0, 128); + + printf("qsort: %.2f ms\n", measureTime(quickSort, array, arrayLength) / 1000.0 / 1000.0); + + randomizeArray(array, arrayLength, 0, 128); + + printf("smart qsort: %.2f ms\n", measureTime(smartQuickSort, array, arrayLength) / 1000.0 / 1000.0); + + free(array); +} diff --git a/homework_3/task_3/smartQSort.c b/homework_3/task_3/smartQSort.c new file mode 100644 index 0000000..48147ec --- /dev/null +++ b/homework_3/task_3/smartQSort.c @@ -0,0 +1,77 @@ +#include "smartQSort.h" + +void insertionSort(int *array, int left, int right) { + for (int i = left + 1; i <= right; ++i) { + for (int j = i - 1; j >= left; --j) { + if (array[j] <= array[j + 1]) { + break; + } + + int temp = array[j]; + array[j] = array[j + 1]; + array[j + 1] = temp; + } + } +} + +int partition(int *array, int left, int right) { + int first = array[left], middle = array[(left + right) / 2], last = array[right]; + + int pivot = first; + if (first <= middle && middle <= last) { + pivot = middle; + } else if (middle <= first && first <= last) { + pivot = first; + } else { + pivot = last; + } + + --left; + ++right; + + while (true) { + do { + ++left; + } while (array[left] < pivot); + do { + --right; + } while (array[right] > pivot); + + if (left >= right) break; + + int t = array[left]; + array[left] = array[right]; + array[right] = t; + } + + return right; +} + +void quickSortInternal(int *array, int left, int right) { + if (left >= right) { + return; + } + + int part = partition(array, left, right); + quickSortInternal(array, left, part); + quickSortInternal(array, part + 1, right); +} + +void smartQuickSortInternal(int *array, int left, int right) { + if (right - left + 1 <= 10) { + insertionSort(array, left, right); + return; + } + + int part = partition(array, left, right); + smartQuickSortInternal(array, left, part); + smartQuickSortInternal(array, part + 1, right); +} + +void quickSort(int *array, int arrayLength) { + quickSortInternal(array, 0, arrayLength - 1); +} + +void smartQuickSort(int *array, int arrayLength) { + smartQuickSortInternal(array, 0, arrayLength - 1); +} diff --git a/homework_3/task_3/smartQSort.h b/homework_3/task_3/smartQSort.h new file mode 100644 index 0000000..465bedf --- /dev/null +++ b/homework_3/task_3/smartQSort.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +void quickSort(int *array, int arrayLength); +void smartQuickSort(int *array, int arrayLength); diff --git a/homework_3/task_3/test.c b/homework_3/task_3/test.c new file mode 100644 index 0000000..259f877 --- /dev/null +++ b/homework_3/task_3/test.c @@ -0,0 +1,67 @@ +#define CTEST_MAIN +#define CTEST_SEGFAULT +#include "../../ctest/ctest.h" + +#include +#include + +#include "smartQSort.h" + +int main(int argc, const char *argv[]) { + return ctest_main(argc, argv); +} + +void assertSorted(int *array, int arrayLength) { + for (int i = 1; i < arrayLength; ++i) { + ASSERT_GE(array[i], array[i - 1]); + } +} + +void sortAndAssert(int *array, int arrayLength) { + smartQuickSort(array, arrayLength); + + for (int i = 1; i < arrayLength; ++i) { + ASSERT_GE(array[i], array[i - 1]); + } +} + +void randomizeArray(int *array, int arrayLength, int minValue, int maxValue) { + for (int i = 0; i < arrayLength; ++i) { + array[i] = rand() * (maxValue - minValue) / RAND_MAX + minValue; + } +} + +CTEST(smartQSortTests, emptyArrayTest) { + smartQuickSort(NULL, 0); +} + +CTEST(smartQSortTests, oneElementArrayTest) { +#define size 1 + int array[size] = { 24 }; + sortAndAssert(array, size); +#undef size +} + +CTEST(smartQSortTests, sameElementsArrayTest) { +#define size 8 + int array[size] = { 31, 31, 31, 31, 31, 31, 31, 31 }; + sortAndAssert(array, size); +#undef size +} + +CTEST(smartQSortTests, constantArrayTest) { +#define size 10 + int array[size] = { 23, 12, 4, 35, 20, -15, 17, 8, 19, 40 }; + sortAndAssert(array, size); +#undef size +} + +CTEST(smartQSortTests, randomArrayTest) { +#define size 100 + int array[size]; + + randomizeArray(array, size, -128, 128); + + sortAndAssert(array, size); +#undef size +} From abd4185bf0bc59d7407bf6c9586e5fbe1e9691a9 Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Thu, 26 Sep 2024 19:14:13 +0300 Subject: [PATCH 05/23] Added free() to task 1 and task 2 --- homework_3/task_1/main.c | 2 ++ homework_3/task_2/main.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/homework_3/task_1/main.c b/homework_3/task_1/main.c index 0426d61..16b7af4 100644 --- a/homework_3/task_1/main.c +++ b/homework_3/task_1/main.c @@ -33,4 +33,6 @@ int main(void) { } else { printf("unknown error\n"); } + + free(array); } diff --git a/homework_3/task_2/main.c b/homework_3/task_2/main.c index 38246f3..28819c8 100644 --- a/homework_3/task_2/main.c +++ b/homework_3/task_2/main.c @@ -44,4 +44,6 @@ int main(void) { } printf("out of %d randomly generated numbers %d %s in the array\n", numbersToCheckCount, foundNumbers, foundNumbers == 1 ? "was" : "were"); + + free(array); } From d1ce705d6479f969e9c7e348deaf94b2a4c62c62 Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Thu, 26 Sep 2024 19:20:04 +0300 Subject: [PATCH 06/23] Use same array to compare sortings in hw3 t3 --- homework_3/task_3/main.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/homework_3/task_3/main.c b/homework_3/task_3/main.c index fe3900c..11808c4 100644 --- a/homework_3/task_3/main.c +++ b/homework_3/task_3/main.c @@ -30,16 +30,18 @@ long long measureTime(void (*sort)(int *, int), int *array, int arrayLength) { int main(void) { int arrayLength = readValue("enter array length: ", "incorrect value: array length cannot be less than zero; try again: "); - int *array = calloc(arrayLength, sizeof(int)); + int *arrayA = calloc(arrayLength, sizeof(int)), + *arrayB = calloc(arrayLength, sizeof(int)); srand(time(NULL)); - randomizeArray(array, arrayLength, 0, 128); + randomizeArray(arrayA, arrayLength, 0, 1024); + arrayB = memcpy(arrayB, arrayA, arrayLength * sizeof(int)); - printf("qsort: %.2f ms\n", measureTime(quickSort, array, arrayLength) / 1000.0 / 1000.0); - - randomizeArray(array, arrayLength, 0, 128); + srand(time(NULL)); - printf("smart qsort: %.2f ms\n", measureTime(smartQuickSort, array, arrayLength) / 1000.0 / 1000.0); + printf("qsort: %.2f ms\n", measureTime(quickSort, arrayA, arrayLength) / 1000.0 / 1000.0); + printf("smart qsort: %.2f ms\n", measureTime(smartQuickSort, arrayB, arrayLength) / 1000.0 / 1000.0); - free(array); + free(arrayA); + free(arrayB); } From b8cd913f4c97c590a18f82369b6fd5311ef0ad58 Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Thu, 26 Sep 2024 19:21:35 +0300 Subject: [PATCH 07/23] Removed unnecessary srand() --- homework_3/task_3/main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/homework_3/task_3/main.c b/homework_3/task_3/main.c index 11808c4..b6dfdf5 100644 --- a/homework_3/task_3/main.c +++ b/homework_3/task_3/main.c @@ -37,8 +37,6 @@ int main(void) { randomizeArray(arrayA, arrayLength, 0, 1024); arrayB = memcpy(arrayB, arrayA, arrayLength * sizeof(int)); - srand(time(NULL)); - printf("qsort: %.2f ms\n", measureTime(quickSort, arrayA, arrayLength) / 1000.0 / 1000.0); printf("smart qsort: %.2f ms\n", measureTime(smartQuickSort, arrayB, arrayLength) / 1000.0 / 1000.0); From d6192737119e85d8a58edbeedf1a69587d4e606d Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Thu, 26 Sep 2024 19:26:12 +0300 Subject: [PATCH 08/23] Edited error message in hw3 task 1 --- homework_3/task_1/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homework_3/task_1/main.c b/homework_3/task_1/main.c index 16b7af4..96ed2c5 100644 --- a/homework_3/task_1/main.c +++ b/homework_3/task_1/main.c @@ -31,7 +31,7 @@ int main(void) { if (findMostFrequentElement(array, arrayLength, &mostFrequentElement, &occurrences)) { printf("most frequent element is %d; it appears %d times in array", mostFrequentElement, occurrences); } else { - printf("unknown error\n"); + printf("couldn't find most frequent element: the array is empty\n"); } free(array); From 5e7c6df4c3d94dd81272fd664e223b6899f90ec4 Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Thu, 26 Sep 2024 22:09:04 +0300 Subject: [PATCH 09/23] Overhauled build script --- build.sh | 118 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 88 insertions(+), 30 deletions(-) diff --git a/build.sh b/build.sh index 02f97cd..bbc9264 100644 --- a/build.sh +++ b/build.sh @@ -7,61 +7,119 @@ executable_extension='undefined_executable_extension' while IFS="=" read -r var value; do case $var in - cmake) - cmake=$value - ;; - compiler) - compiler=$value - ;; - generator) - generator=$value - ;; - executable_extension) - executable_extension=$value - ;; + cmake) cmake=$value ;; + compiler) compiler=$value ;; + generator) generator=$value ;; + executable_extension) executable_extension=$value ;; esac done < config.txt unset IFS +if [[ $cmake = 'undefined_command' ]]; then + echo "cmake not specified" + exit 1 +fi + +if [[ $compiler = 'undefined_compiler' ]]; then + echo "compiler not specified" + exit 1 +fi + +if [[ $generator = 'undefined_generator' ]]; then + echo "generator not specified" + exit 1 +fi + +if [[ $executable_extension = 'undefined_executable_extension' ]]; then + echo "warning: executable extension not specified - assuming there is no executable extension" + executable_extension= +fi + function buildInternal { - $cmake -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_C_COMPILER:FILEPATH=$compiler -S$1 -B./build -G "$generator" - $cmake --build ./build --config Debug --target $2 -j 14 + $cmake -DCMAKE_BUILD_TYPE:STRING=$3 -DCMAKE_C_COMPILER:FILEPATH=$compiler -S$1 -B./build -G "$generator" + if [[ $? -ne 0 ]]; then + exit 1 + fi + + $cmake --build ./build --config $3 --target $2 -j 14 + if [[ $? -ne 0 ]]; then + exit 1 + fi } function build { - buildInternal $1 $(basename -- "$1") + buildInternal "$1/$2" $2 $3 } function run { - buildInternal $1 $(basename -- "$1") - ./build/$(basename -- "$1")$executable_extension + buildInternal "$1/$2" $2 $3 + ./build/$2$executable_extension } function buildTest { - target=$(basename -- "$1")_test - buildInternal $1 $target + buildInternal "$1/$2" "$(echo $2)_test" $3 } function test { - target=$(basename -- "$1")_test - buildInternal $1 $target - ./build/$target$executable_extension + buildInternal "$1/$2" "$(echo $2)_test" $3 + ./build/$(echo $2)_test$executable_extension } -case $1 in +configuration='Debug' +command='undefined_command' +while [[ "$#" -gt 0 ]]; do + case $1 in + build | run | buildTest | test) + command="$1" + shift + + if [[ $# -eq 0 ]]; then + echo "no homework folder specified" + exit 1 + fi + + homework="$1" + if [[ ! -d "$homework" ]]; then + echo "homework folder '$homework' not found" + exit 1 + fi + shift + + if [[ $# -eq 0 ]]; then + echo "no task folder specified" + exit 1 + fi + + task="$1" + if [[ ! -d "$homework/$task" ]]; then + echo "task folder '$task' not found in homework folder '$homework'" + exit 1 + fi + ;; + -r|--release) configuration='Release' ;; + -d|--debug) configuration='Debug' ;; + clear) rm -rf ./build; exit 0 ;; + *) echo "unknown argument: $1"; exit 1 ;; + esac + shift +done + +if [[ $command == 'undefined_command' ]]; then + echo "command not specified" + exit 1 +fi + +case $command in build) - build $2 + build $homework $task $configuration ;; run) - run $2 + run $homework $task $configuration ;; buildTest) - buildTest $2 + buildTest $homework $task $configuration ;; test) - test $2 - ;; - clear) - rm -rf ./build + test $homework $task $configuration ;; esac From 8b0c17b355a12abe51a1adf175576f2857e69849 Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Thu, 26 Sep 2024 22:09:32 +0300 Subject: [PATCH 10/23] Added missing string.h to hw3 task 3 --- homework_3/task_3/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/homework_3/task_3/main.c b/homework_3/task_3/main.c index b6dfdf5..57e0763 100644 --- a/homework_3/task_3/main.c +++ b/homework_3/task_3/main.c @@ -1,5 +1,6 @@ #include #include +#include #include #include "smartQSort.h" From 0aff8a683aebc43da069626fcd2c2981b8465e4b Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Fri, 27 Sep 2024 10:40:16 +0300 Subject: [PATCH 11/23] Added clear option to build script --- build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/build.sh b/build.sh index bbc9264..7d8fddb 100644 --- a/build.sh +++ b/build.sh @@ -98,6 +98,7 @@ while [[ "$#" -gt 0 ]]; do ;; -r|--release) configuration='Release' ;; -d|--debug) configuration='Debug' ;; + -c|--clear) rm -rf ./build; ;; clear) rm -rf ./build; exit 0 ;; *) echo "unknown argument: $1"; exit 1 ;; esac From 886d231189ebb03d776d12c653a5d63b7c6a4b32 Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Fri, 27 Sep 2024 23:01:26 +0300 Subject: [PATCH 12/23] Added buildAll and testAll commands --- CMakeLists.txt | 4 ++ build.sh | 101 ++++++++++++++++++++++++++----- homework_3/CMakeLists.txt | 8 +++ homework_3/task_1/CMakeLists.txt | 2 +- homework_3/task_2/CMakeLists.txt | 2 +- homework_3/task_3/CMakeLists.txt | 2 +- 6 files changed, 100 insertions(+), 19 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 homework_3/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c4f6350 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.20) +project(homework) + +add_subdirectory(homework_3) diff --git a/build.sh b/build.sh index 7d8fddb..46c5955 100644 --- a/build.sh +++ b/build.sh @@ -1,5 +1,7 @@ #!/bin/bash +build_dir='build' + cmake='undefined_cmake' compiler='undefined_compiler' generator='undefined_generator' @@ -32,44 +34,103 @@ fi if [[ $executable_extension = 'undefined_executable_extension' ]]; then echo "warning: executable extension not specified - assuming there is no executable extension" - executable_extension= + executable_extension='' fi -function buildInternal { - $cmake -DCMAKE_BUILD_TYPE:STRING=$3 -DCMAKE_C_COMPILER:FILEPATH=$compiler -S$1 -B./build -G "$generator" - if [[ $? -ne 0 ]]; then - exit 1 +# $1: target to build +# $2: configuration +function build_internal { + configure=false + configuration_cache_file="$build_dir/__last_configuration" + last_configuration='none' + if [[ ! -d $build_dir ]]; then + mkdir "$build_dir" + else + if [[ -f $configuration_cache_file ]]; then + last_configuration=$(<$configuration_cache_file) + fi + fi + + if [[ $2 != $last_configuration ]]; then + $cmake -DCMAKE_BUILD_TYPE:STRING=$2 -DCMAKE_C_COMPILER:FILEPATH=$compiler -S . -B "$build_dir" -G "$generator" + if [[ $? -ne 0 ]]; then + exit 1 + fi + + echo $2 > $configuration_cache_file fi - - $cmake --build ./build --config $3 --target $2 -j 14 + + $cmake --build "$build_dir" --config $2 --target $1 -j 14 if [[ $? -ne 0 ]]; then exit 1 fi } +# $1: homework +# $2: task +# $3: target +function run_internal { + build/$1/$2/$3$executable_extension +} + +# build, run, buildTest and test have these arguments: +# $1: homework +# $2: task +# $3: configuration + function build { - buildInternal "$1/$2" $2 $3 + build_internal ${1}_$2 $3 } function run { - buildInternal "$1/$2" $2 $3 - ./build/$2$executable_extension + build $1 $2 $3 + run_internal $1 $2 ${1}_$2 } function buildTest { - buildInternal "$1/$2" "$(echo $2)_test" $3 + build $1 ${2}_test $3 } function test { - buildInternal "$1/$2" "$(echo $2)_test" $3 - ./build/$(echo $2)_test$executable_extension + buildTest $1 $2 $3 + run_internal $1 $2 ${1}_${2}_test +} + +function foreach_homework_and_task { + for homework_dir in */ ; do + if [[ ! $homework_dir =~ ^(homework_.+)/$ ]]; then + continue + fi + + homework=${BASH_REMATCH[1]} + + for task_dir in $homework_dir*/ ; do + if [[ ! $task_dir =~ ^${homework}/(task_.+)/$ ]]; then + continue + fi + + task=${BASH_REMATCH[1]} + + $1 $homework $task $2 + done + done +} + +# $1: configuration +function buildAll { + foreach_homework_and_task build $1 +} + +# $1: configuration +function testAll { + foreach_homework_and_task test $1 } configuration='Debug' command='undefined_command' while [[ "$#" -gt 0 ]]; do case $1 in - build | run | buildTest | test) + build | run | buildTest | test) command="$1" shift @@ -96,10 +157,11 @@ while [[ "$#" -gt 0 ]]; do exit 1 fi ;; + buildAll | testAll) command="$1" ;; -r|--release) configuration='Release' ;; -d|--debug) configuration='Debug' ;; - -c|--clear) rm -rf ./build; ;; - clear) rm -rf ./build; exit 0 ;; + -c|--clear) rm -rf "$build_dir"; ;; + clear) rm -rf "$build_dir"; exit 0 ;; *) echo "unknown argument: $1"; exit 1 ;; esac shift @@ -123,4 +185,11 @@ case $command in test) test $homework $task $configuration ;; + + buildAll) + buildAll $configuration + ;; + testAll) + testAll $configuration + ;; esac diff --git a/homework_3/CMakeLists.txt b/homework_3/CMakeLists.txt new file mode 100644 index 0000000..c8f55b0 --- /dev/null +++ b/homework_3/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.20) +project(homework_3) + +set(homeworkName "${PROJECT_NAME}") + +add_subdirectory(task_1) +add_subdirectory(task_2) +add_subdirectory(task_3) diff --git a/homework_3/task_1/CMakeLists.txt b/homework_3/task_1/CMakeLists.txt index 9177d45..39015e8 100644 --- a/homework_3/task_1/CMakeLists.txt +++ b/homework_3/task_1/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.20) -project(task_1) +project("${homeworkName}_task_1") add_library(frequencySearch frequencySearch.c) diff --git a/homework_3/task_2/CMakeLists.txt b/homework_3/task_2/CMakeLists.txt index bdeb9ad..9ecdce7 100644 --- a/homework_3/task_2/CMakeLists.txt +++ b/homework_3/task_2/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.20) -project(task_2) +project("${homeworkName}_task_2") add_library(sortAndSearch sortAndSearch.c) diff --git a/homework_3/task_3/CMakeLists.txt b/homework_3/task_3/CMakeLists.txt index 6e25c06..acfee86 100644 --- a/homework_3/task_3/CMakeLists.txt +++ b/homework_3/task_3/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.20) -project(task_3) +project("${homeworkName}_task_3") add_library(smartQSort smartQSort.c) From 0d5b00b5f8387601db25240027807720f4b193c4 Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Sat, 28 Sep 2024 00:15:57 +0300 Subject: [PATCH 13/23] Change directory to task's one when running/testing --- build.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.sh b/build.sh index 46c5955..a99153e 100644 --- a/build.sh +++ b/build.sh @@ -70,7 +70,10 @@ function build_internal { # $2: task # $3: target function run_internal { + return_to=$pwd + cd $1/$2 build/$1/$2/$3$executable_extension + cd $return_to } # build, run, buildTest and test have these arguments: From 3d0de98b667d60602e09d7b8c94d23af49b82654 Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Sat, 28 Sep 2024 00:17:49 +0300 Subject: [PATCH 14/23] Removed minimal version requirement --- homework_3/CMakeLists.txt | 1 - homework_3/task_1/CMakeLists.txt | 1 - homework_3/task_2/CMakeLists.txt | 1 - homework_3/task_3/CMakeLists.txt | 1 - 4 files changed, 4 deletions(-) diff --git a/homework_3/CMakeLists.txt b/homework_3/CMakeLists.txt index c8f55b0..f445d32 100644 --- a/homework_3/CMakeLists.txt +++ b/homework_3/CMakeLists.txt @@ -1,4 +1,3 @@ -cmake_minimum_required(VERSION 3.20) project(homework_3) set(homeworkName "${PROJECT_NAME}") diff --git a/homework_3/task_1/CMakeLists.txt b/homework_3/task_1/CMakeLists.txt index 39015e8..87500be 100644 --- a/homework_3/task_1/CMakeLists.txt +++ b/homework_3/task_1/CMakeLists.txt @@ -1,4 +1,3 @@ -cmake_minimum_required(VERSION 3.20) project("${homeworkName}_task_1") add_library(frequencySearch frequencySearch.c) diff --git a/homework_3/task_2/CMakeLists.txt b/homework_3/task_2/CMakeLists.txt index 9ecdce7..7c4e46c 100644 --- a/homework_3/task_2/CMakeLists.txt +++ b/homework_3/task_2/CMakeLists.txt @@ -1,4 +1,3 @@ -cmake_minimum_required(VERSION 3.20) project("${homeworkName}_task_2") add_library(sortAndSearch sortAndSearch.c) diff --git a/homework_3/task_3/CMakeLists.txt b/homework_3/task_3/CMakeLists.txt index acfee86..0257ba3 100644 --- a/homework_3/task_3/CMakeLists.txt +++ b/homework_3/task_3/CMakeLists.txt @@ -1,4 +1,3 @@ -cmake_minimum_required(VERSION 3.20) project("${homeworkName}_task_3") add_library(smartQSort smartQSort.c) From 0a1cf86f3d091fb2e44113e0b641f5d8a27238e0 Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Sun, 29 Sep 2024 16:00:09 +0300 Subject: [PATCH 15/23] Synced with main-hw2-and-hw3 (hw-3) --- .github/workflows/main.yml | 36 +++++++++++++++ .gitignore | 2 +- CMakeLists.txt | 5 +- build.sh | 95 +++++++++++++++++++++++--------------- 4 files changed, 99 insertions(+), 39 deletions(-) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..48a0b75 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,36 @@ +name: Build And Test + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-24.04] + + steps: + - name: Clone repository + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Build + env: + HW_CMAKE: cmake + HW_CMAKE_COMPILER: gcc + HW_CMAKE_GENERATOR: "Unix Makefiles" + HW_EXE_EXTENSION: none + run: bash build.sh buildAll --clear --release + + - name: Test + env: + HW_CMAKE: cmake + HW_CMAKE_COMPILER: gcc + HW_CMAKE_GENERATOR: "Unix Makefiles" + HW_EXE_EXTENSION: none + run: bash build.sh testAll --clear --release diff --git a/.gitignore b/.gitignore index efc4663..407bfcf 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,4 @@ .vscode/launch.json .vscode/tasks.json build/ -config.txt +config.env diff --git a/CMakeLists.txt b/CMakeLists.txt index c4f6350..902b9f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.20) -project(homework) +project(homework LANGUAGES C) + +set(CMAKE_C_STANDARD 23) +set(CMAKE_C_STANDARD_REQUIRED TRUE) add_subdirectory(homework_3) diff --git a/build.sh b/build.sh index a99153e..0359c35 100644 --- a/build.sh +++ b/build.sh @@ -2,43 +2,54 @@ build_dir='build' -cmake='undefined_cmake' -compiler='undefined_compiler' -generator='undefined_generator' -executable_extension='undefined_executable_extension' - -while IFS="=" read -r var value; do - case $var in - cmake) cmake=$value ;; - compiler) compiler=$value ;; - generator) generator=$value ;; - executable_extension) executable_extension=$value ;; - esac -done < config.txt -unset IFS +if [[ -f config.env ]]; then + source config.env +fi + +cmake=$HW_CMAKE +compiler=$HW_CMAKE_COMPILER +generator=$HW_CMAKE_GENERATOR +executable_extension=$HW_EXE_EXTENSION -if [[ $cmake = 'undefined_command' ]]; then +if [[ -z $cmake ]]; then echo "cmake not specified" exit 1 fi -if [[ $compiler = 'undefined_compiler' ]]; then +if [[ -z $compiler ]]; then echo "compiler not specified" exit 1 fi -if [[ $generator = 'undefined_generator' ]]; then +if [[ -z $generator ]]; then echo "generator not specified" exit 1 fi -if [[ $executable_extension = 'undefined_executable_extension' ]]; then +if [[ -z $executable_extension ]]; then echo "warning: executable extension not specified - assuming there is no executable extension" + executable_extension='none' +fi + +if [[ $executable_extension = 'none' ]]; then executable_extension='' fi +# $1: quiet +# $@: command and args +function run_command { + quiet=$1 + shift + if $quiet; then + "$@" 2>&1 > /dev/null + else + "$@" + fi +} + # $1: target to build # $2: configuration +# $3: quiet function build_internal { configure=false configuration_cache_file="$build_dir/__last_configuration" @@ -52,7 +63,7 @@ function build_internal { fi if [[ $2 != $last_configuration ]]; then - $cmake -DCMAKE_BUILD_TYPE:STRING=$2 -DCMAKE_C_COMPILER:FILEPATH=$compiler -S . -B "$build_dir" -G "$generator" + run_command $3 "$cmake" "-DCMAKE_BUILD_TYPE:STRING=$2" "-DCMAKE_C_COMPILER:FILEPATH=$compiler" "-S" "." "-B" "$build_dir" "-G" "$generator" if [[ $? -ne 0 ]]; then exit 1 fi @@ -60,7 +71,7 @@ function build_internal { echo $2 > $configuration_cache_file fi - $cmake --build "$build_dir" --config $2 --target $1 -j 14 + run_command $3 "$cmake" "--build" "$build_dir" "--config" "$2" "--target" "$1" "-j" "14" if [[ $? -ne 0 ]]; then exit 1 fi @@ -69,10 +80,11 @@ function build_internal { # $1: homework # $2: task # $3: target +# $4: quiet function run_internal { - return_to=$pwd + return_to=$PWD cd $1/$2 - build/$1/$2/$3$executable_extension + run_command $4 "../../build/$1/$2/$3$executable_extension" cd $return_to } @@ -80,23 +92,25 @@ function run_internal { # $1: homework # $2: task # $3: configuration +# $4: quietBuild function build { - build_internal ${1}_$2 $3 + build_internal ${1}_$2 $3 $4 } function run { - build $1 $2 $3 - run_internal $1 $2 ${1}_$2 + build $1 $2 $3 $4 + run_internal $1 $2 ${1}_$2 $4 } function buildTest { - build $1 ${2}_test $3 + build $1 ${2}_test $3 $4 } +# $5: quietTest function test { - buildTest $1 $2 $3 - run_internal $1 $2 ${1}_${2}_test + buildTest $1 $2 $3 $4 + run_internal $1 $2 ${1}_${2}_test $5 } function foreach_homework_and_task { @@ -114,23 +128,28 @@ function foreach_homework_and_task { task=${BASH_REMATCH[1]} - $1 $homework $task $2 + $1 $homework $task $2 $3 $4 done done } # $1: configuration +# $2: quietBuild function buildAll { - foreach_homework_and_task build $1 + foreach_homework_and_task build $1 $2 } # $1: configuration +# $2: quietBuild +# $3: quietTest function testAll { - foreach_homework_and_task test $1 + foreach_homework_and_task test $1 $2 $3 } configuration='Debug' command='undefined_command' +quietBuild=false +quietTest=false while [[ "$#" -gt 0 ]]; do case $1 in build | run | buildTest | test) @@ -163,6 +182,8 @@ while [[ "$#" -gt 0 ]]; do buildAll | testAll) command="$1" ;; -r|--release) configuration='Release' ;; -d|--debug) configuration='Debug' ;; + -qb|--quiet-build) quietBuild=true ;; + -qt|--quiet-test) quietTest=true ;; -c|--clear) rm -rf "$build_dir"; ;; clear) rm -rf "$build_dir"; exit 0 ;; *) echo "unknown argument: $1"; exit 1 ;; @@ -177,22 +198,22 @@ fi case $command in build) - build $homework $task $configuration + build $homework $task $configuration $quietBuild ;; run) - run $homework $task $configuration + run $homework $task $configuration $quietBuild ;; buildTest) - buildTest $homework $task $configuration + buildTest $homework $task $configuration $quietBuild ;; test) - test $homework $task $configuration + test $homework $task $configuration $quietBuild $quietTest ;; buildAll) - buildAll $configuration + buildAll $configuration $quietBuild ;; testAll) - testAll $configuration + testAll $configuration $quietBuild $quietTest ;; esac From f4bbb47c96f5950c1e24eab978c1668091aeb124 Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Sun, 29 Sep 2024 16:15:07 +0300 Subject: [PATCH 16/23] Fixed indentation and set bash as shell explicitly --- .github/workflows/main.yml | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 48a0b75..29c0ec4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,16 +21,18 @@ jobs: - name: Build env: - HW_CMAKE: cmake - HW_CMAKE_COMPILER: gcc - HW_CMAKE_GENERATOR: "Unix Makefiles" - HW_EXE_EXTENSION: none - run: bash build.sh buildAll --clear --release + HW_CMAKE: cmake + HW_CMAKE_COMPILER: gcc + HW_CMAKE_GENERATOR: "Unix Makefiles" + HW_EXE_EXTENSION: none + shell: bash + run: ./build.sh buildAll --clear --release - name: Test env: - HW_CMAKE: cmake - HW_CMAKE_COMPILER: gcc - HW_CMAKE_GENERATOR: "Unix Makefiles" - HW_EXE_EXTENSION: none - run: bash build.sh testAll --clear --release + HW_CMAKE: cmake + HW_CMAKE_COMPILER: gcc + HW_CMAKE_GENERATOR: "Unix Makefiles" + HW_EXE_EXTENSION: none + shell: bash + run: ./build.sh testAll --clear --release From c275b7dd796ef87d49bce658d48476142747b0f3 Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Sun, 29 Sep 2024 16:50:34 +0300 Subject: [PATCH 17/23] Call build script explicitly by bash --- .github/workflows/main.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 29c0ec4..21f62bf 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,8 +25,7 @@ jobs: HW_CMAKE_COMPILER: gcc HW_CMAKE_GENERATOR: "Unix Makefiles" HW_EXE_EXTENSION: none - shell: bash - run: ./build.sh buildAll --clear --release + run: bash build.sh buildAll --clear --release - name: Test env: @@ -34,5 +33,4 @@ jobs: HW_CMAKE_COMPILER: gcc HW_CMAKE_GENERATOR: "Unix Makefiles" HW_EXE_EXTENSION: none - shell: bash - run: ./build.sh testAll --clear --release + run: bash build.sh testAll --clear --release From 59988b32fdc14e67cd805e91a021c481f7da28d0 Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Fri, 4 Oct 2024 20:29:37 +0300 Subject: [PATCH 18/23] Added alloc checks and added format strings where needed (hw3) --- homework_3/task_1/main.c | 7 +++++-- homework_3/task_2/main.c | 7 +++++-- homework_3/task_3/main.c | 8 ++++++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/homework_3/task_1/main.c b/homework_3/task_1/main.c index 96ed2c5..67f4e5c 100644 --- a/homework_3/task_1/main.c +++ b/homework_3/task_1/main.c @@ -12,10 +12,10 @@ void randomizeArray(int *array, int arrayLength, int minValue, int maxValue) { int readValue(const char *prompt, const char *incorrectValueMessage) { int value; - printf(prompt); + printf("%s", prompt); while ((scanf("%d", &value) != 1) || value < 0) { while (getchar() != '\n') {} - printf(incorrectValueMessage); + printf("%s", incorrectValueMessage); } } @@ -23,6 +23,9 @@ int main(void) { int arrayLength = readValue("enter array length: ", "incorrect value: array length cannot be less than zero; try again: "); int *array = calloc(arrayLength, sizeof(int)); + if (array == NULL) { + return 1; + } srand(time(NULL)); randomizeArray(array, arrayLength, 0, 128); diff --git a/homework_3/task_2/main.c b/homework_3/task_2/main.c index 28819c8..5b54a00 100644 --- a/homework_3/task_2/main.c +++ b/homework_3/task_2/main.c @@ -11,10 +11,10 @@ int getRandom(int minValue, int maxValue) { int readValue(const char *prompt, const char *incorrectValueMessage) { int value; - printf(prompt); + printf("%s", prompt); while ((scanf("%d", &value) != 1) || value < 0) { while (getchar() != '\n') {} - printf(incorrectValueMessage); + printf("%s", incorrectValueMessage); } } @@ -23,6 +23,9 @@ int main(void) { int numbersToCheckCount = readValue("enter amount of numbers to check: ", "incorrect value: amount cannot be less than zero; try again: "); int *array = calloc(arrayLength, sizeof(int)); + if (array == NULL) { + return 1; + } int minRandom = 0, maxRandom = 128; diff --git a/homework_3/task_3/main.c b/homework_3/task_3/main.c index 57e0763..82c3fb9 100644 --- a/homework_3/task_3/main.c +++ b/homework_3/task_3/main.c @@ -13,10 +13,10 @@ void randomizeArray(int *array, int arrayLength, int minValue, int maxValue) { int readValue(const char *prompt, const char *incorrectValueMessage) { int value; - printf(prompt); + printf("%s", prompt); while ((scanf("%d", &value) != 1) || value < 0) { while (getchar() != '\n') {} - printf(incorrectValueMessage); + printf("%s", incorrectValueMessage); } } @@ -34,6 +34,10 @@ int main(void) { int *arrayA = calloc(arrayLength, sizeof(int)), *arrayB = calloc(arrayLength, sizeof(int)); + if (arrayA == NULL || arrayB == NULL) { + return 1; + } + srand(time(NULL)); randomizeArray(arrayA, arrayLength, 0, 1024); arrayB = memcpy(arrayB, arrayA, arrayLength * sizeof(int)); From c4cff520db6d862809ed36f00c2b2cd95a863c47 Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Sat, 2 Nov 2024 16:12:20 +0300 Subject: [PATCH 19/23] Added missing return statement --- homework_3/task_1/main.c | 1 + homework_3/task_2/main.c | 1 + homework_3/task_3/main.c | 1 + 3 files changed, 3 insertions(+) diff --git a/homework_3/task_1/main.c b/homework_3/task_1/main.c index 67f4e5c..0253e85 100644 --- a/homework_3/task_1/main.c +++ b/homework_3/task_1/main.c @@ -17,6 +17,7 @@ int readValue(const char *prompt, const char *incorrectValueMessage) { while (getchar() != '\n') {} printf("%s", incorrectValueMessage); } + return value; } int main(void) { diff --git a/homework_3/task_2/main.c b/homework_3/task_2/main.c index 5b54a00..f4f0fee 100644 --- a/homework_3/task_2/main.c +++ b/homework_3/task_2/main.c @@ -16,6 +16,7 @@ int readValue(const char *prompt, const char *incorrectValueMessage) { while (getchar() != '\n') {} printf("%s", incorrectValueMessage); } + return value; } int main(void) { diff --git a/homework_3/task_3/main.c b/homework_3/task_3/main.c index 82c3fb9..4f75ecb 100644 --- a/homework_3/task_3/main.c +++ b/homework_3/task_3/main.c @@ -18,6 +18,7 @@ int readValue(const char *prompt, const char *incorrectValueMessage) { while (getchar() != '\n') {} printf("%s", incorrectValueMessage); } + return value; } long long measureTime(void (*sort)(int *, int), int *array, int arrayLength) { From cc2d23863341ee38a297f4f063338a304e5b10a1 Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Sun, 8 Dec 2024 23:57:11 +0300 Subject: [PATCH 20/23] Removed 'PRIVATE' dependency modifiers (hw 3) --- homework_3/task_1/CMakeLists.txt | 2 +- homework_3/task_2/CMakeLists.txt | 2 +- homework_3/task_3/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homework_3/task_1/CMakeLists.txt b/homework_3/task_1/CMakeLists.txt index 87500be..c2b82bd 100644 --- a/homework_3/task_1/CMakeLists.txt +++ b/homework_3/task_1/CMakeLists.txt @@ -6,4 +6,4 @@ add_executable(${PROJECT_NAME} main.c) target_link_libraries(${PROJECT_NAME} frequencySearch) add_executable(${PROJECT_NAME}_test test.c) -target_link_libraries(${PROJECT_NAME}_test PRIVATE frequencySearch) +target_link_libraries(${PROJECT_NAME}_test frequencySearch) diff --git a/homework_3/task_2/CMakeLists.txt b/homework_3/task_2/CMakeLists.txt index 7c4e46c..be8494c 100644 --- a/homework_3/task_2/CMakeLists.txt +++ b/homework_3/task_2/CMakeLists.txt @@ -6,4 +6,4 @@ add_executable(${PROJECT_NAME} main.c) target_link_libraries(${PROJECT_NAME} sortAndSearch) add_executable(${PROJECT_NAME}_test test.c) -target_link_libraries(${PROJECT_NAME}_test PRIVATE sortAndSearch) +target_link_libraries(${PROJECT_NAME}_test sortAndSearch) diff --git a/homework_3/task_3/CMakeLists.txt b/homework_3/task_3/CMakeLists.txt index 0257ba3..fc49c87 100644 --- a/homework_3/task_3/CMakeLists.txt +++ b/homework_3/task_3/CMakeLists.txt @@ -6,4 +6,4 @@ add_executable(${PROJECT_NAME} main.c) target_link_libraries(${PROJECT_NAME} smartQSort) add_executable(${PROJECT_NAME}_test test.c) -target_link_libraries(${PROJECT_NAME}_test PRIVATE smartQSort) +target_link_libraries(${PROJECT_NAME}_test smartQSort) From 73bae432f8041bccfeaf3e9053f411c84eb569b9 Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Tue, 10 Dec 2024 03:06:20 +0300 Subject: [PATCH 21/23] Fixed includes (hw 3) --- homework_3/task_1/frequencySearch.c | 2 +- homework_3/task_1/test.c | 2 +- homework_3/task_2/sortAndSearch.c | 1 - homework_3/task_2/test.c | 2 +- homework_3/task_3/smartQSort.c | 2 ++ homework_3/task_3/smartQSort.h | 2 -- homework_3/task_3/test.c | 1 - 7 files changed, 5 insertions(+), 7 deletions(-) diff --git a/homework_3/task_1/frequencySearch.c b/homework_3/task_1/frequencySearch.c index 2d457ad..a12b4ca 100644 --- a/homework_3/task_1/frequencySearch.c +++ b/homework_3/task_1/frequencySearch.c @@ -1,7 +1,7 @@ #include "frequencySearch.h" #include -#include +#include int partition(int *array, int left, int right) { int first = array[left], middle = array[(left + right) / 2], last = array[right]; diff --git a/homework_3/task_1/test.c b/homework_3/task_1/test.c index 8156978..e5f329b 100644 --- a/homework_3/task_1/test.c +++ b/homework_3/task_1/test.c @@ -2,7 +2,7 @@ #define CTEST_SEGFAULT #include "../../ctest/ctest.h" -#include +#include #include "frequencySearch.h" diff --git a/homework_3/task_2/sortAndSearch.c b/homework_3/task_2/sortAndSearch.c index ce55731..7d76288 100644 --- a/homework_3/task_2/sortAndSearch.c +++ b/homework_3/task_2/sortAndSearch.c @@ -1,7 +1,6 @@ #include "sortAndSearch.h" #include -#include int partition(int *array, int left, int right) { int first = array[left], middle = array[(left + right) / 2], last = array[right]; diff --git a/homework_3/task_2/test.c b/homework_3/task_2/test.c index ef69a27..78ca674 100644 --- a/homework_3/task_2/test.c +++ b/homework_3/task_2/test.c @@ -2,7 +2,7 @@ #define CTEST_SEGFAULT #include "../../ctest/ctest.h" -#include +#include #include "sortAndSearch.h" diff --git a/homework_3/task_3/smartQSort.c b/homework_3/task_3/smartQSort.c index 48147ec..7d7d978 100644 --- a/homework_3/task_3/smartQSort.c +++ b/homework_3/task_3/smartQSort.c @@ -1,5 +1,7 @@ #include "smartQSort.h" +#include + void insertionSort(int *array, int left, int right) { for (int i = left + 1; i <= right; ++i) { for (int j = i - 1; j >= left; --j) { diff --git a/homework_3/task_3/smartQSort.h b/homework_3/task_3/smartQSort.h index 465bedf..14f7325 100644 --- a/homework_3/task_3/smartQSort.h +++ b/homework_3/task_3/smartQSort.h @@ -1,6 +1,4 @@ #pragma once -#include - void quickSort(int *array, int arrayLength); void smartQuickSort(int *array, int arrayLength); diff --git a/homework_3/task_3/test.c b/homework_3/task_3/test.c index 259f877..7eec616 100644 --- a/homework_3/task_3/test.c +++ b/homework_3/task_3/test.c @@ -2,7 +2,6 @@ #define CTEST_SEGFAULT #include "../../ctest/ctest.h" -#include #include #include "smartQSort.h" From 35363436e61c2572c070b19e58d68c8efaffaea0 Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Sat, 14 Dec 2024 13:55:31 +0300 Subject: [PATCH 22/23] Added seed for random array test (hw3 task 3) --- homework_3/task_3/test.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/homework_3/task_3/test.c b/homework_3/task_3/test.c index 7eec616..52c0860 100644 --- a/homework_3/task_3/test.c +++ b/homework_3/task_3/test.c @@ -59,6 +59,8 @@ CTEST(smartQSortTests, randomArrayTest) { #define size 100 int array[size]; + srand(968475267); + randomizeArray(array, size, -128, 128); sortAndAssert(array, size); From 57440677eeb855599385fc133892d1245f26b00b Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Sun, 22 Dec 2024 22:08:02 +0300 Subject: [PATCH 23/23] Added README (hw 3) --- homework_3/README.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 homework_3/README.md diff --git a/homework_3/README.md b/homework_3/README.md new file mode 100644 index 0000000..38adbb9 --- /dev/null +++ b/homework_3/README.md @@ -0,0 +1,7 @@ +# Homework 3 + +[Task 1. Most frequent element](/homework_3/task_1) + +[Task 2. Search](/homework_3/task_2) + +[Task 3. Smart QSort](/homework_3/task_3)