#include <iostream>     // cin és cout parancsok
#include <fstream>      // fájlkezelés
#include <vector>       // vector adattípushoz
#include <map>          // szótár adattípushoz
#include <set>          // szótár adattípushoz
#include <algorithm>    // sort, find és count_if függvények

using namespace std;

int betu_kodja(vector<char> b,char betu)        // adott betű kódjának meghatározása
{
    auto it=find(b.begin(), b.end(), betu);     // megkeressük a betű "indexét" a vektorban
    if(it!=b.end())                             // ha megtaláljuk, akkor
        return it-b.begin();                    // vissza adjuk az indexet
}

string szo_kodja(vector<char> b,vector<int> k,string sz)    // adott szó kódja
{
    string s="";                    // stringként építjük fel a kódot
    for(auto betu:sz)               // a szó betűire alkalmazzuk a betu_kodja függvényt
    {
        s+=to_string(k[betu_kodja(b,betu)]);        // to_string: kódot stringre alakítja   pl. 4 --> "4"
    }
    return s;
}

void kodhoz_tartozo_szavak(vector<string> szk,vector<string> szk_kodja,string keresett_kod,map<string,vector<string>> &kod_es_szavai)
{

    for(int i=0;i<szk_kodja.size();i++)
    {
        if(szk_kodja[i]==keresett_kod)
            kod_es_szavai[keresett_kod].push_back(szk[i]);
    }
}

void F1(vector<char> b,vector<int> k)
{
    cout << "1. feladat" << endl;
    char betu;
    cout << "Kérek egy betűt: (a-z) ";
    cin >> betu;
    cout << "A betű kódja: " << k[betu_kodja(b,betu)] << endl;
}

void F2(vector<char> b,vector<int> k)
{
    cout << "1. feladat" << endl;
    string szo;
    cout << "Kérek egy szót: ";
    cin >> szo;
    cout << "A szó kódja: " << szo_kodja(b,k,szo) << endl;
}

void F3(vector<string> &szk)
{
    cout << "3. feladat - szavak.txt (input)" << endl;
    string tmp;
    ifstream fbe;
    fbe.open("szavak.txt");
    while(fbe>>tmp)
    {
        szk.push_back(tmp);
    }
    fbe.close();
}

bool hossz_szerint(string a, string b)      // ez az alternatív rendezési megoldáshoz kell, ha úgy akarjuk rendezni a szavakat...
{
    return a.size() > b.size();
}

void F4(vector<string> szk)
{
    cout << "4. feladat" << endl;
    vector<string> tmp;
    tmp=szk;
    // rendezés csökkenő sorrendbe C++-os "lambda-kifejezéssel" szavak hossza szerint
    sort(tmp.begin(),tmp.end(),[](string a, string b) {return a.size() > b.size();});
    // vagy, alternatív megoldás:
    // sort(tmp.begin(),tmp.end(),hossz_szerint);
    cout << "A leghosszabb szó: " << tmp[0] << ", hossza: " << tmp[0].size() << " karakter" << endl;
}

void F5(vector<string> szk)
{
    cout << "5. feladat" << endl;
    // count_if itt kiválóan használható (itt is "lambda-kifejezést" használunk, mint a rendezésnél...)
    cout << "Rövid szavak száma: " << count_if(szk.begin(),szk.end(), [](string item) {return (item.size()<=5);}) << endl;
}

void F6(vector<char> b,vector<int> k,vector<string> szk,vector<string> &szk_kodja)
{
    cout << "6. feladat - kodok.txt (output)" << endl;
    ofstream fki;
    string tmp;
    fki.open("kodok.txt");
    for(int i=0;i<szk.size();i++)       // végigmegyünk a szavak vektoron
    {
        tmp=szo_kodja(b,k,szk[i]);      // előállítjuk az aktuális szó kódját
        fki << tmp << endl;             // kiírjuk a fájlba
        szk_kodja.push_back(tmp);       // elhelyezzük a szavak_kodja vektorban
    }
    fki.close();
}

void F7_8_9(vector<string> szk,vector<string> szk_kodja)
{
    cout << "7. feladat" << endl;
    string kod;             // ezt a kódot adja majd meg a felhasználó
    cout << "Kérek egy kódot: ";
    cin >> kod;
    // szótár: kulcs a kód, szótárbejegyzés a szavak vektora, amik a kódhoz tartoznak (egy vagy több szó vektora)
    map<string,vector<string>> kod_es_szavai;
    set<string> kodhalmaz(szk_kodja.begin(),szk_kodja.end());   // a szavak kódja vektorból halmazt készítünk, ismétlődő kódok miatt
    for(auto k:kodhalmaz)       // a halamzon megyünk végig és veszünk egy-egy kódot
    {
        kodhoz_tartozo_szavak(szk,szk_kodja,k,kod_es_szavai);   // összeállítjuk a szótárbejegyzést (kulcs:kód, bejegyzés: vektor a szavaiból)
    }
    // 7. feladat kiírása
    cout << kod << ": ";
    for(auto szo:kod_es_szavai[kod])    // a kod kulcsú szótárelem kiírása a 7. feladathoz
        cout << szo << " ";
    cout << endl;
    cout << "8. feladat" << endl;
    int maxh=0;                         // 9. feladathoz kell, a legtöbb szóvt tartalmazó szótárelemhez
    map<string,vector<string>> maxi;    // ebben a szótárban lesz a legtöbb szóval rendelkező kód, mint kulcs és a szavak (mint érték a kulcshoz)
    string maxi_kod;                    // a legtöbb szóval rendelkező kód
    for(auto elem:kod_es_szavai)        // 111. sorban összeállított szótár bejárása
    {
        if(elem.second.size()>1)        // csak azokkal a szótárelemekkel foglalkozunk, ahol egy kódhoz több szó is tartozik
        {
            if(elem.second.size()>maxh) // itt keressük a maximális szószámmal rendelkező szótárelemet
            {
                // 9. feladat
                maxh=elem.second.size();
                maxi_kod=elem.first;
                maxi[maxi_kod]=elem.second;     // a szavak vektora a maxi_kodhoz rendelődik, mint kulcshoz
            }
            for(auto e:elem.second)      // egy szótárbejegyzés kiírása (ne feldjük, hogy ez egy vektor
            {
                cout << e << " : " << elem.first << "; ";   // szó majd a kulcs (kód) kiírása, mint a mintában...
            }
        }
    }
    cout << endl;
    cout << "9. feladat" << endl;
    cout << "Legtöbb szóhoz kapcsolódó kód: " << maxi_kod << endl;      // 9. feladat kiírási része
    cout << "Szavak: ";
    for(auto e:maxi[maxi_kod]) {cout << e << " ";}
    cout << endl;
}

int main()
{
    setlocale(LC_ALL,"");
    vector<int> kodok={2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,9};
    vector<char> betuk;
    vector<string> szavak, szavak_kodja;
    for(int i=97;i<123;i++) betuk.push_back(char(i));
    F1(betuk,kodok);
    F2(betuk,kodok);
    F3(szavak);
    F4(szavak);
    F5(szavak);
    F6(betuk,kodok,szavak,szavak_kodja);
    F7_8_9(szavak,szavak_kodja);
    return 0;
}
