1

Тема: Вивести процентне співвідношення двох слів

#include <iostream>
#include <string>
using namespace std;
double per(string word, string word2) {
    int length = 0;
    double len_ratio = 0;
    double len_percent = 0;
    double d_ret = 0;
    int count = 0;
    if(word.size() == word2.size())
        length=word2.size();
    if(word.size() > word2.size()) {
        length = word2.size();
        len_ratio = word2.size() / word.size();
    }
    if(word.size() < word2.size()) {
        length = word.size();
        len_ratio = word.size() / word2.size();
    }
    len_percent = len_ratio * 100;
    for(int i = 0; i < length; i++) {
        if(word2[i] == word[i])
            count++;
    }
    d_ret = (double)count / (double)length * 100.0;
    if(word.size() != word2.size()) {
        d_ret = (double)count / (double)length * 100.0;
            d_ret = (d_ret + len_percent) / 2;
    }
    return d_ret;
}
int main(int argc, char **argv) {
    string loc_str;
    cout << "Locale (uk, en): ";
    cin >> loc_str;
    setlocale(LC_ALL, loc_str.c_str());
    cout << "Word1, word2: ";
    string word1, word2;
    cin >> word1 >> word2;
    cout << "Result: " << per(word1, word2) << endl;
    return 0;
}

Помилок у коді немає. Треба виправити недоліки алгоритму.
Наприклад, їжачок і їжак має співпадати на 50%, а співпадає на 37.5%

Locale (uk, en): uk
Word1, word2: їжачок їжак
Result: 37.5

2

Re: Вивести процентне співвідношення двох слів

Я розумію, це якась синтетична оцінка "схожості" слів за якоюсь неочевидною формулою.
У вас у коді - не та формула, яку вам треба. Але яку вам треба - ви не написали, відповідно, і допомогти вам ми не можемо.

Ну, власне, єдине, що ви написали про потрібну вам формулу - що має повертати 50%, але вас же ось таке не влаштує, правда?

double per(string word, string word2) {
    return 50.0;
}
Подякували: leofun011

3

Re: Вивести процентне співвідношення двох слів

#include <iostream>
#include <string>
using namespace std;
double per(string word, string word2)
{
    int length=0;
    double len_ratio=0;
    double len_percent=0;
    double d_ret=0;
    int count=0;
    if(word.size()>word2.size()) {
        length=word2.size();
        len_ratio=(double)word2.size()/(double)word.size();
    }
    if(word.size()<word2.size()) {
        length=word.size();
        len_ratio=(double)word.size()/(double)word2.size();
    }
    len_percent=len_ratio*(double)100;
    cout << len_percent << endl;//це виводить 66.6667
    if(word.size()==word2.size()) {
        length=word2.size();
        for (int i=0; i<length; i++) {
            if(word2[i]==word[i]) count++;
        }
        d_ret=(double)count/(double)length * 100.0;
    }
    else
    {
        size_t pos=std::string::npos;
        if(word.size()<word2.size()){
            pos = word2.find(word);
        }
        else {
            pos = word.find(word2);
        }
        
        if (pos != std::string::npos)
        {
            return len_percent;
        }
        else
        {
            for (int i=0; i<length; i++) {
                if(word2[i]==word[i]) count++;
            }
            d_ret=(double)count/(double)length * 100.0;
            d_ret=(d_ret+len_percent)/2;
        }
    }
    return d_ret;
}

int main(int argc, char** argv) {
    cout << "Word1, word2: ";
    string word1, word2;
    cin >> word1 >> word2;
    cout << "Result: " << per(word1, word2) << endl;
    return 0;
}
Word1, word2: їжак їжачок
66.6667
Result: 70.8333

Тепер виводить два різних значення і більше 50. Треба людське визначення. Я не знаю як працює людський алгоритм. Перед цією функцією слова зводитимуться до однакового закінчення (я ще не маю алгоритму, треба списки закінчень і виключення).
Не працює зовсім і цей код, який має фільтрувати слова від закінчень без списків закінчень:

