Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions homework_4/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ set(homeworkName "${PROJECT_NAME}")

add_subdirectory(task_1)
add_subdirectory(task_2)
add_subdirectory(task_3)
2 changes: 2 additions & 0 deletions homework_4/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
[Task 1. Binary representation](/homework_4/task_1)

[Task 2. Phone database](/homework_4/task_2)

[Task 3. Modules and files](/homework_4/task_3)
10 changes: 10 additions & 0 deletions homework_4/task_3/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
project("${homeworkName}_task_3")

add_library(newFrequencySearch frequencySearch.c)
add_library(arrayIO arrayIO.c)

add_executable(${PROJECT_NAME} main.c)
target_link_libraries(${PROJECT_NAME} newFrequencySearch arrayIO)

add_executable(${PROJECT_NAME}_test test.c)
target_link_libraries(${PROJECT_NAME}_test newFrequencySearch arrayIO)
34 changes: 34 additions & 0 deletions homework_4/task_3/arrayIO.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "arrayIO.h"

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

bool readFromStream(FILE *file, int **array, int *arrayLength) {
int arrayCapacity = 4;
*arrayLength = 0;
*array = malloc(arrayCapacity * sizeof(int));

if (array == NULL) {
return false;
}

while (!feof(file)) {
int value = -1;
if (fscanf(file, "%d", &value) != 1) {
continue;
}

if (*arrayLength == arrayCapacity) {
arrayCapacity *= 2;
*array = realloc(*array, arrayCapacity * sizeof(int));
if (*array == NULL) {
return false;
}
}
(*array)[*arrayLength] = value;
++*arrayLength;
}

return true;
}
6 changes: 6 additions & 0 deletions homework_4/task_3/arrayIO.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#pragma once

#include <stdbool.h>
#include <stdio.h>

bool readFromStream(FILE *file, int **array, int *arrayLength);
84 changes: 84 additions & 0 deletions homework_4/task_3/frequencySearch.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include "frequencySearch.h"

#include <stdbool.h>
#include <stdlib.h>

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;
}
5 changes: 5 additions & 0 deletions homework_4/task_3/frequencySearch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

#include <stdbool.h>

bool findMostFrequentElement(int *array, int arrayLength, int *mostFrequentElement, int *occurrences);
43 changes: 43 additions & 0 deletions homework_4/task_3/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include <stdio.h>
#include <stdlib.h>

#include "frequencySearch.h"
#include "arrayIO.h"

int main(void) {
char buffer[1024];
printf("input file path: ");
if (scanf("%1023s", buffer) != 1) {
printf("couldn't open file\n");
return 1;
}

FILE *file = fopen(buffer, "r");
if (file == NULL) {
perror("opening file failed");
return 1;
}

int *array;
int arrayLength;
if (!readFromStream(file, &array, &arrayLength)) {
printf("allocation error\n");
return 1;
}

if (ferror(file)) {
perror("read error");
fclose(file);
return 1;
}
fclose(file);

int mostFrequentElement, occurrences;
if (findMostFrequentElement(array, arrayLength, &mostFrequentElement, &occurrences)) {
printf("most frequent element is %d (appears %d time%s)\n", mostFrequentElement, occurrences, occurrences == 1 ? "" : "s");
} else {
printf("couldn't find most frequent element: array is empty\n");
}

free(array);
}
77 changes: 77 additions & 0 deletions homework_4/task_3/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#define CTEST_MAIN
#define CTEST_SEGFAULT
#include "../../ctest/ctest.h"

#include <stdio.h>

#include "frequencySearch.h"
#include "arrayIO.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
}

void loadFile(const char *path, int **array, int *arrayLength) {
FILE *file = fopen(path, "r");
ASSERT_NOT_NULL(file);
ASSERT_TRUE(readFromStream(file, array, arrayLength));
ASSERT_EQUAL(fclose(file), 0);
}

CTEST(arrayIOTests, emptyArrayTest) {
int *array, arrayLength;
loadFile("./testFiles/emptyArray", &array, &arrayLength);
ASSERT_EQUAL(arrayLength, 0);
}

CTEST(arrayIOTests, singleElementTest) {
int *array, arrayLength;
loadFile("./testFiles/singleElement", &array, &arrayLength);
ASSERT_EQUAL(arrayLength, 1);
ASSERT_EQUAL(array[0], 8192);
}

CTEST(arrayIOTests, incrementalArrayTest) {
int *array, arrayLength;
loadFile("./testFiles/incrementalArray", &array, &arrayLength);
ASSERT_EQUAL(arrayLength, 8);
for (int i = 0; i < arrayLength; ++i) {
ASSERT_EQUAL(i, array[i]);
}
}
1 change: 1 addition & 0 deletions homework_4/task_3/testFiles/emptyArray
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

8 changes: 8 additions & 0 deletions homework_4/task_3/testFiles/incrementalArray
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
0
1
2
3
4
5
6
7
1 change: 1 addition & 0 deletions homework_4/task_3/testFiles/singleElement
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
8192