Skip to content
Open
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
35 changes: 35 additions & 0 deletions src/kr2_c/comparer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Успела только склеивание числа и перевод в десятичную, закинула в репо, чтобы не пропадало

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

int numberGetter(const bool *a, int lenA) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Эта функция правильная, жаль всего остального нет.
Думаю, утешительные 3 балла можно поставить.

unsigned int number = 0;
for (int i = 0; i < lenA; i++) {
number = (number << 1) | (a[i] & 1); // сдвиг + добавление бита

// Работу кода можно объяснить в десятичных числах:
// Мы собираем число посимвольно из массива
// То есть был бы у нас массив {1,2,3},
// то шаги были бы такими:
// 1) 0*10 + 1 = 1 (первая цифра из массива)
// 2) 1*10 + 2 = 12 (второе цифра добавилась)
// 3) 12*10 + 3 = 123 (готово)
//
// А так как у нас не десятичная,
// мы сдвигаем биты влево (<<) и делаем |
// Вот только в двоичной << это *2, а не *10
// А | это +1 или +0 (зависимо от ситуации)
}
return number;
}


int main() {
bool arr[] = {1, 0, 1}; // 5 в десятичной (первоначальное число)
int lenA = 3; // длина массива а

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

На будущее, если задаёте тестовые данные в коде, старайтесь делать так, чтобы их было легко подменить:

Suggested change
int lenA = 3; // длина массива а
int lenA = sizeof(arr) / sizeof(bool);


printf("This number in 10cc is %d", numberGetter(arr, lenA));

return 0;
}
197 changes: 197 additions & 0 deletions src/kr2_c/palindrome.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
//
// Created by sasha on 05.12.2025.
//

#include "palindrome.h"
#include <stdio.h>
#include <stdlib.h>

//Проверить список на симметричность.
//С клавиатуры вводятся натуральные числа, построить по ним список и определить, симметричен ли он.
//Например, список из 10 20 30 20 10 симметричен, 10 20 30 40 20 10 — нет.
//Требуется использование настоящего списка на указателях, считать всё в массив не пойдёт.

Node* createList(int data) {
Node* newNode = (Node*)malloc(sizeof(Node));

if (!newNode) {
printf("Error: Memory. Not able to create a list");
exit(1);
}
newNode->data = data;
newNode->next = NULL;

return newNode;
}

void insertElement(Node** head, int data) {
Node* newNode = createList(data);

if (*head == NULL) {
*head = newNode;
return;
}

Node* current = *head;
while (current->next != NULL) {
current = current->next;

}
current->next = newNode;
}

void printList(Node* head) {
printf("Printing the List: \n");
printf("[");
Node *current = head;

while (current != NULL) {
printf("%d, ", current->data);
current = current->next;
}
printf("]\n");
}

// Проверяет симметричность, если 0 - нет симметрии, если 1 - есть
int checkSimetric(Node* head) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Развернуть половину списка -- это очень круто. Правда, я видел тот же самый код у Михаила Васильева.
И у него это решение закоммичено на час раньше, чем у Вас.
При этом, прецедент со списыванием у Вас уже был.

Так что пока за эту задачу ничего ставить не буду, потом что-нибудь для Вас придумаем.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Простите, пожалуйста, за вопрос. А в чем необычность переворота половины списка? Метод двух указателей, пусть и в другом его проявлении проходился на ЕГЭ (Просто делали мы это с концов, left и right, хотя на несколько элементов мы кстати двигались, было такое, поэтому в указателях с шагом 1 и с шагом 2 ничего странного не вижу).
Да, на ЕГЭ был питон, а не С (но это не отменяет идеи, что с самим алгоритмом мы все знакомы в какой-то мере) и односвязный список и там можно было обратиться к элементам через индекс и легко найти середину. Тут же, так как список односвязан, надо найти середину самим, так как двигаться назад и получить прошлый элемент нельзя, то есть указатели left right нереализуемы. А тут середина ищется через A = 2B. И то, мой код не работает в некоторых случаях, значит я вообще совершила в своей идее ошибку.

Честно, вообще нет идей другого решения через односвязный список. Максимум можно было сохранить все элементы в массив и там уже анализировать палиндромность, но это запрещено условием. А больше идей, как без сохранения или переворота у меня честно нет. Кроме написания через двусвязный...
Но когда преподаватель на паре сказал "черт, не подумал, что через двусвязный список делать прям легко" мне было исправлять свой код уже поздно, да и я не умею резко менять планы, простите

Заранее спасибо за любой ответ
Была бы не против услышать ваши мысли на этот счет

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Необычность разворота половины списка заключается в том, что:

  • Другие так не сделали. Я видел этот метод только у Вас, Михаила и Алины.
  • Этот метод довольно сложен в реализации.
  • Это самый эффективный вариант на односвязном списке (он работает в два прохода и вообще не требует дополнительной памяти).

