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_6/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ project(homework_6)
set(homeworkName "${PROJECT_NAME}")

add_subdirectory(task_1)
add_subdirectory(task_2)
add_subdirectory(task_3)
2 changes: 2 additions & 0 deletions homework_6/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@

[Task 1. Merge sort](/homework_6/task_1)

[Task 2. Counting rhyme](/homework_6/task_2)

[Task 3. Sorted list](/homework_6/task_3)
9 changes: 9 additions & 0 deletions homework_6/task_2/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
project("${homeworkName}_task_2")

add_library(cyclicList cyclicList.c)

add_executable(${PROJECT_NAME} main.c)
target_link_libraries(${PROJECT_NAME} cyclicList)

add_executable(${PROJECT_NAME}_test test.c)
target_link_libraries(${PROJECT_NAME}_test cyclicList)
59 changes: 59 additions & 0 deletions homework_6/task_2/cyclicList.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include "cyclicList.h"

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

typedef struct ListElement {
struct ListElement *left;
struct ListElement *right;
int value;
} ListElement;

bool addElementAfter(ListElement *previous, ListElement **newElement, int value) {
ListElement *element = malloc(sizeof(ListElement));
if (element == NULL) {
return false;
}

if (previous == NULL) {
element->left = element;
element->right = element;
} else {
ListElement *next = previous->right;
element->left = previous;
element->right = next;

next->left = element;
previous->right = element;
}

element->value = value;
*newElement = element;

return true;
}

ListElement *getNext(ListElement *element) {
return element->right;
}

int getValue(ListElement *element) {
return element->value;
}

void removeElement(ListElement *element) {
ListElement *left = element->left;
ListElement *right = element->right;
left->right = right;
right->left = left;
free(element);
}

void removeAllElements(ListElement *element) {
ListElement *right = element->right;
do {
ListElement *next = right->right;
removeElement(right);
right = next;
} while (right != element);
}
32 changes: 32 additions & 0 deletions homework_6/task_2/cyclicList.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#pragma once

#include <stdbool.h>

/// @brief Cyclic list element
typedef struct ListElement ListElement;

/// @brief Adds new element after specified element
/// @param previous Element that will be on the left relative to new element,
/// must be `NULL` when creating new list
/// @param newElement Pointer to store created `ListElement` to
/// @param value Value to store in new element
/// @return `true` if added successfully, `false` otherwise (allocaton failed)
bool addElementAfter(ListElement *previous, ListElement **newElement, int value);

/// @brief Gets element on the right of the specified element
/// @param element Element of cyclic list
/// @return Element on the right of the specified element
ListElement *getNext(ListElement *element);

/// @brief Gets value of the specified element
/// @param element Element of cyclic list
/// @return Value of specified element
int getValue(ListElement *element);

/// @brief Removes an element (and calls `free()` on it)
/// @param element Element to remove
void removeElement(ListElement *element);

/// @brief Removes all elements of cyclic list
/// @param element Any element of the list
void removeAllElements(ListElement *element);
56 changes: 56 additions & 0 deletions homework_6/task_2/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include <stdbool.h>
#include <stdio.h>

#include "cyclicList.h"

bool getLastWarrior(int warriorsCount, int killersPerWarrior, int *result) {
ListElement *lastElement = NULL;
for (int i = 0; i < warriorsCount; ++i) {
ListElement *newElement = NULL;
if (!addElementAfter(lastElement, &newElement, i + 1)) {
return false;
}

lastElement = newElement;
}

// set lastElement to point to element
lastElement = getNext(lastElement);

while (getNext(lastElement) != lastElement) {
for (int i = 0; i < killersPerWarrior; ++i) {
lastElement = getNext(lastElement);
}
ListElement *next = getNext(lastElement);
removeElement(lastElement);
lastElement = next;
}

*result = getValue(lastElement);
removeAllElements(lastElement);

return true;
}

int readValue(const char *prompt, const char *incorrectValueMessage) {
int value;
printf("%s", prompt);
while ((scanf("%d", &value) != 1) || value <= 0) {
while (getchar() != '\n') {}
printf("%s", incorrectValueMessage);
}
return value;
}

int main(void) {
int warriorsCount = readValue("warriors count: ", "incorrect value; warriors count should be greater than zero; try again: ");
int nthWarrior = readValue("n-th warrior to be killed: ", "incorrect value; n should be greater than zero; try again: ");

int result = 0;
if (!getLastWarrior(warriorsCount, nthWarrior - 1, &result)) {
printf("allocation error\n");
return 1;
}

printf("last warrior: %d\n", result);
}
65 changes: 65 additions & 0 deletions homework_6/task_2/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#define CTEST_MAIN
#define CTEST_SEGFAULT
#include "../../ctest/ctest.h"

#include <stdlib.h>

#include "cyclicList.h"

int main(int argc, const char *argv[]) {
return ctest_main(argc, argv);
}

ListElement *add(ListElement *after, int value) {
ListElement *element;
ASSERT_TRUE(addElementAfter(after, &element, value));
ASSERT_NOT_NULL(element);

return element;
}

CTEST(cyclicListTests, createTest) {
ListElement *element = add(NULL, 0);

ASSERT_TRUE(getNext(element) == element);
ASSERT_TRUE(getNext(getNext(element)) == element);

removeAllElements(element);
}

CTEST(cyclicListTests, addElementTest) {
ListElement *elementA = add(NULL, 0);
ListElement *elementB = add(elementA, 1);
ListElement *elementC = add(elementB, 2);
ListElement *elementD = add(elementC, 3);

ASSERT_TRUE(getNext(elementA) == elementB);
ASSERT_TRUE(getNext(elementB) == elementC);
ASSERT_TRUE(getNext(elementC) == elementD);
ASSERT_TRUE(getNext(elementD) == elementA);

ASSERT_EQUAL(getValue(elementA), 0);
ASSERT_EQUAL(getValue(elementB), 1);
ASSERT_EQUAL(getValue(elementC), 2);
ASSERT_EQUAL(getValue(elementD), 3);

removeAllElements(elementA);
}

CTEST(cyclicListTests, removeElementTest) {
ListElement *elementA = add(NULL, 0);
ListElement *elementB = add(elementA, 0);
ListElement *elementC = add(elementB, 0);
ListElement *elementD = add(elementC, 0);

removeElement(elementB);
ASSERT_TRUE(getNext(elementA) == elementC);

removeElement(elementC);
ASSERT_TRUE(getNext(elementA) == elementD);

removeElement(elementD);
ASSERT_TRUE(getNext(elementA) == elementA);

removeAllElements(elementA);
}