#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <fstream>
#include <sstream>
#define NO_MATCH -1
using namespace std;
double per(string word, string word2)
{
    int length=0;
    double len_ratio=0;
    double len_percent=0;
    double d_ret=0;
    int count=0;
    if(word.size()>word2.size()) {
        length=word2.size();
        len_ratio=(double)word2.size()/(double)word.size();
    }
    if(word.size()<word2.size()) {
        length=word.size();
        len_ratio=(double)word.size()/(double)word2.size();
    }
    len_percent=len_ratio*(double)100;
    if(word.size()==word2.size()) {
        length=word2.size();
        for (int i=0; i<length; i++) {
            if(word2[i]==word[i]) count++;
        }
        d_ret=(double)count/(double)length * 100.0;
    }
    else
    {
        size_t pos=std::string::npos;
        if(word.size()<word2.size()){
            pos = word2.find(word);
        }
        else {
            pos = word.find(word2);
        }
        
        if (pos != std::string::npos)
        {
            return len_percent;
        }
        else
        {
            for (int i=0; i<length; i++) {
                if(word2[i]==word[i]) count++;
            }
            d_ret=(double)count/(double)length * 100.0;
            d_ret=(d_ret+len_percent)/2;
        }
    }
    return d_ret;
}
int maxword_index(std::vector<std::string> voc_words, string test_word)
{
    int index_total=voc_words.size();
    int percents=0;
    int max_value = 0;
    int max_index=0;
    for (int i=0; i<index_total; i++)
    {
        percents=per(voc_words[i], test_word);
        if (percents > max_value) {
            max_value = percents;
            if(max_value>=70) max_index=i;//70 percents
        }
    }
    
    if(max_value<70) max_index=NO_MATCH;
    return max_index;
}
std::vector<std::string> LoadFile(string FileName) {
    std::vector<std::string> result;
    std::ifstream inputFile(FileName.c_str());
    if (inputFile.is_open()) {
        std::string line;
        while (std::getline(inputFile, line)) {
            result.push_back(line);
        }
        inputFile.close();
    }
    return result;
}
std::vector<std::string> delim(const std::string str) {
    std::vector<std::string> result;
    std::istringstream iss(str);
    std::string word;
    while (iss >> word) {
        result.push_back(word);
    }
    return result;
}
int main(int argc, char** argv) {
    std::string s;
    std::string name;
    std::string vocfilename;
    cout << "File name: ";
    cin >> vocfilename;
    std::vector<std::string> voc_words = LoadFile(vocfilename);
    std::cout << "Text: ";
    std::cin.ignore();  // Ignore the newline character left in the buffer
    std::getline(std::cin, s);
    std::vector<std::string> text_words = delim(s);
    for (int i = 0; i < text_words.size(); i++) {
        int j=maxword_index(voc_words, text_words[i]);
        if(j!=NO_MATCH) std::cout << j << " " << voc_words[j] << ", ";
    }
    return 0;
}

4

Re: Вивести процентне співвідношення двох слів

Тоді може замість кидати випадкові шматки коду, які працюють не так, як вам треба, і скаржитися на це, ви поясните, чого саме ви хочете досягти?

Подякували: leofun011

5 Востаннє редагувалося koala (05.02.2024 16:14:36)

Re: Вивести процентне співвідношення двох слів

Програмування, в цілому - це процес перекладання алгоритмів з людської мови на комп'ютерну. Якщо ви не маєте алгоритму людською мовою - то ви не можете його запрограмувати за визначенням, вам немає чого програмувати.

6

Re: Вивести процентне співвідношення двох слів