Немного проясню: идею развернуть половину списка я похвалил. Даже если Вы и не сами до этого додумались (нпаример, уже видели такую задачу при подготовке к ЕГЭ), всё равно очень хорошо, что Вы выбрали именно этот способ. И я в любом случае поставлю дополлнительные баллы за эту идею, так же как Михаилу.

Претензия не в том, что Вы использовали ту же идею, что у Михаила, а в том, что у вас совпадают реализации этой идеи. Вы можете открыть своё решение и решение Михаила, и сравнить их построчно.

А по поводу других вариантов, Вы можете посмотреть чужие решения. Я видел как минимум 3 других способа:

  • обращение к элементам по индексу (примерно то же, что Вы делаете в main при вставке элемента в конец списка);
  • копирование всего списка и разворот копии целиком;
  • два указателя на двусвязном списке.

И ещё интересное наблюдение: почему-то у Вас, Михаила и Алины совпадают некоторые моменты реализации, которые можно было сделать по-разному. Например, в main при вставке элемента в конец списка Вы каждый раз заново проходите по всему списку, хотя гораздо эффективнее было бы сделать как-то так:

Node* curr = head;
int num;
for (...) {
    scanf("%d", &num);
    curr->next = NewNode(num):
    curr = curr->next;
}

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Хорошо, поняла вас, буду ждать вашего решения насчет нашей перепроверки
Спасибо за ответ

(если отправился запрос на ревью, то извините, случайно клацнула)

if (head == NULL || head->next == NULL) {
return 1;
// Считаем, что пустой список или из 1 элемента симметричен
// (ничто = ничто)
}

Node* end = head; // Указатель, который двигается по 2 узла, дойдет до конца
Node* middle = head; // Когда end дойдет до конца этот должен быть на середине (наверное..)

if (end != NULL && end->next != NULL) {
middle = middle->next;
end = end->next->next;
}

Node* prev = NULL;
Node* next = NULL;
Node* current = middle;

while (current != NULL) {
next = current->next;
current->next = prev;
prev = current;
current = next;
}

Node* firstPart = head;
Node* secondPart = prev;

while (firstPart != NULL && secondPart != NULL) {
if (firstPart->data != secondPart->data) {
return 0;
break;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Зачем break после return?

}

firstPart = firstPart->next;
secondPart = secondPart->next;
}

return 1;
}

void freeList(Node* head) {
Node* current = head;

while (current != NULL) {
Node* temp = current;
current = current->next;
free(temp);
}
}

void testEmptyList() {
Node* list = NULL;
int result = checkSimetric(list);
if (result == 1) {
printf("Palindrome. Test1 passed\n");
} else {
printf("No palindrome. Test1 is not passed\n");
}
freeList(list);
}

void testSingleElement() {
Node* list = NULL;
insertElement(&list, 1);
int result = checkSimetric(list);
if (result == 1) {
printf("Palindrome. Test2 passed\n");
} else {
printf("No palindrome. Test2 is not passed\n");
}
freeList(list);
}

void testNotPalindrome() {
Node* list = NULL;
insertElement(&list, 1);
insertElement(&list, 2);
insertElement(&list, 2);
int result = checkSimetric(list);
if (result == 0) {
printf("Not palindrome. Test3 passed\n");
} else {
printf("Palindrome. Test3 is not passed\n");
}
freeList(list);
}

void testPalindrome() {
Node* list = NULL;
insertElement(&list, 1);
insertElement(&list, 2);
insertElement(&list, 2);
insertElement(&list, 1);
int result = checkSimetric(list);
if (result == 1) {
printf("Palindrome. Test4 passed\n");
} else {
printf("No palindrome. Test4 is not passed\n");
}
freeList(list);
}

int main() {
Node* head = NULL;

printf("Tests:\n");
testEmptyList();
testSingleElement();
testNotPalindrome();
testPalindrome();

int element;
printf("Enter numbers, for exiting enter negative number or 0 \n");

while (1) {
scanf("%d", &element);
if (element <= 0) {
printf("Exiting... \n");
break;
}
insertElement(&head, element);
}
printList(head);
int result = checkSimetric(head);
if (result == 1) {
printf("Palindrome\n");
} else {
printf("No palindrome\n");
}

freeList(head);

return 0;
}






23 changes: 23 additions & 0 deletions src/kr2_c/palindrome.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// Created by sasha on 05.12.2025.
//

#ifndef KR_PALINDROME_H

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

По стайлгайду нельзя использовать include guards.

#define KR_PALINDROME_H

typedef struct Node {
int data;
struct Node* next;
} Node;

Node* createEmptyList(int data);

void insertElement(Node**, int data);

void printList(Node* head);

void freeList(Node* head);

int checkSimetric(Node* head);

#endif //KR_PALINDROME_H