Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Критерий - дублирование кода #16

Open
AndrewGavril opened this issue Dec 29, 2023 · 3 comments
Open

Критерий - дублирование кода #16

AndrewGavril opened this issue Dec 29, 2023 · 3 comments

Comments

@AndrewGavril
Copy link

AndrewGavril commented Dec 29, 2023

Пример:

switch (getcommand()){
    case 0:
        cnt_sentences = readtext(&sentences);
        if (!sentences) return 0;
        preprocessing(&sentences, &cnt_sentences);
        printtext(&sentences, &cnt_sentences);
        freetext(&sentences, &cnt_sentences);
        return 0;
    case 1:
        cnt_sentences = readtext(&sentences);
        if (!sentences) return 0;
        preprocessing(&sentences, &cnt_sentences);
        bananapplesearch(&sentences, &cnt_sentences);
        freetext(&sentences, &cnt_sentences);
        return 0;
    case 2:
        cnt_sentences = readtext(&sentences);
        if (!sentences) return 0;
        preprocessing(&sentences, &cnt_sentences);
        convertnumsandalpha(&sentences, &cnt_sentences);
        printtext(&sentences, &cnt_sentences);
        freetext(&sentences, &cnt_sentences);
        return 0;
    case 3:
        cnt_sentences = readtext(&sentences);
        if (!sentences) return 0;
        preprocessing(&sentences, &cnt_sentences);
        siftedoutput(&sentences, &cnt_sentences);
        freetext(&sentences, &cnt_sentences);
        return 0;
    case 4:
        cnt_sentences = readtext(&sentences);
        if (!sentences) return 0;
        preprocessing(&sentences, &cnt_sentences);
        sorttextnums(&sentences, &cnt_sentences);
        printtext(&sentences, &cnt_sentences);
        freetext(&sentences, &cnt_sentences);
        return 0;
    case 5:
        printhelp();
        return 0;
    case 9:
        scanf("%d\n", &N);
        cnt_sentences = readtext(&sentences);
        if (!sentences) return 0;
        printduplicates(&sentences, &cnt_sentences, &N);
        return 0;
    default:
        printf("Error: Unexpected command\n");
        return 0;
    }

Очевидно, что половина кода дублируется и можно переписать в:

void do_processing_command(int command, char ***sentences, int *cnt_sentences){
    switch (command){
    case 0:
        printtext(&sentences, &cnt_sentences);
        break;
    case 1:
        bananapplesearch(&sentences, &cnt_sentences);
        break;
    case 2:
        convertnumsandalpha(&sentences, &cnt_sentences);
        printtext(&sentences, &cnt_sentences);
        break;
    case 3:
        siftedoutput(&sentences, &cnt_sentences);
        break;
    case 4:
        sorttextnums(&sentences, &cnt_sentences);
        printtext(&sentences, &cnt_sentences);
        break;
    }
    freetext(&sentences, &cnt_sentences);
}
...
switch ((command = getcommand())){
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
        cnt_sentences = readtext(&sentences);
        if (!sentences) return 0;
        preprocessing(&sentences, &cnt_sentences);
        do_processing_command(command, &sentences, &cnt_sentences);
    case 5:
        printhelp();
        return 0;
    default:
        printf("Error: Unexpected command\n");
        return 0;
}

Можно еще улучшить и сократить этот код, но избежания явного дублирования кода в if-else и switch-case уже достаточно.

@jcdkiki
Copy link
Collaborator

jcdkiki commented Feb 21, 2024

Думал сейчас над реализацией этого всего. В общем, мне кажется, что проверки на списывание на всяких codeforces используют следующий алгоритм:

  1. Раскрыть макросы и токенизировать оба текста, подлежащих сравнению.
  2. Упростить некоторые токены. Например, конструкции while и for заменяются один токеном LOOP
  3. Посчитать расстояние Левенштейна между токенами этих текстов (или определить их "разницу" каким-то другим образом, о котором я не знаю).
  4. Если процент сходства (1 - distance(s1, s2) / max(len(s1), len(s2))) превышает какую-то константу, то код СПИСАН.

Алгоритм несложный, но проблема в том, что в нашем случае мы не знаем, какие части кода нужно сравнивать. Сравнивать всё подряд это тупо, неинтересно и дорого.

Если упростить эту задачу до сравнения "внутренностей" конструкций if-else и switch-case, а не всего подряд, то для меня это звучит более чем реализуемо. Понятно, что такой алгоритм будет отлавливать далеко не все случаи дублирования кода, но хотя бы что-то.

@jcdkiki
Copy link
Collaborator

jcdkiki commented Feb 26, 2024

image
Что если просто показывать студенту, заславшему работу, нечто такое. И чтобы эта проверка носила рекомендательный характер, как с проверкой формата отчётов.

@jcdkiki
Copy link
Collaborator

jcdkiki commented Feb 26, 2024

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants