<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ondra[sej] Blog</title>
	<atom:link href="http://www.ondrejsykora.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ondrejsykora.com/blog</link>
	<description></description>
	<lastBuildDate>Sun, 21 Mar 2010 13:17:49 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Typy chyb v programech v Prologu</title>
		<link>http://www.ondrejsykora.com/blog/2010/03/21/typy-chyb-v-programech-v-prologu/</link>
		<comments>http://www.ondrejsykora.com/blog/2010/03/21/typy-chyb-v-programech-v-prologu/#comments</comments>
		<pubDate>Sun, 21 Mar 2010 12:33:05 +0000</pubDate>
		<dc:creator>Ondřej Sýkora</dc:creator>
				<category><![CDATA[Prolog]]></category>

		<guid isPermaLink="false">http://www.ondrejsykora.com/blog/?p=166</guid>
		<description><![CDATA[Jak potvrdí asi každý, kdo se programováním zabýval delší dobu, většina programovacích jazyků si je hodně podobná. Existují sice odlišnosti v tom, jaké používají závorky, čím oddělují příkazy, jestli (jak) podporují objektové programování nebo jak přistupují ke správě paměti. To jsou ale jen kosmetické záležitosti a drobná vylepšení klasického &#8220;imperativního&#8221; stylu výpočtu, kdy počítač provádí [...]]]></description>
			<content:encoded><![CDATA[<p>Jak potvrdí asi každý, kdo se programováním zabýval delší dobu, většina programovacích jazyků si je hodně podobná. Existují sice odlišnosti v tom, jaké používají závorky, čím oddělují příkazy, jestli (jak) podporují objektové programování nebo jak přistupují ke správě paměti. To jsou ale jen kosmetické záležitosti a drobná vylepšení klasického &#8220;imperativního&#8221; stylu výpočtu, kdy počítač provádí jeden příkaz (instrukci) za druhým tak, jak je programátor zapsal. </p>
<p>To ale není jediný možný přístup k tvorbě programů. Teorie (a koneckonců i praxe) říkají, že stejné výpočetní síly jde dosáhnout také pomocí vhodně složené sady logických formulí (&#8220;Logické programování&#8221;). Nabízí se otázka, jestli &#8211; a jak &#8211; způsob programování ovlivní, jaké chyby se v programu mohou vyskytnout. Logické programování ale je spíš koncept výpočtu než určitý programovací jazyk, proto se ve zbytku textu omezím na vyprávění o jazyku Prolog, který z tohoto konceptu vychází.<br />
<span id="more-166"></span><br />
Pravda ale také je, že největší inspirace k sepsání tohoto textu je cvičení z Neprocedurálního programování, které vedu, a kde se začíná právě Prologem. Seznam typů chyb tak je z větší částí soupis chyb, na které jsem narazil během opravování domácích úkolů. Některé z nich jsem čekal, jiné (hlavně ty z první kategorie) mě dost překvapily.</p>
<h3>Překlepy, syntaktické chyby a chyby při překladu</h3>
<p>K této kategorii chyb není moc co říkat, tady se Prolog v ničem neliší od imperativních programovacích jazyků. Prolog má, stejně jako jiné programovací jazyky, určitou syntaxi, kterou není složité porušit. Asi největší problém je zvyknout si na to, že velké/malé první písmeno identifikátoru rozhoduje o jeho typu (proměnná/konstanta). Na druhou stranu, překladač na takové chyby upozorní, takže jejich oprava je triviální.</p>
<p>To samé platí pro překlepy v názvech predikátů. Prolog sice není staticky kompilovaný jazyk a za běhu jde přidávat nebo odebírat pravidla a fakty (program se tak může sám modifikovat), ale pokud váš program obsahuje dotazy na neexistující predikáty, tak překladač vypisuje varování. Všechna varování sice jde vypnout, ale pokud si pod sebou někdo cíleně řeže větev&#8230;</p>
<p>Překlep v názvu proměnné je o trochu horší. Proměnné v Prologu jsou deklarované prostě tím, že jsou někde v programu zapsané. Situaci trochu zachraňují varování překladače v případě, že je některá z proměnných použitá jen jednou, ale ani to nemusí stačit. Nepříjemné je i to, že styl programování v Prologu vede k velkému množství pomocných proměnných a kde je hodně proměnných, tam rychle vzniká chaos.</p>
<h3>Logické chyby</h3>
<p>V případě logických chyb opět nejde o nic, co by v jiných jazycích nebylo. Špatný &#8211; nebo špatně zapsaný algoritmus, konstanta sem, konstanta tam, špatně zapsaná podmínka&#8230; prostě nic, co by v jiných jazycích nebylo. A stejně jako v jiných jazycích, ani v Prologu překladač s hledáním logických chyb moc nepomůže. Koneckonců, jak říká teorie, překladač může odhalit zjevné chyby, ale jinak toho moc nezmůže. A stejně jako typy chyb, i způsob boje proti nim je zcela tradiční.</p>
<p>Kapitola sama pro sebe jsou nekonečné cykly. I v programu, který je jinak úplně správně, není problém vyrobit nekonečný cyklus vhodným přehozením podmínek. V logickém programování jako výpočetním modelu se při vždy (nedeterministicky) vybere správný postup výpočtu. V praxi to je trochu problém, protože orákulum pro správný nedeterministický výběr stále ještě nepatří k mezi běžně dostupný hardware. Pořadí, v jakém Prolog provádí vyhodnocování proto je pevně dané a tak stačí nešťastné pořadí predikátů&#8230;</p>
<h3>Chyby způsobené nejednoznačností</h3>
<p>Třetí typ chyb by sice správně měl patřit pod &#8220;Logické chyby&#8221;, ale protože jde o záležitos specifickou pro Prolog a jeho způsob výpočtu, nechám je samostatně. Koneckonců, jde o článek o Prologu, ne?</p>
<p>Z nedeterministické povahy výpočtu v logickém programování vyplývá také další typ chyby. Volbu &#8220;správného&#8221; směru výpočtu nejde (na současných počítačích) z principu implementovat přímo, proto je v Prologu nahrazena backtrackingem. Pokud v některém kroce výpočet nemůže pokračovat dál, není to žádný problém, Prolog se vrátí o krok zpět a (opět podle deterministických pravidel) zkusí jinou větev výpočtu. Nejlépe je toto chování vidět přímo v příkazovém řádku interpretu Prologu &#8211; po nalezení odpovědi na dotaz Prolog čeká na vaši reakci a pokud odpověď zamítnete (tj. řeknete mu, že výpočet selhal), zkusí backtrackovat, aby našel další možné odpovědi.</p>
<p>To samo o sobě ještě není žádný problém. Naopak jde o základní vlastnost, která dělá Prolog Prologem. Problém je, že programátorům, kteří s Prologem začínají (ale nejen jim), se často stane, že na tuto vlastnost při psaní kódu a při jeho testování zapomenou. Často tak vznikne predikát, který sice dá správnou první odpověď, ale pokud ho přinutíte backtrackovat, budete se divit. Situace, které mohou nastat jsou různé. Začínají neškodným zopakování vrácené hodnoty. To sice zdrží výpočet, ale jinak žádné škody nenapáchá. Horší je, pokud takový predikát vrací správnou hodnotu nekonečně krát, nebo při backtrackování vrací nesprávné hodnoty &#8211; to už efektivně znamená buď zacyklený program, nebo celkově chybný výpočet.</p>
<p>V zásadě jsou dvě možnosti, jak se těmto chybám bránit. První z nich je dopsat vstupní podmínky ke každé variantě predikátu, aby pro každý vstup bylo jednoznačně určeno, ke kterém predikátu patří. Druhá možnost je vhodně umístěný operátor řezu. Jaká varianta je lepší záleží na konkrétní situaci &#8211; operátor řezu může vést k efektivnějšímu programu, na druhou stranu se tím ztrácí přehlednost a ještě víc se zvedá význam správného uspořádání pravidel. Může se stát, že nejednoznačnost v určité úloze nevadí, protože na backtracking nikdy nedojde. Ale i v takovém případě je dobré na možné problémy s nejednoznačností myslet, protože tyhle okamžiky &#8220;nikdy&#8221; nastávají až nečekaně často.</p>
<p>Na závěr jen krátký (učebnicový) příklad, jak nevinně může taková chyba vypada.</p>
<p><code>removeAll(_, [], []).<br />
removeAll(X, [X|Xs], Ys) :- removeAll(X, Xs, Ys).<br />
removeAll(X, [Y|Xs], [Y|Ys]) :- removeAll(X, Xs, Ys).</code></p>
<p>Oprava by mohla vypadat například takto:</p>
<p><code>removeAll(_, [], []).<br />
removeAll(X, [X|Ys], Ys) :- removeAll(X, Xs, Ys).<br />
removeAll(X, [Y|Xs], [Y|Ys]) :- X \= Y, removeAll(X, Xs, Ys).</code></p>
<p>nebo s použitím operátoru řezu takto:</p>
<p><code>removeAll(_, [], []).<br />
removeAll(X, [X|Xs], Ys) :- !, removeAll(X, Xs, Ys).<br />
removeAll(X, [Y|Xs], [Y|Ys]) :- removeAll(X, Xs, Ys).</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ondrejsykora.com/blog/2010/03/21/typy-chyb-v-programech-v-prologu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zkušenosti po měsíci s Mackem</title>
		<link>http://www.ondrejsykora.com/blog/2009/05/15/zkusenosti-po-mesici-s-mackem/</link>
		<comments>http://www.ondrejsykora.com/blog/2009/05/15/zkusenosti-po-mesici-s-mackem/#comments</comments>
		<pubDate>Fri, 15 May 2009 19:35:10 +0000</pubDate>
		<dc:creator>ondrasej</dc:creator>
				<category><![CDATA[Nezařazeno]]></category>

		<guid isPermaLink="false">http://ondra.sykorky.cz/blog/2009/05/15/zkusenosti-po-mesici-s-mackem/</guid>
		<description><![CDATA[Zhruba před měsícem se mi naskytla příležitost k výměně notebooku za nový, kterou jsem rád využil. Po zkušenostech s HP se mi moc nechtělo řešit instalaci Linuxu a hardwarové perverze. Stejně tak se mi nechtělo dělat si &#34;Unix&#34; z Windows, aby na nich šlo aspoń trochu pracovat. Po zvážení všech alternativ a uvážení, že OS X [...]]]></description>
			<content:encoded><![CDATA[<p>Zhruba před měsícem se mi naskytla příležitost k výměně notebooku za nový, kterou jsem rád využil. Po zkušenostech s HP se mi moc nechtělo řešit instalaci Linuxu a hardwarové perverze. Stejně tak se mi nechtělo dělat si &quot;Unix&quot; z Windows, aby na nich šlo aspoń trochu pracovat. Po zvážení všech alternativ a uvážení, že OS X je vlastně zčásti maskované FreeBSD&#8230; jsem se vydal vstříc novým zážitkům s novým OS.</p>
<p><span id="more-165"></span></p>
<h3>Jak jsem vybíral</h3>
<p>Notebook používám hlavně na cestách, na balkóně, na zahradě a když zrovna desktop vytěžuju výpočtama. Notebook používám jen na práci a na komunikaci. Aby nedošlo k nedorozumění, práce pro mě znamená jednak programování (v kdečem, hlavně Java, Perl, Haskell, C# a C++) a psaní (LaTeX). Při práci zhusta využívám standardní unixové nástroje (bash, sed, grep, &#8230;) pro skriptování a pro transformaci dat. Hry na notebooku nehraju, na filmy se na něm dívám jen zřídka. Naopak si cením lehkých notebooků s pevnější konstrukci (k NTB se chovám slušně, ale často ho přenáším) a delší výdrž na baterie, abych s sebou nemusel nosit adaptér úplně všude.</p>
<p>Když to shrnu, tak od notebooku chci, aby</p>
<ul>
<li>na něm šlo bez problémů provozovat Linux nebo jiný Unix-like systém.</li>
<li>byl snadno přenosný &#8211; tedy aby se mi vešel do batohu (v pouzdře) a nepřipadal jsem si s ním na zádech jako šnek s ulitou.</li>
<li>vydržel běžet z baterie ostře víc než tři hodiny.</li>
<li>měl rozumný výpočetní výkon (stačí libovolně Core2 Duo + dostatek paměti)</li>
<li>nevětral, pokud zrovna nedělá něco fakt náročného.</li>
<li>byl od &quot;rozumného výrobce&quot; a byla na něj dostupná záruka typu Next Business Day.</li>
<li>nepoužíval dotykové senzory a nevypadal jako vánoční stromeček.</li>
</ul>
<p>Naopak nepotřebuju</p>
<ul>
<li>výkonnou grafickou kartu.</li>
<li>velké LCD nebo nadstandardní rozlišení.</li>
<li>&quot;bezpečnostní&quot; mechanismy jako je čtečka otisků prstů nebo systémové heslo.</li>
<li>závratně velký disk, nedejbože dva v RAIDu.</li>
<li>moc USB portů nebo dokovací stanici.</li>
</ul>
<p>Nakonec jsem na vybíral mezi ThinkPadem X200 a 13,3&quot; unibody MacBookem. X200 je sice menší a o dost lehčí, po dlouhém rozhodování ale vyhrál MacBook (větší, ale stále přijatelné rozměry a váha, o něco nižší cena, Unix bez shánění ovladačů a jako bonus možnost vyvíjet pro iPhone).</p>
<h3>Co mi vyhovuje</h3>
<p>Začnu tím, co se mi na MacBooku proti mým předchozím notebookům líbí. Jako první věc &#8211; ano, OS X skutečně má pod grafickým rozhraním Unixový systém. Všechny standardní nástroje včetně pěkné terminálové aplikace jsou hned v základní instalaci. Překvapilo mě, že byl k dispozici i Perl, Subversion klient a X-Window server. Navíc díky <a href="http://www.macports.org">MacPorts</a> lze instalovat další (Unixové) aplikace stejným způsobem jako na FreeBSD. Obecně &#8211; pokud nějaká aplikace existuje pro Linux, pravděpodobně půjde přeložit i pro OS X a pravděpodobně už to někdo udělal. Na druhou stranu jde o systém určený pro daný hardware, takže není potřeba nic kompilovat, konfigurovat nebo instalovat. A pokud potřebuju nějaké aplikace z Windows, jde je virtualizovat (a s <a href="http://www.vmware.com/products/fusion/">VMWare Fusion</a> i &quot;integrovat&quot; mezi Macovské). Visual Studio 2008 není žádný problém.</p>
<p>Uživatelské prostředí v OS X je vcelku příjemné a nemám pocit, že by mě nějak brzdilo při práci (až na pár drobností popsaných níže). Když si člověk zvykne na nové klávesové zkratky, dá se s ním pracovat celkem efektivně. Navíc dvojhmaty přes Command (který je vedle mezerníku) mi přijdou o dost jednodušší než přes Control, není na ně potřeba tolik kroutit ruce.</p>
<p>Dál se mi hodně líbí tělo &quot;z jednoho kusu hliníku&quot; (jak udělali, že notebook jde otevřít, když to je z jednoho kusu?!), notebook je díky němu pěkně pevný, nikde se nic neprohýbá a nevrže. Tělo navíc slouží pro odvod tepla jako velký (a tichý) chladič. Ale už vím, že uvnitř je i větráček &#8211; viděl jsem ho, když jsem přidával paměť. Trochu jsem se bál, aby při větším zatížení nebyl rozpálený celý notebook, ale zatím jsem nenarazil na problém a i po delším zatížení není horký a jde bez problémů nechat na kolenou. Ještě uvidím, jak se bude chovat za horkých letních dní. Pěkný je taky adaptér &#8211; je celkem malý a navíc jde, podobně jako u Dellu, jednoduše sbalit do úhledného balíčku (ale to si možná zaslouží vlastní zápis).</p>
<p>Příjemná věc je obrovský touchpad bez tlačítek. Chce to chvíli si zvyknout, ale už bych neměnil. Touchpad navíc (ve výchozím nastavení) nekliká po klepnutí, ale až po domáčknutí, takže nechtěná kliknutí prakticky neexistují, přestože není nijak zapuštěný.</p>
<p>A jako poslední drobnost (ale příjemnou) bych uvedl design, který je prostě povedený. Opravdu si cením celkové &quot;jednoduchosti&quot; &#8211; co není potřeba, to tam není. Prakticky žádné rušivé modré a zelené diody. A i ty, co tam jsou, svítí jen když je potřeba (dioda co bliká, když je notebook uspaný, ale zhasne, když je zapnutý), nebo když si o to uživatel řekne (indikátor stavu baterie, který je na tlačítko). Prakticky jediný úlet je svítící ohryzek na zadní straně displeje, ale ten stejně při práci s notebookem není vidět <img src='http://www.ondrejsykora.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Navíc je fajn, že na hliníku nezůstávají viditelné otisky prstů. MacBook White bych používat nemohl.</p>
<h3>Co se mi (zas tolik) nelíbí</h3>
<p>Tak a teď ty méně příjemné záležitosti. Z hlediska hardware mi chybí hlavně čtečka paměťových karet. Ano, dá se za pár korun sehnat externí, ale je to další věc, kterou je potřeba nosit s sebou. Podobné to je s výstupem na externí monitor. Ten je realizovaný přes Minidisplay Port a je k němu potřeba dokoupit redukci. Že je ji potřeba dokoupit se dá přežít, že to je další věc, co jde někde zapomenout, už je horší. Někomu by mohlo vadit, že MacBook má jen dva USB porty, ale já to nejsem.</p>
<p>Další trochu nepříjemná záležitost je CD/DVD mechanika, která je štěrbinová, takže má problémy s menšími formáty CD. Na druhou stranu, ani si nevzpomínám, kdy jsem naposledy cpal do notebooku vůbec nějaké CD nebo DVD. Vlastně vzpomínám&#8230; když jsem po pořízení toho předchozího instaloval Ubuntu.</p>
<p>Na klávesnici mi chybí klávesy PgUp/PgDown, Home a End (které jsou dostupné přes Fn). Dá se na to zvyknout a při práci dvěma rukama je přístup přes Fn a šipky možná rychlejší, než hledat samostatný Page Down někde na okraji klávesnice. Jinak je klávesnice na psaní hodně příjemná, nikde se neprohýbá a klávesy jsou pěkně oddělené mezerami. Moc se mi nelíbí rozložení klávesnice &#8211; US je víceméně standardní, ale u české jsou některé znaky jinde než jsem zvyklý a na středník přes Alt si budu zvykat hodně těžko.</p>
<p>Věc, která mi ale u ovládání vadí asi nejvíc je chybějící tlačítko pro kontextové menu. Ve většině aplikací jde nazkratkovat celé menu, ale z nějakého důvodu ve Finderu v menu chybí položka &quot;Otevřít s&#8230;&quot;. To je jen v kontextovém menu souboru a jediný způsob jak se k tomu dostat, je myší. Podobně myšové mi přijde přepínání v rámci oken jedné aplikace (ano, to z klávesnice jde, ale&#8230;).</p>
<p>Displej má výborný obraz a podsvícení, jenom nechápu, proč se musí tak lesknout. Asi to je součást firemní image. Nebo výsledek lobby očních lékařů. Jak jsem zjistil, existují přímo pro MacBook matné fólie, ještě kdyby je někdo (za rozumnou cenu) dovážel do ČR&#8230; Díky dobrému podsvícení se dá pracovat i v autobuse/ve vlaku, ale na matno by to bylo ještě lepší. Navíc mi přijde, že 1440&#215;900 by na 13,3&quot; notebooku bylo výborné rozlišení, ale co, pracovat se dá i v 1280&#215;800. Co ale nechápu už vůbec, je, že celkem nízké rozlišení je i u 15,4&quot; MacBooků Pro.</p>
<p>Daly by se najít ještě další drobnosti, jako poněkud nestabilní ukazatel baterie (i když za to možná mohla automatická regulace jasu displeje), ale už nejde o žádné zásadní bugy, které by mě nějak trápily.</p>
<h3>Závěrem</h3>
<p>I když se na něm dají najít věci k pomlouvání, myslím si, že MacBook výborný stroj, který bez problémů plní moje požadavky. OS X vidím jako výhodu, není v něm problém přepínat mezi klikáním a konzolí jak se mi to zrovna hodí &#8211; a pokud zrovna potřebuju Visual Studio, tak s Fusion to jde i bez přepínání do virtuálního počítače. Desktop od Apple bych si nekoupil, ale MacBook je výborná volba (nejen) jako Unixový notebook, v žádném případě nelituju, že jsem si ho pořídil a doporučuju i ostatním. Doporučuju <img src='http://www.ondrejsykora.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.ondrejsykora.com/blog/2009/05/15/zkusenosti-po-mesici-s-mackem/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Client-side captcha</title>
		<link>http://www.ondrejsykora.com/blog/2009/05/05/client-side-captcha/</link>
		<comments>http://www.ondrejsykora.com/blog/2009/05/05/client-side-captcha/#comments</comments>
		<pubDate>Tue, 05 May 2009 18:38:23 +0000</pubDate>
		<dc:creator>ondrasej</dc:creator>
				<category><![CDATA[Nezařazeno]]></category>

		<guid isPermaLink="false">http://ondra.sykorky.cz/blog/2009/05/05/client-side-captcha/</guid>
		<description><![CDATA[Díky tomu, že spammeři vám vlezou úplně všude, je dnes běžnou součástí většiny formulářů, je dnes běžnou součástí většiny veřejně viditelných webových formulářů captcha. Tedy otázka nebo úkol, jehož zpracování je pro člověka triviální, ale počítač se s ním (zatím) nedokáže jednoduše vypořádat.

Určení, jestli formulář vyplnil člověk nebo spamovací automat je pak jednoduché &#8211; pokud [...]]]></description>
			<content:encoded><![CDATA[<p>Díky tomu, že spammeři vám vlezou úplně všude, je dnes běžnou součástí většiny formulářů, je dnes běžnou součástí většiny veřejně viditelných webových formulářů captcha. Tedy otázka nebo úkol, jehož zpracování je pro člověka triviální, ale počítač se s ním (zatím) nedokáže jednoduše vypořádat.<br />
<span id="more-164"></span></p>
<p>Určení, jestli formulář vyplnil člověk nebo spamovací automat je pak jednoduché &#8211; pokud je úkol splněný správně, pak formulář zřejmě vyplnil člověk. Pokud ne, byl to počítač. Nepříjemné je, že splnění úkolu se musí testovat na serveru &#8211; pokud by k němu docházelo pouze na klientovi, bylo by pro spammery jednoduché tuto kontrolu obejít vyřazením testu (například vypnutím JavaScriptu) a pak odesílat obsah formuláře automaticky.</p>
<p>Na druhou stranu ale je nepříjemné, že pokud formulář obsahuje validaci hodnot v JavaScriptu, pak se tato validace nedá moc dobře vztáhnout i na captchu. Lze sice najít jednoduché řešení pomocí AJAXu, ale to naráží na asynchronní komunikaci a na bezpečnostní omezení XMLHttpRequestu (zakázané cross-domain requesty, které nemusí, ale mohou vadit).</p>
<p>Druhá možnost, jak dosáhnout validace už na straně klienta, je inspirovat se kryptografickými postupy. Víme například, že faktorizace na prvočísla je těžký problém, pro který neznáme efektivní algoritmus. A teď jak toho využít pro tvorbu captchy:</p>
<ol>
<li>Příprava na serveru: server vygeneruje dvě dostatečně velká prvočísla <em>p</em> a <em>q</em> a vypočítá jejich součin <em>n</em>. Prvočíslo <em>p</em> zakóduje do captchy (například jako obvyklá čísla v obrázku) a spolu s obrázkem pošle číslo <em>n</em>.</li>
<li>Klient dostane obrázek s kódem a číslo <em>n</em>. Uživatel opíše číslo z obrázku. Pokud ho opíše správně, jde o prvočíslo <em>p</em> a číslo <em>n</em> je jím dělitelné bez zbytku. JavaScript během validace formuláře ověří dělitelnost a v případě neúspěchu upozorní uživatele.</li>
<li>Protože faktorizace je obtížný problém, klient pouze na základě čísla <em>n</em> nemůže v rozumném čase zjistit, jaké jsou hodnoty <em>p</em> a <em>q</em>. Navíc, pokud by jí provedl, uspěje pouze v 50 % případů, protože správná odpověď je pouze jedno prvočíslo, klient ale bez použití obrázku neví, které z prvočísel to je.</li>
</ol>
<p>Pro dosažení rozumné bezpečnosti je potřeba použít delší prvočísla. Dostatečná hodnota by mohlo být například 256 bitů na jedno prvočíslo. Drobnou nevýhodou této metody je, že taková prvočísla mají cca 77 číslic (znaků), což by odradilo nejen spammery, ale i běžné uživatele. Pokud pro kódování použijeme i velká a malá písmena, sníží se počet znaků na 44, což moc velké zlepšení není.</p>
<p>Lepší tedy je použít alternativní řešení (díky Jirkovi za nápad), zvolit dostatečně dlouhý náhodný kód, tak 6-10 znaků, zakódovat je do captchy klasickým způsobem a spolu s captchou poslat hash kódu. Pokud bude hashovací funkce zvolená rozumně, nebude možné pomocí ní získat původní kód a navíc inverze hashovací funkce opět povede k více možnostem, z nichž jen jedna bude správná.</p>
<p>Nejlepší (nejjednodušší) nakonec ale stejně bude přestat teoretizovat, zůstat u současných (osvědčených) řešení a captchu ověřit jen na straně serveru&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ondrejsykora.com/blog/2009/05/05/client-side-captcha/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Kdo vlastně zabíjí hraní na PC?</title>
		<link>http://www.ondrejsykora.com/blog/2008/10/22/kdo-vlastne-zabiji-hrani-na-pc/</link>
		<comments>http://www.ondrejsykora.com/blog/2008/10/22/kdo-vlastne-zabiji-hrani-na-pc/#comments</comments>
		<pubDate>Tue, 21 Oct 2008 22:20:11 +0000</pubDate>
		<dc:creator>ondrasej</dc:creator>
				<category><![CDATA[GameDev]]></category>
		<category><![CDATA[Real Life]]></category>

		<guid isPermaLink="false">http://ondra.sykorky.cz/blog/2008/10/22/kdo-vlastne-zabiji-hrani-na-pc/</guid>
		<description><![CDATA[V posledních měsících vyšlo několik opravdu zajímavých her pro PC. S dobrým nápadem, od zkušených autorů a výbornými recenzemi. Přesto si ani jednu z nich nekoupím. Aby nedošlo k nedorozumění,  neplánuju si je ani stáhnout od pirátů, nebo obstarat jinak. Prostě je, přestože by mě zajímaly, nebudu hrát.

O jaké hry konkrétně jde? První, známější [...]]]></description>
			<content:encoded><![CDATA[<p>V posledních měsících vyšlo několik opravdu zajímavých her pro PC. S dobrým nápadem, od zkušených autorů a výbornými recenzemi. Přesto si ani jednu z nich nekoupím. Aby nedošlo k nedorozumění,  neplánuju si je ani stáhnout od pirátů, nebo obstarat jinak. Prostě je, přestože by mě zajímaly, nebudu hrát.<br />
<span id="more-163"></span><br />
O jaké hry konkrétně jde? První, známější případ, je simulace &#8220;všeho&#8221;, tedy Spore. Druhá je nepatrně méně znamé a očekávané pokračování černobylské akce S.T.A.L.K.E.R.: Clear Sky.</p>
<p>Co mají obě hry společného? Obě jsou velmi dobře chráněné proti pirátům. Dokonce tak dobře, že je (legálně) jde nainstalovat jen třikrát. V praxi to znamená, že si člověk nesmí přeinstalovat Windows. Nesmí měnit hardware, nesmí svoji kopii půjčit sourozencům když zrovna není čas na hraní. Jinak si vyčerpá svůj čas na hru bez toho, že by aspoń trochu zahrál. Za ceny přes 1000 Kč to je trochu moc starostí. V případě Stalkera jde ochranná perverze tak daleko, že omezení na tři instalace mí i verze pro Steam, který sám o sobě zajišťuje aktivaci po Internetu. Tady mě vážně nenapadá jiné vysvětlení, než záměrné omezování uživatelů.</p>
<p>Teoreticky jde hru upiratit. Pokud pomineme, že pirátství nelegální, je pro autory hry docela užitečné. Takový pirát jednak rozšiřuje komunitu hráčů (a slouží jako motivace pro další zájemce o hru) a jednak slouží jako docela dobrá reklama. Reklama, která nemá problémy s počtem aktivací a proto o nich nikomu neřekne. Jasně, že pár lidem tu hru nahraje sám pirát, ale pár dalších si ji třeba koupí. A nebo si ji koupí známí pirátova kamaráda. A tak dále.</p>
<p>Pojďte si taky nekoupit Spore a další hry s DRM a dát tak jasný signál, že tohle nechceme. Pojďte takové hry nestahovat, ať nemají vydavatelé pocit, že to je skoro ono, jenom to chce lepší ochranu. Pojďte podporovat tvůrce, kteří aktivaci nevyžadují. Že situace není ještě úplně ztracená, ukazuje třeba i český a polský CD Projekt, jejichž Zaklínač nejen nevyžaduje aktivaci, ale pro kterého dokonce nabídli obsah nedávno vydané rozšířené edice zdarma ke stažení majitelům původní hry. Takhle má vypadat služba zákazníkům, ne je omezovat a obvińovat z krádeže (u videjí navíc obvinění vidí jenom majitelé originálu, kdo by si něco takového kopíroval s filmem?). Tak co, kdo další se přidá?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ondrejsykora.com/blog/2008/10/22/kdo-vlastne-zabiji-hrani-na-pc/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Opera Mobile a Opera Mini, zkušenosti po měsíci používání</title>
		<link>http://www.ondrejsykora.com/blog/2008/08/29/opera-mobile-a-opera-mini-zkusenosti-po-mesici-pouzivani/</link>
		<comments>http://www.ondrejsykora.com/blog/2008/08/29/opera-mobile-a-opera-mini-zkusenosti-po-mesici-pouzivani/#comments</comments>
		<pubDate>Fri, 29 Aug 2008 21:15:04 +0000</pubDate>
		<dc:creator>ondrasej</dc:creator>
				<category><![CDATA[Real Life]]></category>
		<category><![CDATA[Windows Mobile]]></category>

		<guid isPermaLink="false">http://ondra.sykorky.cz/blog/2008/08/29/opera-mobile-a-opera-mini-zkusenosti-po-mesici-pouzivani/</guid>
		<description><![CDATA[O mobilní telefony a mobilní Internet se mimo běžne volání a SMS a občasné hledání v jízdních řádech moc nezajímám. Při cestách po ČR s sebou buď vozím notebook, nebo (a to většinou) jde o cesty tak krátké, že Internet nepotřebuju vůbec. Celý minulý měsic a pár dní k tomu jsem strávil v zahraničí, pouze [...]]]></description>
			<content:encoded><![CDATA[<p>O mobilní telefony a mobilní Internet se mimo běžne volání a SMS a občasné hledání v jízdních řádech moc nezajímám. Při cestách po ČR s sebou buď vozím notebook, nebo (a to většinou) jde o cesty tak krátké, že Internet nepotřebuju vůbec. Celý minulý měsic a pár dní k tomu jsem strávil v zahraničí, pouze s telefonem (Nokia 6120) a s Windows Mobile PDA. Na obou zařízeních byl nainstalovaný prohlížeč Opera. V tomto zápisku se snažím shrnout svoje zkušenosti (teda spíš připomínky), které jsem během měsíčního používáni nasbíral.<br />
<span id="more-162"></span><br />
Na začátek a pro úplnost &#8211; cílová země byla Velká Británie, mobilní operátor Three (který asi jako jediný v UK nabízí rozumný datový tarif na předplacených SIM kartách a provozuje především 3G síť). Opera Mobile byla ve verzi 8.65 (aktuální verze ve chvíli, kdy jsem odjížděl), Opera Mini byla předinstalovaná výrobcem telefonu, za její aktuálnost neručím. Později jsem ale v rámci objektivity vše ještě testoval aktuální verzi Opery Mini na SE K610i.</p>
<p>Tento zápis je hlavně seznam problémů a nedodělků, na druhou stranu nechci, aby z něj nekdo získal dojem, že mobilní Opera je nepoužitelný krám, protože to prostě není pravda. Jde o funkční a poměrně rychlý prohlížeč, ve kterém jde, více či méně pohodlně, udělat témeř vše, co v plnohodnotné verzi na PC. A to nemluvím pouze o prohlíženi statických stránek a hledání na Google. Nakonec úspěšně proběhly i složitější operace jako rezervace hotelu a letenek.</p>
<p>Tolik k pozitivním stránkam, teď ty slibované nepříjemnosti. K mému překvapení se ukázalo, že Opera Mini a Opera Mobile jsou hodně odlišné aplikace, a co je v jedné dobře zvládnuté, může v druhé představovat velký problém. Další text proto rozdělím do sekcí podle toho, o kterou verzi jde.</p>
<h3>Společné neduhy</h3>
<h4>Načítaní obrázků</h4>
<p>Příjemnou vlastností obou mobilních Oper je, že lze vypnout nahrávání obrázků, aby se stránky načítaly rozumně rychle i s pomalejším připojením. I když jde o standardní vlastnost, přítomnou ve všech prohlížečích, na mobilech ji považuji za obzvlášť důležitou, protože rychlé mobilní připojení stále není standardem ani ve vyspělejších zemích. O cenách za kilobyte nemluvě.<br />
Většinu času jsem pracoval bez načítání obrázků, nicméně ve výjimečných případech to bez nich prostě nejde (captcha, fotky při rezervaci ubytování, mapy, &#8230;). Proto mě dost překvapilo, že načítáni jde zapnout/vypnout jen globálně pro celou aplikaci (a ne například pouze pro jedno okno ve verzi Mobile). Zároveń chybí funkce &#8220;načíst obrázky na aktuální stránce&#8221;, kterou je nutné emulovat zapnutím načítání v Settings, reloadem stránky, a následným vypnutím načítání. Implementace takove funkce je triviální a výrazně by zvýšila uživatelský komfort.</p>
<h4>Rozložení stránky vzhledem k velikosti displeje</h4>
<p>Hodně stránek není vytvořených korektně podle webových standardů. A i ty co jsou, často nepočítají se zobrazením na miniaturních displejích mobilů a PDA. Obvykle to nepředstavuje vážný problém, ale například použití frame pevné šířky může znamenat problém, protože celou plochu obrazovky zabere navigační menu, zatímco na užitečná data zbývá jeden řádek textu.<br />
Ideální řešení by asi bylo použít virtuálni obrazovku určité &#8220;běžné&#8221; velikosti (např. 800&#215;600) pro výpočet velikosti prvků stránky, a nepočítat podle velikosti obrazovky telefonu nebo PDA.</p>
<h3>Opera Mini</h3>
<p>Jde o J2ME aplikaci optimalizovanou pro mobilní telefony. Překvapivě je hodně svižná a ani na stránkách využívajících JavaScript s ní nebyly zásadní problémy.</p>
<h4>Pohyb kurzoru</h4>
<p>Opera dobře zvládá reagovat na pohyb kurzoru (hover, JavaScriptové handlery), tady problém není. Problém je, že kurzor je vždy cca ve středu zorného pole. To ale znamená, že pokud se nějaka informace zobrazí při zastavení kurzoru nad určitým prvkem na stránce (tooltipy, vysvětlivky, &#8230;) a není viditelná celá, tak si ji neprečtete. Při posunu výhledu se totiž posune i kurzor. V tu chvíli ale přestane být na tom jediném správném místě a informace opět zmizí, nebo ji nahradí jiná.<br />
Částečné řešení je ve vhodnou chvíli vypnout podporu JavaScriptu (globální volba, stejně jako u načítání obrázků), přečíst si kýžený text, a pak JS opět zapnout. Komfort opět veškerý žádný.</p>
<h4>Podpora více oken</h4>
<p>Prestože Opera dokáže otevřít pop-up okna nezávisle na zdrojovém, človek nic takového udělat nemůže. Přitom právě možnost mít více oken současně je klíčová třeba při hledání dopravy, hotelu a dalších činnostech, kde se porovnávají různé nabídky a možnosti. Nutná funkčnost v Opeře očividně implementovaná je (viz pop-up okna), proto nechápu, proč není možné používat více než jedno okno v jeden okamžik.<br />
Částečne je možné tuto funkci &#8220;simulovat&#8221; pomocí záložek nebo ukládáni stránek do paměti, ale ani jedna možnost není zcela funkční a přináší s sebou řadu problémů, především u aplikaci s formuláři.</p>
<h3>Opera Mobile</h3>
<p>Jak název napovídá, jde o verzi pro Windows Mobile (resp. Pocket PC). Původně jsem očekával, že půjde o výrazně vyspělejší aplikaci, než je Javová verze, ale skutečnost mě mnohdy dost překvapila.</p>
<h4>Ukládání stránek</h4>
<p>Z neznámého důvodu není možné uložit stránku &#8220;na disk&#8221;. Nevím proč a neumím si to nijak vysvětlit, protože to zvládá i verze Mini.</p>
<h4>Zavírání oken</h4>
<p>Tlačítko pro zavření okna je hned nad horním tlačítkem vertikálního scrollbaru. A neptá se na potvrzení. No a zkuste se do toho scrollbaru strefit stylusem&#8230; Za jízdy autobusem&#8230; Po křivých anglických silničkách&#8230; Máte? Dodávám, že jsem se občas ukliknul, i když jsem seděl v klidu na posteli. Což dost naštve, zvlášť když človek scrolluje, aby zkontroloval pracně vyplněný formulář.<br />
Co by pomohlo &#8211; buď nechat zavíráni oken jen v kontextovém menu okna (kde prozměnu tato funkce chybí), nebo před zavřením okna požadovat potvrzení. A nejlépe obojí.</p>
<h3>Závěrem</h3>
<p>Protože v příspěvku píšu hlavně o nedostatcích, musím ještě jednou zdůraznit, že se jedná o funkční a ve většině případů dobře použitelný software, který je stále výrazně lepší, než konkurence (různé OEM prohlížeče v telefonech a Pocket Internet Explorer). A to jak v komfortu, tak v množství funkcí. Navíc se pro PDA chystá výrazně inovovaná verze 9.5, u které už snad většina uvedených výtek nebude platit. Uvidíme &#8211; zatím budu vše z povzdáli sledovat a v pravou chvili se do věci vložím.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ondrejsykora.com/blog/2008/08/29/opera-mobile-a-opera-mini-zkusenosti-po-mesici-pouzivani/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Spojování podmínek v Petalu</title>
		<link>http://www.ondrejsykora.com/blog/2008/06/01/spojovani-podminek-v-petalu/</link>
		<comments>http://www.ondrejsykora.com/blog/2008/06/01/spojovani-podminek-v-petalu/#comments</comments>
		<pubDate>Sun, 01 Jun 2008 13:22:35 +0000</pubDate>
		<dc:creator>ondrasej</dc:creator>
				<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://ondra.sykorky.cz/blog/2008/06/01/spojovani-podminek-v-petalu/</guid>
		<description><![CDATA[Po zápisku o HTML::Mason přidávám pár hintů k dalšímu šablonovacímu systému pro Perl, tentokrát pro Petal. Proti Masonu je Petal o dost jednodušší, ale na weby s několika stránkami bohatě stačí. Petal má navíc velkou výhodu v tom, že je kompletně postavený na XML, takže je možné jeho použití jednoduše kombinovat s dalšími XML nástroji. [...]]]></description>
			<content:encoded><![CDATA[<p>Po zápisku o HTML::Mason přidávám pár hintů k dalšímu šablonovacímu systému pro Perl, tentokrát pro <a title="Petal - Perl Template Attribute Language" href="http://search.cpan.org/~bpostle/Petal-2.19/lib/Petal.pm">Petal</a>. Proti Masonu je Petal o dost jednodušší, ale na weby s několika stránkami bohatě stačí. Petal má navíc velkou výhodu v tom, že je kompletně postavený na XML, takže je možné jeho použití jednoduše kombinovat s dalšími XML nástroji. Některé věci v něm ale jsou zjednodušené možná až příliš &#8211; například syntaxe výrazů v podmínkách. To může znamenat problém, pokud je viditelnost některých prvků stránky řízena složitější logikou a využívá se více proměnných.<br />
<span id="more-161"></span><br />
V podmínkové části šablon lze zadat jenom jednu proměnnou. Nejjednodušší způsob, jak tento problém obejít, je přidat pomocné proměnné obsahující požadované kombinace podmínek.</p>
<pre>$tal->process(a => $a, b => $b, a_or_b => $a || $b);</pre>
<p>To je ale nepříjemné řešení, protože zesložiťuje komunikaci mezi šablonou a &#8220;užitečným kódem&#8221; a může vyžadovat úpravy perlového kódu při změně designu stránky.</p>
<p>Jak tedy zapsat základní logické spojky? V dokumentace to přímo napsané není, ale nakonec to není tak složité:<br />
<em>Pozn.: v příkladech používám pro Petalovské atributy namespace <code>tal</code>, jako to je v příkladech v dokumentaci na CPANu.</em></p>
<h3>Negace</h3>
<p>Nejjednodušší varianta, před podmínku stačí dopsat <code>false:</code></p>
<pre><strong>if</strong> (not $hashref-&gt;{"a"}) {
  #...
}</pre>
<p>lze zapsat jako</p>
<pre>&lt;span tal:condition="false:a"&gt;...&lt;/span&gt;</pre>
<h3>Konjunkce (logické and)</h3>
<p>Logický and jde vytvořit jednoduše, jako vyhodnocení posloupnosti podmínek (tj. vnořením tagů s podmínkou do sebe). Problém je, že tak ve výsledném HTML kódu vzniknou nechtěné elementy. Tomu jde v Petalu zabránit přidáním atributu omit-tag s pravdivou hodnotou (například <code>omit-tag="string:1"</code>) u pomocných tagů, přidaných jen kvůli podmínkám.</p>
<pre><strong>if</strong> ($hashref-&gt;{"a"} &#038;&#038; $hashref-&gt;{"b"}) {
  #...
}</pre>
<p>lze tedy zapsat jako</p>
<pre>&lt;span tal:omit-tag="string:1" tal:condition="a"&gt;
  &lt;span tal:condition="b"&gt;
    ...
  &lt;/span&gt;
&lt;/span&gt;</pre>
<h3>Disjunkce (logické or)</h3>
<p>S disjunkcí to je o něco složitější, trik s vnořování tagů tu zopakovat nejde. Na druhou stranu lze využít schopnost Petalu vkládat hodnoty proměnných přímo do textu pomocí dolarové notace &#8211; ${x} se při zpracování šablony nahradí hodnotou proměnné x. To lze využít ke skládání hodnot pro podmínky. Přidáním <code>string:</code> na začátek podmínkového atributu Petal přinutíme, aby výraz v podmínce zpracovával jako řetězec (a ne jako název proměnné). Pak do něj lze zadat více proměnných najednou (viz příklad). Pokud alespoń jedna z nich bude mít pravdivou hodnotu, pak bude mít pravdivou hodnotu celý řetězec a podmínak bude splněna.</p>
<pre><strong>if</strong> ($hashref-&gt;{"a"} || $hashref-&gt;{"b"}) {
  #...
}</pre>
<p>lze zapsat jako</p>
<pre>&lt;span tal:condition="string:${a}${b}"&gt;
  ...
&lt;/span&gt;</pre>
<h3>Složitější výrazy</h3>
<p>Už budou trochu problém&#8230; každou logickou formuli sice lze přepsat na konjunkci disjunkcí (konjunktivní normální tvar) a na ten pak aplikovat výše uvedené postupy, ale o přehlednosti takové šablony bych si dovolil předem pochybovat. O skutečné potřebě používat takové podmínky také.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ondrejsykora.com/blog/2008/06/01/spojovani-podminek-v-petalu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Excalibur vstává z mrtvých (už zase?)</title>
		<link>http://www.ondrejsykora.com/blog/2008/05/28/excalibur-vstava-z-mrtvych-uz-zase/</link>
		<comments>http://www.ondrejsykora.com/blog/2008/05/28/excalibur-vstava-z-mrtvych-uz-zase/#comments</comments>
		<pubDate>Wed, 28 May 2008 18:26:14 +0000</pubDate>
		<dc:creator>ondrasej</dc:creator>
				<category><![CDATA[GameDev]]></category>
		<category><![CDATA[Real Life]]></category>

		<guid isPermaLink="false">http://ondra.sykorky.cz/blog/2008/05/28/excalibur-vstava-z-mrtvych-uz-zase/</guid>
		<description><![CDATA[Posledních pár týdnů žije český Internet &#8211; nebo alespoń jeho malá část &#8211; snahou o oživení herního časopisu Excalibur. Ve své době šlo o legendu a zároveń první časopis v ČR, který se věnoval počítačovým hrám jako hlavnímu tématu. Po založení časopisu Score (a odchodu většiny redakce) jeho sláva postupně upadala, až upadla úplně. Včetně [...]]]></description>
			<content:encoded><![CDATA[<p>Posledních pár týdnů žije český Internet &#8211; nebo alespoń jeho malá část &#8211; snahou o oživení herního časopisu Excalibur. Ve své době šlo o legendu a zároveń první časopis v ČR, který se věnoval počítačovým hrám jako hlavnímu tématu. Po založení časopisu Score (a odchodu většiny redakce) jeho sláva postupně upadala, až upadla úplně. Včetně časopisu. Martin Ludvík (-ml-), vydavatel časopisu, se několikrát pokoušel o oživení časopisu a využití značky, pokaždé ale bez valného úspěchu.<br />
<span id="more-160"></span><br />
Nejnovější pokus probíhá právě teď. Zajímavé na něm je, že můžeme ve Web 2.0 duchu sledovat pokrok k prvnímu číslu online, skoro v reálném čase, na <a href="http://excaliburblog.cz/">Blogu pro obnovu vydávání legendárního časopisu počítačových her</a>. No nevím jak na vás, ale na mě blog působí spíš rozpačitě&#8230; po přečtení vyznívá v duchu <i>&#8220;nový Excalibur bude skvělý, zábavný a přitom poučný a bude se v něm o hrách psát úplně jinak, než v konkurenčních časopisech. Tak a teď mi [čtenáři] řekněte, co a jak do něj vlastně máme psát.&#8221;</i> Tak si říkám, jestli -ml- má vůbec nějaký plán, jak časopis koncipovat a dál rozvíjet.</p>
<p>V tomhle dojmu mě utvrzuje i drobná poznámka na konci <a href="http://www.vreco.cz/2008/04/martin-ludvik-chce-ozivit-excalibur-po-kolikate-uz/">Vrecova zápisku na stejné téma</a>, že před časem se to -ml- pokoušel vytáhnout z konkurence. Na jednu stranu obdivuju jeho výdrž a odhodlání, ale pokud má Excalibur dotáhnout do úspěšného konce, je potřeba především silná vlastní vize, ne sbírat moudrosti z komentářů na Internetu&#8230;</p>
<p>To ale neznamená, že bych jeho snaze nefandil. Už jenom proto, že -ml- v Excalibur očividně opravdu hodně věří. A taky proto, že situace na trhu českých herních časopisů je, mírně řečeno, strnulá. A proto, že před časem jsem s nostalgií pomalu na Aukru dával dohromady první ročníky Excaliburu a Score a vzpomínal na ty krásné časy <img src='http://www.ondrejsykora.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.ondrejsykora.com/blog/2008/05/28/excalibur-vstava-z-mrtvych-uz-zase/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>HTML::Mason, mod_perl, čeština a utf-8</title>
		<link>http://www.ondrejsykora.com/blog/2008/05/25/htmlmason-mod_perl-cestina-a-utf-8/</link>
		<comments>http://www.ondrejsykora.com/blog/2008/05/25/htmlmason-mod_perl-cestina-a-utf-8/#comments</comments>
		<pubDate>Sat, 24 May 2008 23:30:56 +0000</pubDate>
		<dc:creator>ondrasej</dc:creator>
				<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://ondra.sykorky.cz/blog/2008/05/31/htmlmason-mod_perl-cestina-a-utf-8/</guid>
		<description><![CDATA[HTML::Mason je jednou z výborných (řekl bych nejlepších, ale dost jsem jich ještě nevyzkoušel) voleb při vývoji webových aplikací v Perlu. Výhod je spousta &#8211; komponenty, přehledná syntax, jednoduché na naučení. Dokud je vyvýjená aplikace v angličtině a pro anglicky mluvící, je všechno krásné, funkční a jednoduché. Problém začne až ve chvíli, kdy se na [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.masonhq.com">HTML::Mason</a> je jednou z výborných (řekl bych nejlepších, ale dost jsem jich ještě nevyzkoušel) voleb při vývoji webových aplikací v Perlu. Výhod je spousta &#8211; komponenty, přehledná syntax, jednoduché na naučení. Dokud je vyvýjená aplikace v angličtině a pro anglicky mluvící, je všechno krásné, funkční a jednoduché. Problém začne až ve chvíli, kdy se na web začne míchat Unicode.<br />
<span id="more-159"></span><br />
Podle dokumentace funguje Unicode v Perlu tak nějak automaticky a interní reprezentace řetězců je vždy UTF-8. To je sice pravda, ale jen z části. Retězce totiž Perlu interpretuje buď jako řetězec (a pak je interně v Unicode), nebo jako pole bytů. Pak pochopitelně v Unicode není. Dokud pracujeme jen s jedním typem řetězců (a nevadí drobnosti jako nesprávné délky řetězce), není nutné situaci řešit, prostě to nějak funguje a výstup je správně. Horší to je ve chvíli, kdy se začnou kombinovat Unicode řetězce s poli bytů &#8211; v takové chvíli je nutné překódovat oba řetězce do stejného formátu. Perl si vybere Unicode jako menší zlo, ale obě možné volby jsou špatně. Obzvlášť pikantní situace nastane ve chvíli, kdy bytový řetězec už ve skutečnosti je v Unicode: při konverzi nedojde k rozpoznání multibyte znaků a každý byte je interpretován jako samostatný znak (a díky tomu z něj v Unicode reprezentaci opět vznikne multibyte znak). Typicky se tento problém projevuje na místech, kde se kombinují data ze dvou různých zdrojů:</p>
<p><strong>První problém:</strong> soubory s Masonovskými komponentami obsahují HTML kód (z pochopitelných důvodů psaný jako UTF-8) a je potřeba Perl přesvědčit, že je tak také má interpretovat. V &#8220;normálním&#8221; skriptu to lze udělat například přidáním řádku</p>
<pre><strong>use</strong> utf8;</pre>
<p>na začátek souboru. Masonovská šablona sice normální skript není, ale Mason šablony při zpracování překládá na skripty (takže text+html v šabloně padne do řetězcových konstant) a ty pak spouští. Takže zbývá jen odhalit, jakým způsobem do nich propašovat výše uvedený řádek. Přímočerá možnost je uvést ho do sekce <code>&lt;%init&gt;</code> u každé komponenty. Nepraktické, že? Naštěstí jde Masonu v konfiguraci Apache předat kus kódu, který bude přidán na začátek kódu každé komponentu. Při použití přes mod_perl stačí do konfigurace Apache přidat řádek:</p>
<pre>PerlSetVar MasonPreamble "use utf8;"</pre>
<p>Podobně pro (Fast)CGI.</p>
<p><strong>Druhý problém:</strong> <code>Apache2::Request</code> nenastavuje interní Unicode flag automaticky, přestože z HTTP hlaviček ví, že data v Unicode jsou (kvůli možným útokům přes neplatné UTF-8 znaky). Při normální práci přes <code>mod_perl</code> není problém parametry správně překódovat nebo zpracovat ručně, ne přes <code>Apache2::Request</code>. s Masonem to je trochu horší &#8211; parametry si zpracovává sám pomocí <code>Apache2::Request</code> a nepodařilo se mi najít jednoduché řešení, jak zasáhnout přímo do zpracování parametrů, ale bez změn ve zdrojových kódech Masonu. Naštěstí se k parametrům dá dostat  v Masonovských autohandlerech ještě předtím, než se k nim dostane libovolná komponenta. Vložení následujícího kódu do autohandleru v kořenovém adresáři aplikace</p>
<pre><%init>
%ARGS = <strong>map</strong> { 	$_ = Encode::decode('utf8', $_); }%ARGS;
$m->call_next(%ARGS);
<%init></pre>
<p>způsobí překódování parametrů do UTF tak, že všechny ostatní komponenty je dostanou ve správném tvaru.</p>
<p><strong>Třetí, čtvrtý, &#8230; problém:</strong> řetězce z databáze, souborů a dalších zdrojů. Ale to až někdy jindy. A nebo na to přijdete sami <img src='http://www.ondrejsykora.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.ondrejsykora.com/blog/2008/05/25/htmlmason-mod_perl-cestina-a-utf-8/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ještě jednou Sudoku</title>
		<link>http://www.ondrejsykora.com/blog/2008/01/26/jeste-jednou-sudoku/</link>
		<comments>http://www.ondrejsykora.com/blog/2008/01/26/jeste-jednou-sudoku/#comments</comments>
		<pubDate>Sat, 26 Jan 2008 20:28:29 +0000</pubDate>
		<dc:creator>ondrasej</dc:creator>
				<category><![CDATA[AI]]></category>

		<guid isPermaLink="false">http://ondra.sykorky.cz/blog/2008/01/26/jeste-jednou-sudoku/</guid>
		<description><![CDATA[V minulém příspěvku o Sudoku solveru. -mt- v diskuzi pod příspěvkem namítal, že solver je podobně rychlý jako jeho naivní solver v C++. Že by chytré řešení v Javě bylo stejně rychlé jako naivní řešení v C++ zní trochu divně &#8212; ledaže by to s tou chytrostí nebylo tak horké&#8230;
Nebylo. Při kontrole korektnosti pozice se [...]]]></description>
			<content:encoded><![CDATA[<p>V <a href="http://ondra.sykorky.cz/blog/2008/01/05/rychlost-alokaci-v-jave/">minulém příspěvku</a> o <a href="http://ondra.sykorky.cz/projects/sudoku-solver">Sudoku solveru</a>. -mt- v diskuzi pod příspěvkem namítal, že solver je podobně rychlý jako jeho naivní solver v C++. Že by chytré řešení v Javě bylo stejně rychlé jako naivní řešení v C++ zní trochu divně &#8212; ledaže by to s tou chytrostí nebylo tak horké&#8230;</p>
<p>Nebylo. Při kontrole korektnosti pozice se testovalo, zda v některé skupině (tj. řádku, sloupci nebo podčtverci) nejsou dvě stejné hodnoty a že pro každé pole zbývá alespoń jedna možná hodnota. Přidáním dalšího testu, který kontroluje, jestli do každé skupiny stále lze vložit (nebo už je vloženo) všech devět číslic. Na úloze z <a href="http://ondra.sykorky.cz/blog/2008/01/05/rychlost-alokaci-v-jave/">předchozího příspěvku</a> klesl počet návratů při backtrackingu díky rychlejší detekci nekorektní pozice z 174844 na 35039.</p>
<p>Bez dalších technických optimalizací se čas nutný přo nalezení řešení výše zmíněné úlohy (na stejném stroji) snižil z průměrných 2940,3 ms na 392.16 (&plusmn; 16) ms. Nová verze solveru včetně zdrojových kódů je ke stažení na <a href="http://ondra.sykorky.cz/projects/sudoku-solver">stránce projektu</a>. Několik nápadů na zrychlení ještě zbývá, ale to zas někdy příště&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ondrejsykora.com/blog/2008/01/26/jeste-jednou-sudoku/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rychlost alokací v Javě</title>
		<link>http://www.ondrejsykora.com/blog/2008/01/05/rychlost-alokaci-v-jave/</link>
		<comments>http://www.ondrejsykora.com/blog/2008/01/05/rychlost-alokaci-v-jave/#comments</comments>
		<pubDate>Sat, 05 Jan 2008 00:41:59 +0000</pubDate>
		<dc:creator>ondrasej</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://ondra.sykorky.cz/blog/2008/01/05/rychlost-alokaci-v-jave/</guid>
		<description><![CDATA[Když jsem před časem programoval Sudoku solver v Javě, použil jsem jednoduchý, dalo by se říci až naivní, přístup k vytvoření zásobníku pro backtracking. Při řešení jednoduchých sudoku naivní implementace nevadí, protože k backtrackování dochází jen minimálně. Jak to je s (ne)efektivností tohoto řešení doopravdy se ukázalo až na opravdu těžkých zadáních z Minimum Sudoku.

Při [...]]]></description>
			<content:encoded><![CDATA[<p>Když jsem před časem programoval <a href="http://ondra.sykorky.cz/projects/sudoku-solver">Sudoku solver</a> v Javě, použil jsem jednoduchý, dalo by se říci až naivní, přístup k vytvoření zásobníku pro backtracking. Při řešení jednoduchých sudoku naivní implementace nevadí, protože k backtrackování dochází jen minimálně. Jak to je s (ne)efektivností tohoto řešení doopravdy se ukázalo až na opravdu těžkých zadáních z <a href="http://people.csse.uwa.edu.au/gordon/sudokumin.php">Minimum Sudoku</a>.<br />
<span id="more-157"></span><br />
Při tvorbě jsem efektivitu moc neřešil &#8211; testoval jsem hlavně na jednodušších zadáních, kde řešení nacházel poměrně rychle. Když jsem pak chtěl vyzkoušet &#8220;nejtěžší&#8221; variaty z Minimum Sudoku, tak mě doba výpočtu v řádu vteřin trochu překvapila a začal jsem do programu mírně vrtat. Vyvrtané informace shrnují následující odstavce.</p>
<p>Na začátek pár slov o reprezentaci dat a uložení hrací plochy. Ke každému políčku (<code>Field</code>) si algoritmus udržuje tři základní údaje: hodnotu políčka (0-9; 0 znamená nevyplněné políčko) a množinu hodnot, které políčku ještě jde přiřadit (jeden bit pro každou hodnotu). Stav hrací plochy je pak uložen jako dvourozměrné pole políček.</p>
<p>Základní myšlenka řešícího algoritmu spočívá v propagaci možných hodnot a backtrackingu, podobně jako v programování s omezujícími podmínkami. Po přiřazení hodnoty jednomu políčku je tato hodnota zakázána všem ostatním políčkům ve stejné skupině (řádku, sloupci, čtverci). Když v některém políčku zbyde jediná hodnota, pak ji tomuto políčku přiřadí (a provede další propagaci). Pokud jsou v některém poli zakázány všechny možné hodnoty, prohledávání v této větvi končí neúspěchem.<br />
Pokud po skončení propagace hodot jsou některá políčka stále nepřiřazená, algoritmus zkusí do takového pole dosadit jednu z povolených hodnot (to, že políčko zůstalo po propagaci volné znamená, že na základě dostupných informací je do něj možné dosadit více než jednu hodnotu) a provádí backtracking.</p>
<h3>Naivní řešení</h3>
<p>Naivní řešení používá pro uložení zásobníku <code>java.util.Stack&lt;T&gt;</code>. Při každém sestupu při backtrackování se alokuje nová reprezentace hrací plochy a zařadí na zásobník. O staré stavy ze zásobníku, pro které prohledávání selhalo se stará garbage collector. Jednoduché, ale funkční.</p>
<p><code><b>private</b> Stack<field[][]> gameStateStack;</p>
<p><b>private static</b> Field[][] cloneGameState(Field[][] _source) {<br />
&nbsp;&nbsp;Field[][] clone = <b>new</b> Field[GAME_SIZE][];<br />
&nbsp;&nbsp;<b>for</b>(int i=0; i < GAME_SIZE; i++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;clone[i] = <b>new</b> Field[GAME_SIZE];<br />
&nbsp;&nbsp;<b>for</b>(int x=0; x < GAME_SIZE; x++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;<b>for</b>(int y=0; y < GAME_SIZE; y++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clone[x][y] = <b>new</b> Field(_source[x][y]);<br />
&nbsp;&nbsp;<b>return</b> clone;<br />
}</p>
<p><b>private void</b> popGameState() {<br />
&nbsp;&nbsp;currentGameState = gameStateStack.pop();<br />
}</p>
<p><b>private void</b> pushGameState() {<br />
&nbsp;&nbsp;Field[][] new_state = cloneGameState(currentGameState);<br />
&nbsp;&nbsp;gameStateStack.push(currentGameState);<br />
&nbsp;&nbsp;currentGameState = new_state;<br />
}<br />
</code></p>
<h3>Zlepšení s předalokováním</h3>
<p>Teď se nad problémem zamyslíme trochu víc. Je snadné si uvědomit, že při řešení Sudoku 9&#215;9 nikdy nebude hloubka zanoření backtrackingu vyšší než 81 &#8211; podle počtu polí na hrací ploše. Ve skutečnosti bude ještě nižší, protože některá pole jsou obsazená již v zadání. 81 je poměrně málo. Dost málo na to, aby šlo všech 81 stavů hrací plochy na zásobníku předalokovat a při backtrackingu do nich jen zkopírovat aktuální stav hry.</p>
<p><code><i>// alokováno při inicializaci</i><br />
<b>private</b> Field[][][] gameStateStack = <b>null</b>;<br />
<b>private int</b> stackPosition = 0;</p>
<p><b>private void</b> cloneGameState() {<br />
&nbsp;&nbsp;Field[][] source = gameStateStack[stackPosition - 1];<br />
&nbsp;&nbsp;Field[][] clone = gameStateStack[stackPosition];<br />
&nbsp;&nbsp;<b>for</b>(int x=0; x < GAME_SIZE; x++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;<b>for</b>(int y=0; y < GAME_SIZE; y++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clone[x][y].assign(source[x][y]);<br />
}</p>
<p><b>private void</b> popGameState() {<br />
&nbsp;&nbsp;stackPosition&minus;&minus;;<br />
&nbsp;&nbsp;currentGameState = gameStateStack[stackPosition];<br />
}</p>
<p><b>private void</b> pushGameState() {<br />
&nbsp;&nbsp;stackPosition++;<br />
&nbsp;&nbsp;cloneGameState();<br />
&nbsp;&nbsp;currentGameState = gameStateStack[stackPosition];<br />
}</code></p>
<h3>Výsledky</h3>
<p>Efektivitu obou verzí kódu jsem testoval na následujícím zadání (těžké sudoku se sedmnácti podporami):<br />
<code><br />
-&nbsp;-&nbsp;-|-&nbsp;-&nbsp;-|-&nbsp;1&nbsp;3<br />
-&nbsp;-&nbsp;-|-&nbsp;3&nbsp;-|-&nbsp;8&nbsp;-<br />
-&nbsp;7&nbsp;-|-&nbsp;-&nbsp;-|-&nbsp;-&nbsp;-<br />
-----+-----+-----<br />
-&nbsp;-&nbsp;-|2&nbsp;-&nbsp;6|-&nbsp;-&nbsp;-<br />
-&nbsp;3&nbsp;-|-&nbsp;-&nbsp;-|9&nbsp;-&nbsp;-<br />
-&nbsp;-&nbsp;-|-&nbsp;1&nbsp;-|-&nbsp;-&nbsp;-<br />
-----+-----+-----<br />
6&nbsp;-&nbsp;-|5&nbsp;-&nbsp;-|2&nbsp;-&nbsp;4<br />
-&nbsp;-&nbsp;-|4&nbsp;-&nbsp;-|7&nbsp;-&nbsp;-<br />
1&nbsp;-&nbsp;-|-&nbsp;-&nbsp;-|-&nbsp;-&nbsp;-</code></p>
<p>Naměřené časy shrnuje tabulka níže. Jde o průměrné časy ze 100 pokusů, aby měl JVM dost času se zahřát. Při řešení jednoho zadání solver provedl vždy 174844 rekurzivních sestupů a tedy i &#8220;alokací&#8221; nového pole.</p>
<table>
<tr>
<td><b>Naivní verze:</b></td>
<td>3140,3 ms (&plusmn; 30 ms)</td>
</tr>
<tr>
<td><b>Verze bez alokací:</b></td>
<td>2940,3 ms (&plusmn; 35 ms)</td>
</tr>
</table>
<p>Časy jsem měřil na počítači s procesorem Intel Core2Duo 1800MHz, spoustou paměti, Gentoo Linuxem a Javou 1.6 (nicméně výsledky na Javě 1.5 jsou obdobné). Rozdíl je sice viditelný (cca 7%), přesto je o dost menší, než jsem čekal. Je vidět, že se v Sunu opravdu snaží o co nejefektivnější JVM a na jejich tvrzení, že nemá smysl optimalizovat na počet alokací opravdu něco bude <img src='http://www.ondrejsykora.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.ondrejsykora.com/blog/2008/01/05/rychlost-alokaci-v-jave/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
