Zdravim!
Tak dnesni zapoctovy test probihal velmi zajimave :] Zacali jsme o pul hod pozdeji, cas na vypracovani 3hodiny. Zadavajicim byl tentokrat pan Zaoral a vymyslel si hezky priklad :] Tady je:
Meli jsme napsat program jmenem nsort, ktery tridil nasledujici typy souboru:
Parametry programu:
nsort [-i vstupnisoubor] [-o vystupnisoubor] [-t separator] N1 S3 N20 S2 ...
kde parametry -i -o -t byly nepovinne, pokud nebyl uvedenny separator, byl to implicitne '#', pokud nebyl uvedenny vstupni / vystupni soubor, cetlo / zapisovalo se do cin/ cout.
Vstupni soubor vypadal napriklad nejak takto:
12;50;adsfew;8342;neco1
10;7;xxxx;;neco2
10;8;yyyy;89;neco3
....
vstupni parametry N1 S3 N20 S2 rikali nasledujici vec:
zesortuj soubor podle sloupce 1, ve kterem je integer, pokud jsou tam nejake stejne zaznamy tak podle sloupce 3, ve kterem je string, pokud jsou stejne.... atd. poradi sloupcu mohlo byt libovolne na prikazove radce.
Pokud nebyl dany sloupec urcen typem tim, co je na prikazove radce, tak jsme si ho mohli uchovavat libovolne. ALE ty sloupce, co urcene byly jsme MUSELI uchovavat v programu pod danym typem - coz byl pro vetsinu nejspise kamen urazu.
Nas program musel byt jednodusse rozsiritelny na libovolny jiny typ, takze zadna trida ve ktere by byly vektory vsech typu a byl by vyuzity vzdy jen jeden. Implementovat jsme meli ale jenom integer a string.
Pocet sloupcu, radku mohl byt nekonecny....nemelo to pri zadnem vstupu spadnout apod...no uprimne si myslim, ze to nedodrzel nikdo - navic, pokud ja vim, to nejak zvlast nekontroloval :]
mno potom co napsal to zadani jsem si rikal, ze to nebude az TAK tezke...
ale po 2 hodinach co neuspesne odeslo cca 5 lidi bylo jasne, ze to nebude ani vubec jednoduche. Sice Zaoral hyril vtipem, ze to jde udelat za 20-30min...mno rad bych videl jak :] Nejspis jsem to delal zbytecne slozite, ale po 2hodinach a 50ti minutach jsem vitezoslavne odchazel jako prvni...a ostatni nevypadali moc nadsene...no ale treba nastavil nejaky cas navic a nakonec nebyl az tak prisny :] [ostatni at doplni :]
Mala rada na zaver: nedavejte si zapocet na 6 vecer :]
[zap. test] 31.1. 17:30
Tak me to stihlo odhlasit, nez jsem to dopsal cele :] Takze jsem to byl ja, Veslar ![Wink ;)](./images/smilies/icon_wink.gif)
Tady je muj (prasacky, od zapoctu neupraveny) kod [ neeee ze bych to neumel liiip, ale to viiite, casu malo :]]] , ktery ale nakonec na uspech stacil.... [a to se pocita :]
Jo, jeste jsem zapomnel napsat, ze internet byl odpojeny, ale flaska se stahnutym CPP reference me zachranila :]
BTW: jak to nakonec dopadlo s ostatnima?
![Wink ;)](./images/smilies/icon_wink.gif)
Tady je muj (prasacky, od zapoctu neupraveny) kod [ neeee ze bych to neumel liiip, ale to viiite, casu malo :]]] , ktery ale nakonec na uspech stacil.... [a to se pocita :]
Jo, jeste jsem zapomnel napsat, ze internet byl odpojeny, ale flaska se stahnutym CPP reference me zachranila :]
BTW: jak to nakonec dopadlo s ostatnima?
- Přílohy
-
- main.cpp
- (6.87 KiB) Staženo 188 x
Trouble? I call it sport.
- starecml
- Matfyz(ák|ačka) level I
- Příspěvky: 24
- Registrován: 25. 9. 2006 18:06
- Typ studia: Informatika Bc.
- Kontaktovat uživatele:
domaci uloha
ja bych jenom rad podotknul, ze presne tento priklad nam daval p.Zavoral na cvicenich jako domaci ulohu. Takze pokud bych tam sel, tak bych to dal tak za tech 20 min ![Wink ;)](./images/smilies/icon_wink.gif)
nj, kdo si vybere dobre cviceni, ma napul u zapoctu vyhrano![Rolling Eyes :roll:](./images/smilies/icon_rolleyes.gif)
jinak znam i originalni (Zavoralovske) reseni, ktere je fakt vychytane... neco ve smyslu, ze na trizeni se pouzije multimapa vektoru, kde ve vektoru jako polozka je odkaz na predka vsech typu... Jedine co je potreba napsat je operator < pro multimapu aby vedela jak to tridit![Smile :)](./images/smilies/icon_smile.gif)
![Wink ;)](./images/smilies/icon_wink.gif)
nj, kdo si vybere dobre cviceni, ma napul u zapoctu vyhrano
![Rolling Eyes :roll:](./images/smilies/icon_rolleyes.gif)
jinak znam i originalni (Zavoralovske) reseni, ktere je fakt vychytane... neco ve smyslu, ze na trizeni se pouzije multimapa vektoru, kde ve vektoru jako polozka je odkaz na predka vsech typu... Jedine co je potreba napsat je operator < pro multimapu aby vedela jak to tridit
![Smile :)](./images/smilies/icon_smile.gif)
-
- Matfyz(ák|ačka) level III
- Příspěvky: 186
- Registrován: 10. 12. 2004 22:35
- Typ studia: Informatika Bc.
- Kontaktovat uživatele:
Re: domaci uloha
Tak by si to sem mohol dat. Celkom by ma zaujimalo to zavoralske riesenie.starecml píše:jinak znam i originalni (Zavoralovske) reseni, ktere je fakt vychytane... neco ve smyslu, ze na trizeni se pouzije multimapa vektoru, kde ve vektoru jako polozka je odkaz na predka vsech typu... Jedine co je potreba napsat je operator < pro multimapu aby vedela jak to tridit
![Shocked :shock:](./images/smilies/icon_eek.gif)
![Rolling Eyes :roll:](./images/smilies/icon_rolleyes.gif)
- starecml
- Matfyz(ák|ačka) level I
- Příspěvky: 24
- Registrován: 25. 9. 2006 18:06
- Typ studia: Informatika Bc.
- Kontaktovat uživatele:
Re: domaci uloha
jaj tak to sa velice omluvam, ale ja sem to neprogramoval. Hned vysvetlim proc: Ono, my jsme delali dve male domaci ulohy, a to gumove pole a nekonecny int, z cehoz na konci vzniklo nekonecne pole nekonecnych intu...Tak by si to sem mohol dat. Celkom by ma zaujimalo to zavoralske riesenie.
No a to jsme meli poslat p.Zavoralovi a on to ohodnotil. Pokud vsak nekdo neobstal v jeho hodnoceni, tak delal nahradni ulohu, coz byla prave tato uloha... Jelikoz ja jsem patril mezi ty stastlivce, kteri ji nemuseli delat, tak mohu pouze pozadat nejakeho kolegu, ktery to delal, aby to sem soupl...
takze se omlouvam, ale zadosti vyhovet nemohu. Reseni vim, protoze nam ho Zavoral rikal na poslednim cviceni...
starecml
Re: domaci uloha
MIKI píše:Tak by si to sem mohol dat. Celkom by ma zaujimalo to zavoralske riesenie.teda ten odkaz na predka vsetkych typov. ako by sa to kodilo?
Kód: Vybrat vše
#include <iostream>
#include <fstream>
#include <iterator>
#include <string>
#include <set>
#include <vector>
#include <map>
#include <list>
#include <functional>
#include <algorithm>
#include <cstdlib>
using namespace std;
/*
msort [-i fn] [-o fn] [-t tabchar] { TN }
T: S, N
N: cislo sloupce
reprezenace podle typu sortu - abstract num, int/string/...
sloupce jedne radky indexovat -> vector sloupcu
slicing -> vector ukazatelu
ma se to setridit - rovnou multiset (muzou tam byt stejne radky) s vlastnim porovnavanim
*/
///// hodnoty sloupcu
class ColBase { // abstraktni predek - umi se klonovat a porovnavat
public:
ColBase() {}
virtual ColBase* clone( void) = 0;
virtual ~ColBase() {}
virtual bool operator<( const ColBase& col) const = 0;
virtual void print( void) const = 0;
};
template <class T> class Col : public ColBase { // template - konkretni instanciace pro string a long
private:
typename T val;
public:
Col<T>() : val( 0) {}
Col<T>( T val_) : val( val_) {}
ColBase* clone( void) { return new Col<T>( val); }
~Col<T>() {}
bool operator<( const ColBase& col) const
{ return this->val < dynamic_cast<const Col<T>*>(&col)->val; }
void print( void) const;
};
///// sloupce a radky
class Column { // jedna hodnota sloupce
private:
ColBase* cb; // slicing - ukazatel na abstraktniho predka
public:
Column() : cb( 0) {}
Column( ColBase* cb_) : cb( cb_) {} // vytvari se vlozenim alokovaneho konkretniho typu
Column( const Column& col) { cb = col.cb->clone(); } // prvek vectoru - musi se umet kopirovat
Column& operator=( const Column& col) { delete cb; cb = col.cb->clone(); return *this; }
bool operator<( const Column& col) const { return *this->cb < *col.cb; }
virtual ~Column() { delete cb; }
void print( void) const { cb->print(); }
};
class Row { // jedna radka zpracovanych hodnot sloupcu dle typu
private:
vector<Column> v; // jednotlive sloupce
public:
Row() {}
~Row() { v.clear(); }
void print( void) const;
void add( ColBase* cb) { v.push_back( *new Column( cb)); }
friend class RowLess;
};
class RowLess { // porovnani dvou radek pro MyFile
public:
bool operator() ( const Row& r1, const Row& r2);
};
///// cely soubor
typedef map<int,char> TypeMap; // index sloupce -> typ (pouze pro specifikovane)
typedef list<int> SortOrder; // seznam indexu sloupcu pro trideni
typedef multiset< Row, RowLess> MyFile; // vnitrni reprezentace celeho souboru - usporadane radky
///// globalni promenne
class App {
public:
istream *in; // vstupni proud (cin nebo dynamicky alokovany)
ostream *out; // vystupni proud (cout nebo dynamicky alokovany)
char tab; // oddelovac
MyFile file; // cely soubor
TypeMap coltype; // typy sloupcu
SortOrder sort; // trideni
int columns; // nutny pocet sloupcu (dle spec. trideni)
App() : tab( '\t'), columns(0), in(0), out(0) {}
~App() {
if( in != &cin) delete in;
if( out != &cout) delete out;
}
};
App a;
///// pomocne funkce
// porovnavani dvou radek
// postupne testuju nerovnost odpovidiajicich sloupcu podle definovaneho trideni
bool RowLess::operator() ( const Row& r1, const Row& r2)
{
SortOrder::iterator i;
for( i = a.sort.begin(); i != a.sort.end(); i++) {
if( r1.v[*i] < r2.v[*i])
return true;
if( r2.v[*i] < r1.v[*i])
return false;
}
return false;
}
// metody pro tisk - tela musi byt az tady kvuli a.out
template <class T> void Col<T>::print( void) const { *a.out << val << a.tab; }
void Row::print( void) const { for_each( v.begin(), v.end(), mem_fun_ref(&Column::print)); *a.out << endl; }
// vlastni zpracovani
void init_file( int argc, char** argv) // nacteni parametru, otevreni souboru
{
string s;
int col;
ifstream *in = 0;
ofstream *out = 0;
while( *++argv) {
s = *argv;
if( s[0] == '-') { // nepovinne parametry
switch( s[1]) {
case 'i':
case 'I': // vstup
if( in) throw( 4);
in = new ifstream;
in->open( s.substr(2).c_str());
if( ! *in) throw( 5);
a.in = in;
break;
case 'o':
case 'O': // vystup
if( out) throw( 5);
out = new ofstream;
in->open( s.substr(2).c_str());
if( ! *out) throw( 6);
a.out = out;
break;
case 't':
case 'T': // oddelovac
if( ! s[2]) throw( 7);
a.tab = s[2];
break;
default:
throw( 3);
}
} else { // trideni
if( s.length() < 2) throw( 9);
col = strtol( s.substr(1).c_str(), 0, 10);
a.coltype[col] = s[0]; // ulozit typ sloupce
a.sort.push_back( col); // trideni podle dalsiho sloupce do seznamu
if( col + 1 > a.columns) // pocet nutnych sloupcu - pro kontrolu
a.columns = col + 1;
}
}
if( ! in) // default cin/cout
a.in = &cin;
if( ! out)
a.out = &cout;
}
void read_file( void) // zpracovani vstupu - kompletni logika
{
string buf; // prectena radka
string::iterator b, e; // parsovaci iteratory sloupce
int col; // identifikator sloupce
Row* r; // dynamicky tvorene radky
while( getline( *a.in, buf)) { // nacist radku
r = new Row;
b = e = buf.begin(); // zacatek retezce
for( col = 0; e != buf.end(); col++) {
e = find( b, buf.end(), a.tab); // oddelovac nebo konec radky
switch( a.coltype[col]) { // pozor - vzdy vytvoreni prvku, reference na existujici
case 'N': {
long n = strtol( string(b,e).c_str(), 0, 10);
r->add( new Col<long>( n)); // pridat do radky
} break;
case 'S':
case 0: { // dotaz do mapy vytvori prvek s default constructorem
string s( b, e); // retezec (konstruktor s intervalem iteratoru)
r->add( new Col<string>( s)); // pridat do radky
} break;
default:
throw( 8);
}
b = e; // posunout iterator
if( e != buf.end()) // preskocit oddelovac
b++;
}
if( col < a.columns) throw( 11); // prilis malo sloupcu
a.file.insert( *r); // radka hotova - zatridit (podle usporadani)
}
}
///// main
int main( int argc, char** argv)
{
try {
init_file( argc, argv);
read_file();
for_each( a.file.begin(), a.file.end(), mem_fun_ref(&Row::print));
} catch( int n) {
cout << "
Znama chyba " << n << endl;
} catch(...) {
cout << "
Podivna chyba" << endl;
}
return 0;
}