#include <iostream>
#include <string>
using namespace std;
bool check_suff(string suffix, string word)
{
    if(word.substr(word.size() - suffix.size()) == suffix) return 1;
    return 0;
}
bool check_preff(string preffix, string word)
{
    if (word.size() >= preffix.size() && word.substr(0, preffix.size()) == preffix) return 1;
    return 0;
}
double per(string word, string word2)
{
    int length=0;
    double len_ratio=0;
    double len_percent=0;
    double d_ret=0;
    int count=0;
    if(word.size()>word2.size()) {
        length=word2.size();
        len_ratio=(double)word2.size()/(double)word.size();
    }
    if(word.size()<word2.size()) {
        length=word.size();
        len_ratio=(double)word.size()/(double)word2.size();
    }
    len_percent=len_ratio*(double)100;
    cout << len_percent << endl;
    if(word.size()==word2.size()) {
        length=word2.size();
        for (int i=0; i<length; i++) {
            if(word2[i]==word[i]) count++;
        }
        d_ret=(double)count/(double)length * 100.0;
    }
    else
    {
        bool preff_match=0;
        if(word.size()<word2.size()){
            //pos = word2.find(word);
            preff_match=check_preff(word, word2);
        }
        else {
            //pos = word.find(word2);
            preff_match=check_preff(word2, word);
        }
        
        if (/*pos != std::string::npos*/ preff_match)
        {
            return len_percent;
        }
        else
        {
            for (int i=0; i<length; i++) {
                if(word2[i]==word[i]) count++;
            }
            d_ret=(double)count/(double)length * 100.0;
            d_ret=(d_ret+len_percent)/2;
        }
    }
    return d_ret;
}

int main(int argc, char** argv) {
    cout << "Word1, word2: ";
    string word1, word2;
    cin >> word1 >> word2;
    cout << "Result: " << per(word1, word2) << endl;
    return 0;
}

Є два слова
1) визначити довжину слів
2) порахувати процентне співвідношення слова з меншою довжиною до слова з більшою довжиною
3) якщо довжина однакова порівняти символи і повернути процентне співвідношення співпадіння символів.
4) якщо довжина різна
4.1) спробувати шукати однаковий початок. Слово з меншою довжиною є початком. Якщо початок однаковий, повернути процентне співвідношення слова з меншою довжиною.
4.2) якщо початок різний порівнювати символи слова з меншою довжиною з символами слова з більшою довжиною. Отримане процентне співвідношення слова з меншою довжиною до слова з більшою довжиною додати до процентного співвідношення співпадіння символів і поділити на 2 (середнє арифметичне).

7

Re: Вивести процентне співвідношення двох слів

Це ви зараз, як я зрозумів, замість того, щоб описувати, що вам ТРЕБА, описали, що ви ЗРОБИЛИ - і це при тому, що ви ж самі кажете, що те, що ви зробили, вам не підходить.

v002002 написав:

Перед цією функцією слова зводитимуться до однакового закінчення (я ще не маю алгоритму, треба списки закінчень і виключення).

Це натякає, що у вас є якась більша задача, яку ви намагаєтеся розв'язати зведеням слів до спільного закінчення і підрахуноком "схожості". Цілком можливо, що всі ваші проблеми - не від того, що у вас не виходить "правильну формулу" знайти, а від того, що ви просто обрали неправильний шлях розв'язання тієї більшої задачі, і "правильної формули" просто не існує.

8

Re: Вивести процентне співвідношення двох слів

Завдання зробити програму, яка визначає подію по опису (як ChatGPT)
Після перевірки схожості у тому варіанті який я хочу програма повинна переформулювати текст без закінчень, наприклад

краплі вода падають з хмара

і згенерувати хеш. У якості хеша використовувати записані через кому індекси слів, наприклад

1,5,7,88,90:йде дощ

Так без повторних хешів і легше генерувати. Кожному хешу в текстовому файлі (для зменшення обсягу) через двокрапку відповідь. Треба вгадувати подію по опису без прив'язки до часу (ходив, ходитиму)

9

Re: Вивести процентне співвідношення двох слів

Код порівняння за довжиною працює без проблем

#include <iostream>
#include <string>
using namespace std;
double len_per(string word, string word2)
{
    int length=0;
    double len_ratio=1;
    double len_percent=0;
    if(word.size()>word2.size()) {
        length=word2.size();
        len_ratio=(double)word2.size()/(double)word.size();
    }
    if(word.size()<word2.size()) {
        length=word.size();
        len_ratio=(double)word.size()/(double)word2.size();
    }
    len_percent=len_ratio*(double)100;
    cout << len_percent << endl;
    
    return len_percent;
}

int main(int argc, char** argv) {
    cout << "Word1, word2: ";
    string word1, word2;
    cin >> word1 >> word2;
    cout << "Result: " << len_per(word1, word2) << endl;
    return 0;
}
Word1, word2: їжак їжачок
66.6667
Result: 66.6667

а код що надано у попередньому пості
https://replace.org.ua/post/190138/#p190138

Word1, word2: їжак їжачок
66.6667
Result: 70.8333

звідки береться 70.8333?

10 Востаннє редагувалося koala (05.02.2024 21:44:53)

Re: Вивести процентне співвідношення двох слів

v002002 написав:

звідки береться 70.8333?

len_percent = 66.6667
d_ret = 75
Середнє - якраз 70.8333

Те, що ви робите - трохи безнадійно, якщо ви одразу суворо не обмежите список слів.
Хочете пораду? Поставте на початку функції

if(word.size()>word2.size())
    std::swap(word, word2);

і все, word завжди коротший за word2. Більше жодних перевірок, код скорочується майже удвічі.
До речі, можете їх назвати на кшталт longer і shorter, щоб не плутати, котре коротше.

Подякували: v0020021

11

Re: Вивести процентне співвідношення двох слів

Дякую.

double per(string word, string word2)
{
    int length=0;
    double len_ratio=0;
    double len_percent=0;
    double d_ret=0;
    int count=0;
    if(word.size()!=word2.size()) {
        if(word.size()>word2.size()) std::swap(word, word2);
        length=word.size();
        len_ratio=(double)word.size()/(double)word2.size();
        len_percent=len_ratio*(double)100;
        cout << len_percent << endl;
        bool preff_match=check_preff(word, word2);
        if (preff_match)
        {
            return len_percent;
        }
        else
        {
            for (int i=0; i<length; i++) {
                if(word2[i]==word[i]) count++;
            }
            d_ret=(double)count/(double)length * 100.0;
            d_ret=(d_ret+len_percent)/2;
        }
    }
    
    else {
        length=word2.size();
        for (int i=0; i<length; i++) {
            if(word2[i]==word[i]) count++;
        }
        d_ret=(double)count/(double)length * 100.0;
    }
    return d_ret;
}

Я просто був не зрозумів. Воно шукає слово "їжак" у слові "їжачок" і його не знаходить тому виводить середнє арифметичне. Якщо ввести "їжа" і "їжачок" виводить 50%

12

Re: Вивести процентне співвідношення двох слів

Ще трохи доробив:

double per_internal(const string &shorter, const string &longer) {
    int count = 0;
    for(int i = 0; i < shorter.size(); i++)
        if(shorter[i] == longer[i]) 
            count++;

    double d_ret = count * 100.0 / shorter.size(); // в будь-якому разі треба обчислити

    if(shorter.size() == longer.size()) // перевіряємо і виходимо
        return d_ret;

    double len_percent = shorter.size() * 100.0 / longer.size(); // (double)100 - це просто 100.0

    if(count == shorter.size()) // тепер не потрібен preff_match
        return len_percent;

    return (d_ret + len_percent) / 2.0;
}

inline double per(const string &word, const string &word2) {
    return word.size() > word2.size() ? per_internal(word2, word) : per_internal(word, word2);
}

Тепер замість std::swap викликається функція per_internal з правильним порядком аргументів. Додав посилання в аргументи і витиснув воду.

Подякували: v0020021