Jste zde

Zajímavé úlohy pro programátory v C a C++ #4

Zkouškové skončilo a já tak mohu v klidu přinést další zajímavou úlohu. Tentokrát budeme programovat pouze v C++ a cílem bude vytvořit program, který bude provádět zadanou činnost a použít při tom co nejmenší počet příkazů.

Zadání

Doplňte do následujícího kódu příkazy tak, aby daný program po přeložení a spuštění četl slova (složená z položek typu char, uvažujte pouze ASCII znaky) oddělená bílými znaky ze standardního vstupu až do konce vstupu a všechna je vytisknul seřazená od "nejmenšího" po "největší" (operátorem porovnání dvou stringů je <, čili lexikografické uspořádání), každé slovo na jednom řádku. Cílem je, aby výsledný program (zdrojový kód, přesněji tělo funkce main()) obsahoval co nejmenší počet příkazů, takže pokud už někdo přijde s řešením, můžete klidně zkusit jeho program zkrátit o jeden příkaz atd. :).

// Zde doplňte hlavičkové soubory
 
// Zde doplňte případné deklarace/direktivy using pro zčitelnění kódu
 
int main() {
    // Zde doplňte tělo programu
}

Ukázkový výstup

$ ./program <<< "beta alfa gamma delta"
alfa
beta
delta
gamma

Omezení

Nesmíte používat ternární operátor a operátory čárka, &&, ||, and, or. Kromě hlavičkových souborů (pouze ze standardní C++ knihovny/STL) a případných deklarací/direktiv using pro zčitelnění kódu nedoplňujte žádný kód mimo tělo funkce main(). Řešení musí být implementačně nezávislé (tj nepoužívejte konstrukty s nespecifikovaným či nedefinovaným chováním) a přeložitelné podle standardu C++98.

Řešení

Zadanou úlohu lze vyřešit programem, jehož tělo funkce main() obsahuje 2 příkazy.

#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
#include <set>
 
using namespace std;
 
int main() {
	multiset<string> words((istream_iterator<string>(cin)), istream_iterator<string>());
	copy(words.begin(), words.end(), ostream_iterator<string>(cout, "\n"));
}

Je použit kontejner multiset, protože na vstupu se může vyskytovat několikrát stejné slovo a také proto, že automaticky řadí vstupní data (defaulně pomocí binárního predikátu less<>, což nám vyhovuje). Je využit konstruktor, který čte data z rozsahu 2 iterátorů. No, a druhý příkaz je standardní způsob výpisu obsahu kontejneru na výstup.

Poznámka pro ty, kteří se podivují nad zdánlivě nadbytečnými závorkami v prvním příkazu. Zkuste si je odstranit - program se pak nepřeloží, protože první příkaz nebude vytvářet objekt, ale deklarovat funkci... C++ je holt roztodivný jazyk :). Zájemce poprosím, aby si přečetli pátý komentář ("You are the victim of..".) z tohoto threadu, který popisuje, v čem je přesně problém.

Komentáře

Nikoho nenapada zadne reseni tohoto ukolu? To se mi nechce verit :).

#include <string>
#include <iostream>
#include <set>
 
typedef std::multiset<std::string> container;
 
int main() {
	container words;
	std::string current;
	while (std::cin >> current) {
		words.insert(current);
	}
 
	for (container::iterator it = words.begin(); it != words.end(); ++it) {
		std::cout << *it << std::endl;
	}
}

Diky, reseni je spravne. Pocet prikazu: 8.

#include <string>
#include <iostream>
#include <iterator>
#include <set>
 
typedef std::multiset<std::string> container;
 
int main() {
        container words;
        std::string current;
        while (std::cin >> current) {
                words.insert(current);
        }
 
        copy(words.begin(), words.end(), std::ostream_iterator<std::string>(std::cout,"\n"));
}

Diky, pouzita uprava snizuje pocet prikazu na 5.

Podari se to nekomu udelat na mene nez 5 prikazu?

#include <string>
#include <iostream>
#include <set>
#include <iterator>
 
typedef std::multiset<std::string> container;
 
int main() {
	container words;
	copy(std::istream_iterator<std::string>(std::cin),
			std::istream_iterator<std::string>(),
			std::inserter(words, words.begin()));
	copy(words.begin(), words.end(), std::ostream_iterator<std::string>(std::cout,"\n"));
}

Sikovna uprava - pocet prikazu: 3.

Podari se to nekomu jeste prekonat? :)

Zveřejnil jsem moje komentované řešení čtvrtého úkolu.

Přidat komentář