Ruby po kapkách – úkoly a řešení pro 3. díl seriálu

4. března 2009

Web je interaktivní médium. A dá se toho využít ke spokojenosti čtenářů i autorů. Umožňuje mi to reagovat na ohlasy požadující jednak náměty k procvičení popisovaných rysů Ruby a také ukázková řešení zadaných úkolů. Abych příliš nenarušoval strukturu článků, rozhodl jsem se zatím uveřejňovat úkoly zvlášť.

Na konci třetího dílu byly návrhy na filtry, které by mělo být možné zrealizovat pouze s využitím informací publikovaných v prvních třech článcích. První úlohou bylo napsat filtr, který spočítá řádky vstupu. To je vcelku jednoduché a docílíme toho například následujícím krátkým prográmkem.

n = 0
while gets
n = n + 1
end
puts n

Za povšimnutí stojí dvě věci. První je inicializace proměnné n. V prvním řádku ji nastavíme na hodnotu 0. Pokud bychom to neudělali, došlo by k chybě v okamžiku, kdy bychom se k ní pokusili přičíst jedničku. Interpret by totiž takové označení proměnné neznal. Druhou věcí je zapomínání návratové hodnoty z volání gets. V příkladech filtrů jsme načtený řádek vždy ukládali do proměnné. V tomto případě by nám to k ničemu nebylo, takže návratovou hondotu využíváme jen pro test ukončovací podmínky cyklu. Připomínám, že ukončení nastane v okamžiku, kdy program narazí na konec souboru a gets vrátí hodnotu nil.

Druhým problémem byl filtr, který načítá na každém řádku dvě čísla oddělená mezerou a vypisuje jejich součet. Zde je zřejmé, že každý řádek potřebujeme načíst, rozdělit na dvě části oddělené mezerou a sečíst číselnou hodnotů těchto dvou řetězců. Využijeme k tomu metodu index třídy String a indexovací operátory. Řešení může vypadat například takto.

while line = gets
h = line.index(‚ ‚)
a = line[0..(h -1)].to_f
b = line[(h + 1)..-1].to_f
puts a + b
end

Stručně řečeno: každý řádek načteme do proměnné line, do proměnné h pak uložíme pozici mezery nalezenou voláním metody index a nakonec pomocí indexování získáme sčítance a a b a vypíšeme jejich součet. Samotnou mezeru do zpracování nechceme, proto při indexování řetězce od její pozice přičítáme a odčítáme jedničku.

Tento kód nevypadá příliš elegantně. Je to ale způsobeno snahou o využití co nejjednodušších prostředků, které nám Ruby poskytuje. Pro zvýšení estetického zážitku uvedu zápis ekvivaletní funkčnosti poněkud pokročilejšími technikami. Již brzy však uvidíme, že zvládnutí těchto technik není nic těžkého.

while line = gets
puts line.split(‚ ‚).inject { |s, n| s.to_f + n.to_f }
end

Mimochodem toto řešení funguje pro libovolný počet čísel oddělených mezerou.

Posledním úkolem bylo vytvoření filtru, který vypisuje poslední slovo z každého řádku vstupu, kde slova jsou oddělena mezerou a vždy jsou aspoň dvě. Máme-li použít jen informace z článků, budeme pravděpodobně muset opět nějak použít metodu index k hledání mezery. Nicméně tentokrát hledáme poslední mezeru, takže si musíme pomoci drobným trikem – obrátíme řetězec naruby, vezmeme z něho část do první mezery a výsledek pak převrátíme zpátky. Použijeme k tomu metodu reverse.

while line = gets
r = line.reverse
puts r[0..(r.index(‚ ‚) – 1)].reverse
end

Kdo zapátral v dokumentaci ke třídě String nejspíš objevil metodu rindex, která funguje stejně jako index, ale hledá od konce řetězce. Kód by pak mohl vypadat následovně.

while line = gets
puts line[(line.rindex(‚ ‚) + 1)..-1] end

Když předběhneme do příštího dílu, mohli bychom to napsat takto hezky.

while line = gets
puts line.split(‚ ‚).last
end

Povšimněte si, že tento kód lze číst téměř jako anglickou prózu.

Na závěr pár námětů k zamyšlení do příště. Předpokládejme, že uživatel zadá na STDIN buď slovo „ano“ nebo slovo „ne“ a stiskne enter (pro zjednodušení nebudeme ošetřovat žádné jiné stavy ani potenciální chyby). Zkuste dopsat chybějící první část následujícího kódu. Vymyslete několik variant a zkuste najít řešení, kde byste nepoužili podmínku. Budete-li chtít, můžete doplnit situaci, kdy není zadáno ani jedno ze zmíněných slov.


if p
puts „Bylo to ANO!“
else
puts „Bylo to NE!“
end

Jako druhý úkol zkuste vytvořit filtr, který bude načítat slovník a vypisovat palindromy – slova, která jsou stejná, i když je čteme odzadu. Slovník bude textový soubor, kde je na každém řádku jedno slovo. Pokud si chcte program vyzkoušet v praxi, zkuste hledat slovníky například tímto dotazem do Google: http://www.google.cz/search?hl=cs&q=%C4%8Desk%C3%BD+wordlist&btnG=Hledat&lr=

A do třetice všeho dobrého napište program, který vypíše všechna prvočísla menší než 100. Opět vyzkoušejte více variant.

Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *