#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#include <map>
#include <iterator>
typedef std::map<std::string, std::vector<std::string>> databazaSlov;
std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems)
{
std::stringstream ss(s);
std::string item;
while(std::getline(ss, item, delim))
{
elems.push_back(item);
}
return elems;
}
std::vector<std::string> split(const std::string &s, char delim)
{
std::vector<std::string> elems;
return split(s, delim, elems);
}
databazaSlov vytvorDatabazu(std::string slovnikFile)
{
databazaSlov hotovaDatabaza;
std::ifstream inputStream;
inputStream.open(slovnikFile);
if(!inputStream.is_open())
{
return hotovaDatabaza;
}
std::string line;
std::vector<std::string> slova;
while(inputStream.good())
{
std::getline(inputStream,line);
std::istringstream iss(line);
std::copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(), std::back_inserter<std::vector<std::string> >(slova));
//v tejto chvili mame zo suboru natahane slova
for(int i = 0; i < slova.size(); ++i) //v tejto sekcii z natahanych slov spravime mapu slovo + slabikovy vector
{
std::vector<std::string> slabiky;
std::string slovo = slova[i];
slabiky = split(slovo, '-');
std::string opraveneSlovo;
for(int j = 0; j < slovo.size(); ++j) //tento cyklus je na opravu slov - totiz po natahani je v map.first slovo aj s pomlckami, co je dobre kvoli parseru - po parsovani je nutne ich dat prec
{
char pismeno = slovo[j];
if(pismeno == '-')
{
continue;
}
else
{
opraveneSlovo.push_back(pismeno); //ano, po pismenach... no a co ? :D ked teraz uvazujem, mohol so mto lepit aj po slabikach....
}
}
slovo = opraveneSlovo;
hotovaDatabaza.insert(std::pair<std::string, std::vector<std::string>> (slovo, slabiky));
}
}
inputStream.close();
return hotovaDatabaza;
}
std::vector<std::string> nacitajVstup(std::string vstupFile) //v podstate zjednodusena verzia vyssej metody
{
std::ifstream inputStream;
std::vector<std::string> slova;
inputStream.open(vstupFile);
if(!inputStream.is_open())
{
return slova;
}
std::string line;
while(inputStream.good())
{
std::getline(inputStream,line);
std::istringstream iss(line);
std::copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(), std::back_inserter<std::vector<std::string> >(slova));
//v tejto chvili mame zo suboru natahane slova a to je vlastne cela veda ^.^
}
inputStream.close();
return slova;
}
bool jeSlovnikove(std::string slovo, databazaSlov slova) //toto nam matchuje aktualne slovo zo slovnikom - kolega Bednarek mi vynadal a vravel, ze ak pouzivam map, mam pouzivat aj find :D
{
databazaSlov::iterator it;
for(it = slova.begin(); it != slova.end(); ++it)
{
std::string match = it->first;
if(match == slovo)
{
return true;
}
}
return false;
}
std::vector<std::string> kdeVSlovniku(std::string slovo, databazaSlov slova) //tu som si to teda potom opravil... :) predtym tu bol tiez forcyklus s iteratorom ;)
{
databazaSlov::iterator it;
int vysl;
it = slova.find(slovo);
return it->second;
}
void zalamuj(databazaSlov wordData, std::vector<std::string> vstupnyText, std::string outName, int rowSize) //jadro celeho programu a vlastne jedina naozaj zlozita cast kodu
{
int spotrebovanaSirka = 0;
std::ofstream out;
out.open(outName, std::ios::trunc | std::ios::out);
for(int i = 0; i < vstupnyText.size(); ++i) //prebehneme cely zoznam slov zo vstupu
{
std::string daneSlovo = vstupnyText[i];
if(!jeSlovnikove(daneSlovo, wordData)) //tu sa zisti, ci aktualne slovo je v slovniku
{
if(daneSlovo.size() >= rowSize && spotrebovanaSirka == 0) //osetrenie pre neslovnikove slova, ktore su vacsie ako maximalna sirka riadku - tie rovno flusnem von
{
out << daneSlovo << "\n";
spotrebovanaSirka == 0;
continue;
}
spotrebovanaSirka += daneSlovo.size() + 1; //+1 pre medierku
if(spotrebovanaSirka > rowSize) //dalsi riadok + znamienko - preliali sme sa cez hranicu riadku, takze hodime new line, spotrebu dame na nulu a dekrementujeme - to nam zaruci, ze sa k nevhodnemu slovu vratime v dalsom kole a nevynechame ho
{
out << "\n";
--i;
spotrebovanaSirka = 0;
}
else
{
daneSlovo += " "; //pridame medzierku
out << daneSlovo; //vypise aj s medzerou;
}
}
else//nie je slovnikove a mozeme lamat :3
{
std::vector<std::string> slabikySlova = kdeVSlovniku(daneSlovo, wordData); //toto povodne vracalo iterator, kde sa nachadza slovo v slovniku - boli s tym problemy, tak som si rozmyslel, ze mozem rovno vratit vector slabik :)
spotrebovanaSirka += daneSlovo.size() + 1; //+1 pre medierku
if(spotrebovanaSirka >= rowSize - 1) //dalsi riadok + znamienko - znova, ak cele slovo nezmestim, musim pozriet ci zmestim nejaky substring slabik
{
int sirkaNecelehoSlova = 0;
spotrebovanaSirka -= daneSlovo.size() + 1; //zhodme spotrebovanu sirku zase dole...
for(int x = 0; x < slabikySlova.size(); ++x) //preiterujeme cez slabiky daneho slova
{
std::string slabika = slabikySlova[x];
sirkaNecelehoSlova += slabika.size();
spotrebovanaSirka += sirkaNecelehoSlova;
if(spotrebovanaSirka > rowSize) //dalsi riadok + znamienko //ak to nejde s danou slabikou, flusneme von pomlcku a new line
{
if(x != 0) //toto je osetrenie, aby nam nevznikali pomlcky pred prvou slabikou
{
out << "-\n";
--x;
}
else
{
out << "\n";
--x; //a dekrementujeme vodiacu premennu pre slabiky - efekt ako vyssie pre cele slova.
}
spotrebovanaSirka = 0;//treba aj dovypisovat slovo
sirkaNecelehoSlova = 0;
//slovo mi ale dovypisuje v pohode ten cyklus vyssie - tuna prehodim spotrebu na nulu a on sa vrati a zisti, ze spotreba je nulova a bude pisat dalej...
//prejde do else vetvy a vypise zvysok slova ^^ ak sa da... ak nie pozalamuje a tak
}
else
{
out << slabikySlova[x]; //vypise aj s medzerou;
if(x == slabikySlova.size() - 1) //ano, ak sme dopisali poslednu slabiku slova, prosime si za to aj medzeru... :)
{
out << " ";
++spotrebovanaSirka; //spotreba narastla presne o 1 medzeru
}
}
}
}
else //neslovnikove slovo, ktore zmestim - flusnem von
{
daneSlovo += " "; //pridame medzierku
out << daneSlovo; //vypise aj s medzerou;
}
}
}
out.close();
return;
}
int main()
{
//nacitat slovnik do databazy slov - asi map<string, vector>
//nakrajane slova medzerami, v slove su '-', teda nakrajam to na slova a slova nakrajam na slabiky
//nacitat vstup do vectoru
//
//int rowSize = 3;
int rowSize = 11;
//testnite si to pre oba rowSize, a potom este pre 15 :)
databazaSlov wordData;
std::vector<std::string> vstupnyText;
std::string vstup = "input.txt";
std::string lang = "slovnik.txt";
std::string vystup = "von.txt";
//bolo nam dovolene zadratovat nazvy suborov natvrdo
wordData = vytvorDatabazu(lang);
//POZOR !!!!!!! v databaze su pomlcky, dat prec ! :) -- DONE !!!
//teraz nacitanie vstupu
vstupnyText = nacitajVstup(vstup);
//vytvorenie vystupu
zalamuj(wordData, vstupnyText, vystup, rowSize);
std::cout << "lol"; //toto lol je tu kvoli krokovaniu :D
return 0;
}