[zap. test] 31.1. 17:30

Návštěvník

[zap. test] 31.1. 17:30

Příspěvek od Návštěvník »

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 :]
Veslar
Matfyz(ák|ačka) level I
Příspěvky: 19
Registrován: 20. 6. 2006 19:39

Příspěvek od Veslar »

Tak me to stihlo odhlasit, nez jsem to dopsal cele :] Takze jsem to byl ja, Veslar ;)

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 186 x
Trouble? I call it sport.
Uživatelský avatar
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

Příspěvek od starecml »

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 ;)
nj, kdo si vybere dobre cviceni, ma napul u zapoctu vyhrano :roll:

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 :)
MIKI
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

Příspěvek od MIKI »

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 :)
Tak by si to sem mohol dat. Celkom by ma zaujimalo to zavoralske riesenie. :shock: teda ten odkaz na predka vsetkych typov. ako by sa to kodilo? :roll:
Uživatelský avatar
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

Příspěvek od starecml »

Tak by si to sem mohol dat. Celkom by ma zaujimalo to zavoralske riesenie. :shock:
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...
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
Návštěvník

Re: domaci uloha

Příspěvek od Návštěvník »

MIKI píše:Tak by si to sem mohol dat. Celkom by ma zaujimalo to zavoralske riesenie. :shock: teda ten odkaz na predka vsetkych typov. ako by sa to kodilo? :roll:

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;
}
Odpovědět

Zpět na „2006“