<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
  <title>Hiperkocka.hu</title>
  <link href="http://hiperkocka.hu/blog/atom.xml" rel="self" />
  <link href="http://hiperkocka.hu/" />
  <updated>2013-01-26T13:44:44-08:00</updated>
  <author>
    <name>Tóth Dávid</name>
    <email>tothda@gmail.com</email>
  </author>
  <id>http://hiperkocka.hu/</id>

  
    <entry>
      <title>Clojure és a nyolc királynő</title>
      <link href="http://hiperkocka.hu/blog/2010/01/02/clojure-es-a-nyolc-kiralyno"/>
      <updated>2010-01-02T00:00:00-08:00</updated>
      <id>http://hiperkocka.hu/blog/2010/01/02/clojure-es-a-nyolc-kiralyno</id>
      <content type="html">&lt;p&gt;Az egész tavaly Húsvétkor kezdődött. Verpeléten voltunk Kriszti anyukájánál három napot. Kellett valami elfoglaltság, ezért megvásároltam Stuart Halloway &lt;a href='http://pragprog.com/titles/shcloj/programming-clojure'&gt;Programming Clojure&lt;/a&gt; című könyvének PDF verzióját. Nem nagyon kommunikáltam eztán a külvilággal a következő néhány napban, amíg a végére nem értem. Remek olvasmány volt, nagyon jól bemutatja a &lt;a href='http://clojure.org'&gt;Clojure&lt;/a&gt; és a funkcionális programozás lenyűgözően elegáns mivoltát. Belelkesedtem, de aztán lecsendesedett a dolog. Felvettem egy rakás Clojure-rel foglalkozó blog-ot a reader-ben, amiket szorgalmasan olvastam is, de kódot nem nagyon írtam. Egészen most karácsonyig.&lt;/p&gt;

&lt;p&gt;Amikor is (nem meglepő módon) kiderült, hogy egy programnyelvet nem lehet megtanulni, ha csak olvasol róla. Bármennyit is olvasol róla. A nyelvet használni kell, s közben vért izzadni a legtriviálisabb problémák megoldásáért is. Amiket következő alkalommal persze már csuklóból old meg az ember.&lt;/p&gt;

&lt;p&gt;Első feladatként a &lt;a href='http://en.wikipedia.org/wiki/Eight_queens_puzzle'&gt;Nyolc királynő problémát&lt;/a&gt; tűztem magam elé. A megoldása nem különösebben bonyolult, éppen megfelelő egy új nyelv felfedezéséhez. A nyolc királnyő probléma arról szól, hogyan lehet 8 db királynőt feltenni egy sakktáblára úgy, hogy ne támadják egymást. Összesen 92 db megoldása van.&lt;/p&gt;

&lt;h2 id='backtracking'&gt;Backtracking&lt;/h2&gt;

&lt;p&gt;A módszert, amivel a nyolc királynő problémát meg szokás oldani, &lt;a href='http://en.wikipedia.org/wiki/Backtracking'&gt;backtracking&lt;/a&gt;-nek hívják. A lényege pontokba szedve röviden a következő:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Az összes olyan állapotot keressük, melyek megoldásai a problémának.&lt;/li&gt;

&lt;li&gt;A folyamat során mindig rendelkezünk egy állapottal, ami általában részleges, de néha teljes megoldás.&lt;/li&gt;

&lt;li&gt;Minden részleges megoldáshoz meg tudjuk mondani az őt követő állapotok halmazát. Ezek egy lépéssel közelebb vannak egy teljes megoldáshoz.&lt;/li&gt;

&lt;li&gt;Egy állapotról el kell tudnunk dönteni, hogy az teljes megoldása-e a problémának.&lt;/li&gt;

&lt;li&gt;Ha egy részleges megoldáshoz tartozó követő állapotok halmaza üres, akkor zsákutcába kerültünk, ezért visszalépünk az őt megelőző állapotba (ez a backtrack), és ott egy másik részleges megoldás felé indulunk tovább.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ha a fenti pontokat a nyolc kiránynő problámra vetítem, akkor a következőket kapom:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mind a 92 megoldást szeretném megkapni.&lt;/li&gt;

&lt;li&gt;Az állapotot egy tömb reprezentálja, ami kezdetben üres. Később a tömb i. eleme mondja meg, hogy az i. oszlopban lévő királynő melyik sorban van.&lt;/li&gt;

&lt;li&gt;Részleges megoldás esetén k oszlophoz rendeltünk királynőt, ahol k &amp;lt; 7 (a számozást nullával kezdjük). Ekkor a követő állapotok halmaza azon állapotokat tartalmazza, melyekben már a k + 1-dik oszlopban is van királynő, és ez semelyik előzőt sem támadja.&lt;/li&gt;

&lt;li&gt;Mivel minden részleges megoldásunkra igaz, hogy senki nem támad senkit, egy állapot teljes megoldás, ha az állpot tömbjénak hossza 8.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='clojure_implementci'&gt;Clojure implementáció&lt;/h2&gt;

&lt;p&gt;A kód megtekinthető egyben a &lt;a href='http://gist.github.com/267522'&gt;ebben a gist&lt;/a&gt;-ben, de itt most szeretnék végigmenni rajta, hogy lássuk, hogyan épül fel a program. Csapjunk is a lovak közé!&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='clojure'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;def &lt;/span&gt;&lt;span class='nv'&gt;N&lt;/span&gt; &lt;span class='mi'&gt;8&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;distance&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='nv'&gt;y&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;Math/abs&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;- &lt;/span&gt;&lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='nv'&gt;y&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;solution?&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;state&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;= &lt;/span&gt;&lt;span class='nv'&gt;N&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;count &lt;/span&gt;&lt;span class='nv'&gt;state&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;next-states&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;s&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;map &lt;/span&gt;&lt;span class='o'&gt;#&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;conj &lt;/span&gt;&lt;span class='nv'&gt;s&lt;/span&gt; &lt;span class='nv'&gt;%&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;range &lt;/span&gt;&lt;span class='nv'&gt;N&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;N&lt;/code&gt; a tábla oldalának hossza, sakktábla esetén 8. A &lt;code&gt;distance&lt;/code&gt; egy segédfüggvény, két szám különbségének abszolút értékét számolja ki. A &lt;code&gt;solution?&lt;/code&gt; prediktátum eldönti egy állapotról, hogy az teljes megoldás-e. Esetünkben ez akkor igaz, ha a tömb hossza 8.&lt;/p&gt;

&lt;p&gt;Az első izgalmasabb dolgot a &lt;code&gt;next-states&lt;/code&gt; függvény végzi. Kiszámolja az &lt;code&gt;s&lt;/code&gt; nevű paraméterként kapott állapotból elérhető állapotok listáját. A &lt;code&gt;(range N)&lt;/code&gt; esetünkben a &lt;code&gt;(0 1 2 3 4 5 6 7)&lt;/code&gt; szekvenciává értékelődik ki. A &lt;code&gt;map&lt;/code&gt; végigmasíroz ezen a kollekción, és mindegyik elemet hozzácsapja &lt;code&gt;s&lt;/code&gt;-hez. A map értéke minden esetben egy nyolc elemű vector lesz. Lássunk két példát a &lt;code&gt;next-states&lt;/code&gt;-re:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='clojure'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;next-states&lt;/span&gt; &lt;span class='p'&gt;[])&lt;/span&gt;  &lt;span class='c1'&gt;; =&amp;gt; ([0] [1] [2] [3] [4] [5] [6] [7])&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;next-states&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;])&lt;/span&gt; &lt;span class='c1'&gt;; =&amp;gt; ([1 0] [1 1] [1 2] [1 3] [1 4] [1 5] [1 6] [1 7])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;El kell tudnunk dönteni azt, hogy két királynő támadja-e egymást egy bizonyos állapotban. Épp ezt teszi a következő függvény.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='clojure'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;attack?&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;s&lt;/span&gt; &lt;span class='nv'&gt;i&lt;/span&gt; &lt;span class='nv'&gt;j&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;xi&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;s&lt;/span&gt; &lt;span class='nv'&gt;i&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='nv'&gt;xj&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;s&lt;/span&gt; &lt;span class='nv'&gt;j&lt;/span&gt;&lt;span class='p'&gt;)]&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;or &lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;= &lt;/span&gt;&lt;span class='nv'&gt;xi&lt;/span&gt; &lt;span class='nv'&gt;xj&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;= &lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;distance&lt;/span&gt; &lt;span class='nv'&gt;xi&lt;/span&gt; &lt;span class='nv'&gt;xj&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;distance&lt;/span&gt; &lt;span class='nv'&gt;i&lt;/span&gt; &lt;span class='nv'&gt;j&lt;/span&gt;&lt;span class='p'&gt;)))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Az &lt;code&gt;s&lt;/code&gt; paraméter az állapotvektor, az &lt;code&gt;i&lt;/code&gt; és &lt;code&gt;j&lt;/code&gt; pedig a két összehasonlítandó királynő indexei. A két királynő az alábbi esetekben támadja egymást:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;egy oszlopban vannak &amp;#8211; ez itt a reprezentációból következően nem lehetséges&lt;/li&gt;

&lt;li&gt;egy sorban vannak &amp;#8211; &lt;code&gt;(= xi xj)&lt;/code&gt; feltétel&lt;/li&gt;

&lt;li&gt;átlósan támadják egymást &amp;#8211; ez akkor van, ha a sorindexeik különbsége megegyezik az oszlopindexeik különbségével, azaz &lt;code&gt;(= (distance xi xj) (distance i j))&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Azt is el kell tudnunk dönteni, hogy egy állapot érvényes-e, azaz nincs-e két olyan királynő, akik támadják egymást. Mivel az algoritmusunk csak érvényes állapotból lép tovább, elég csak azt megvizsgálnunk, hogy az utoljára felrakott királynő támadja-e valamelyik már korábban fentlévőt.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='clojure'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;valid-state?&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;s&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;max-idx&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;dec &lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;count &lt;/span&gt;&lt;span class='nv'&gt;s&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
        &lt;span class='nv'&gt;pairs&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;map &lt;/span&gt;&lt;span class='o'&gt;#&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list &lt;/span&gt;&lt;span class='nv'&gt;%&lt;/span&gt; &lt;span class='nv'&gt;max-idx&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;range &lt;/span&gt;&lt;span class='nv'&gt;max-idx&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
        &lt;span class='nv'&gt;no-attack?&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;fn &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;pair&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
                     &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;not &lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;attack?&lt;/span&gt; &lt;span class='nv'&gt;s&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;first &lt;/span&gt;&lt;span class='nv'&gt;pair&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;last &lt;/span&gt;&lt;span class='nv'&gt;pair&lt;/span&gt;&lt;span class='p'&gt;))))]&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;every? &lt;/span&gt;&lt;span class='nv'&gt;no-attack?&lt;/span&gt; &lt;span class='nv'&gt;pairs&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A &lt;code&gt;max-idx&lt;/code&gt; az utoljára felrakott királynő indexe. A &lt;code&gt;pairs&lt;/code&gt; azon indexpárok listája, amelyeket vizsgálnunk kell. Abban az esetben példul, ha most raktuk fel a negyedik királnyőt a &lt;code&gt;pairs&lt;/code&gt; értéke &lt;code&gt;((0 3) (1 3) (2 3))&lt;/code&gt; lesz, hiszen az új (3-as indexű) királynőt össze kell vetnünk a 0,1,2-es indexűvel. A &lt;code&gt;no-attack?&lt;/code&gt; egy függvény (predikátum), ami paraméterként egy indexpárt kap, és a korábban megírt &lt;code&gt;attack?&lt;/code&gt; függvény segítségével eldönti, hogy a pár-hoz tartozó királynők támadják-e egymást. A &lt;code&gt;valid-state?&lt;/code&gt; visszatérési értékét végül az &lt;code&gt;(every? no-attack? pairs)&lt;/code&gt; kifejezés szolgáltatja. Az &lt;code&gt;every?&lt;/code&gt; a &lt;code&gt;pairs&lt;/code&gt;-ban lévő összes indexpárral meghívja a &lt;code&gt;no-attack?&lt;/code&gt;-ot, és ha mindegyik &lt;code&gt;true&lt;/code&gt;-val tér vissza, akkor az értéke igaz lesz, egyébként hamis.&lt;/p&gt;

&lt;p&gt;Következő függvényünk megmondja, hogy egy állapotból milyen következő érvényes állapotokba mehetünk tovább.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='clojure'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;next-valid-states&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;s&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;filter &lt;/span&gt;&lt;span class='nv'&gt;valid-state?&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;next-states&lt;/span&gt; &lt;span class='nv'&gt;s&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Majd ezután nincs más hátra, mint megkeresnünk a megoldásokat. Ezt a rekurzív &lt;code&gt;backtrack&lt;/code&gt; függvény végzi. Paramérként egy állapotot kap. Ha ez az állapot egy megoldás, akkor visszatér vele, ez a rekurzió egyik alapesete (az alapeset - base case - az az ág, amikor a rekurzív függvény nem hívja meg magát). Minden más esetben kiszámolja a következő állapotok listáját, majd a &lt;code&gt;mapcat&lt;/code&gt; mindegyikre rekurzívan meghívja a &lt;code&gt;backtrack&lt;/code&gt;-et és a végén konkatenálja az eredményként kapott listákat. A másik alapeset az, amikor a következő állapotok listája egy üres lista. Az &lt;code&gt;eight-queens&lt;/code&gt;-nek, ami a végső megoldást szolgáltatja nem kell mást tennie, mint egy üres vektorral meghívnia a &lt;code&gt;backtrack&lt;/code&gt;-et.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='clojure'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;backtrack&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;state&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;if &lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;solution?&lt;/span&gt; &lt;span class='nv'&gt;state&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;state&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;next-states&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;next-valid-states&lt;/span&gt; &lt;span class='nv'&gt;state&lt;/span&gt;&lt;span class='p'&gt;)]&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;mapcat &lt;/span&gt;&lt;span class='nv'&gt;backtrack&lt;/span&gt; &lt;span class='nv'&gt;next-states&lt;/span&gt;&lt;span class='p'&gt;))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;eight-queens&lt;/span&gt; &lt;span class='p'&gt;[]&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;backtrack&lt;/span&gt; &lt;span class='p'&gt;[]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Végül néhány segédfüggvény, ami az eredmények kiírását végzi.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='clojure'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;format-solution&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;solution&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;letters&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;vec&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;seq &lt;/span&gt;&lt;span class='s'&gt;&amp;quot;ABCDEFGH&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
        &lt;span class='nv'&gt;positions&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;map &lt;/span&gt;&lt;span class='o'&gt;#&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;str-join&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;%1&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;+ &lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='nv'&gt;%2&lt;/span&gt;&lt;span class='p'&gt;)])&lt;/span&gt; &lt;span class='nv'&gt;letters&lt;/span&gt; &lt;span class='nv'&gt;solution&lt;/span&gt;&lt;span class='p'&gt;)]&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;str-join&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;, &amp;quot;&lt;/span&gt; &lt;span class='nv'&gt;positions&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;print-solutions&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;solutions&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;doseq &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;solution&lt;/span&gt; &lt;span class='nv'&gt;solutions&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;println &lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;format-solution&lt;/span&gt; &lt;span class='nv'&gt;solution&lt;/span&gt;&lt;span class='p'&gt;))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;print-all-solution&lt;/span&gt; &lt;span class='p'&gt;[]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;print-solutions&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;eight-queens&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Kicsit hosszúra sikerült ez a poszt, de ha valaki végiolvassa remélem felkelti az érdklődését a Clojure iránt. Hajrá!&lt;/p&gt;</content>
    </entry>
  
    <entry>
      <title>Pomodoro technika</title>
      <link href="http://hiperkocka.hu/blog/2009/05/10/pomodoro-technique.html"/>
      <updated>2009-05-10T00:00:00-07:00</updated>
      <id>http://hiperkocka.hu/blog/2009/05/10/pomodoro-technique.html</id>
      <content type="html">&lt;p&gt;A &lt;a href='http://www.pomodorotechnique.com'&gt;pomodoro technika&lt;/a&gt; egy egyszerű módszer arra, hogyan végezzük el napi feladatainkat kellemes és folyamatos tempóban. Segít elkerülni a halogatást. És segít a kívülről és belülről folyamatosan érkező zavaró tényezők leküzdésében.&lt;/p&gt;

&lt;p&gt;Az alapgondolat a nap felosztása 25 perces egységekre. Az időmérésre a hardcore pomodoro júzerek egy paradicsom alakú konyhai órát használnak, innen a módszer neve, a pomodoro olaszul paradicsomot jelent.&lt;/p&gt;

&lt;h3 id='a_mdszer_rvid_bemutatsa'&gt;A módszer rövid bemutatása&lt;/h3&gt;

&lt;p&gt;Tömören és velősen: következő feladat kiválasztva, óra 25 percre felteker, meló indul, meló megy, meló megy, meló megy, idő letel, óra csörög, pomodoro befejeződött. 25 perc elég rövid idő ahhoz, hogy maximálisan koncentrálni tudjunk az adott feladatra, és eseteleg az időközben beérkező zavaró tényezőket is el tudjuk tolni a végéig.&lt;/p&gt;

&lt;p&gt;A 25 perces időtartamot nevezzük &lt;em&gt;egy pomodoro&lt;/em&gt;-nak. Eztán 5 perc szünet következik, amikor is kötelező &lt;strong&gt;nem munkával&lt;/strong&gt; foglalkozni. Ez tökéletes alkalom, hogy készítsünk magunknak egy kávét, felkeressük a mellékhelységet vagy lecsekkoljuk az email fiókunkat. Amint letelt a szünet, kezdődik a következő pomodoro.&lt;/p&gt;

&lt;p&gt;Négy pomodoro után nagyszünet következik (mint az iskolában), ami 15-30 perc. Erre is érvényes mindaz, ami a kisszünetre. Ha letelt, a mókuskerék indul tovább.&lt;/p&gt;

&lt;p&gt;A &lt;a href='http://www.pomodorotechnique.com'&gt;pomodorotechnique.com&lt;/a&gt; weboldalról letölthető pdf-ből sokkal okosabbak lehetünk. Megtudhatjuk miért érdemes egy kis könyveléssel is kiegészíteni a mókát. Csináljunk naponta egy To-Do sheet-et, jelöljük melyik feladatra hány pomodoro-t használtunk. Nap végén ezt vezessük át perzisztensebb formába (adatbázis, excell sheet), hogy később rendelkezzünk statisztikával, amiből folyamatosan következtetéseket levonva fejleszthetjük magunkat tovább és tovább a &lt;a href='http://en.wikipedia.org/wiki/Getting_Things_Done'&gt;GTD&lt;/a&gt; és &lt;a href='http://agilemanifesto.org/'&gt;Agile&lt;/a&gt; nirvána felé vezető úton.&lt;/p&gt;

&lt;h3 id='sajt_tapasztalatok'&gt;Saját tapasztalatok&lt;/h3&gt;

&lt;p&gt;Egy hetes tesztidőszak után kijelenthetem, hogy látok fantáziát a dologban. A könyveléses és statisztkakészítős részből egyelőre csak annyit alkalmaztam, hogy valahova felírtam a feladatokat, és hogy hány pomodoro-nyi időt töltöttem velük. Valahogy az az érzésem, hogy jó lenne ezt szoftverrel megtámogatni, de még nem találtam ilyet.&lt;/p&gt;

&lt;p&gt;Szóval lássuk csak, hogy nekem miért tetszik:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Már gyerekkoromban is úgy nyírtam otthon a füvet, hogy téglalapokra osztottam a területet, és egyesével végezetem velük. A munkaidő felosztása 25 perces szakaszokra teljesen analogizál ezen perverz hajlammal.&lt;/li&gt;

&lt;li&gt;Amióta vannak az 5 perces szünetek nincs akkora rumli a dolgozószobámban, sőt az egész lakásban. Pár perc alatt csomó mindent odébb lehet rakni.&lt;/li&gt;

&lt;li&gt;Ha valami megszakítás érkezik, (pl. barátnő éppen filmet akar nézni, de nem tudja a feliratot beüzemelni), akkor sokkal meggyőzőbb a következő: &amp;#8220;várjál kicsi 5 percet, lejár a vekker és már ott is vagyok&amp;#8221;, minthogy &amp;#8220;na még ezt a webservice hívást lefejlesztem&amp;#8221;.&lt;/li&gt;

&lt;li&gt;Ha valamibe nagyon nincs kedvem belefogni, könnyebb úgy tekinteni rá, hogy csinálok 2 pomodoro-t, aztán abba is hagyom, ha végeztem, ha nem.&lt;/li&gt;

&lt;li&gt;Nap végén nem azt látom, hogy egy kis feladatot megcsináltam, aztán belekezdtem egy nagyobbba és azzal meg sehol sem állok, hanem azt, hogy összesen megcsináltam 10 pomodoro-t és ez jó érzés.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Az eddigi tapasztalataim tehát pozitívak, de meglátjuk mit hoz a jövő. Ha sikerül elmerülnöm a módszer rejtelmeibe elképzelhető, hogy írok még róla, addig is mindenkinek ajánlom a friss napérlelte olasz paradicsomot!&lt;/p&gt;

&lt;h4 id='id1'&gt;&lt;span class='highlighted'&gt;Frissítés (2009.07.08)&lt;/span&gt;&lt;/h4&gt;

&lt;p&gt;Néhány alkalmazás, melyek segíthetenek a módszer alkalmazásában:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://mytomatoes.com/'&gt;mytomatoes.com&lt;/a&gt; (webalkalmazás)&lt;/li&gt;

&lt;li&gt;&lt;a href='http://www.focusboosterapp.com/'&gt;focus booster&lt;/a&gt; (Adobe AIR kliens)&lt;/li&gt;

&lt;li&gt;&lt;a href='http://code.google.com/p/pomodairo/'&gt;Pomodairo&lt;/a&gt; (Adobe AIR kliens)&lt;/li&gt;

&lt;li&gt;&lt;a href='http://e.ggtimer.com/'&gt;e.ggtimer.com&lt;/a&gt; (online timer, webalkalmazás)&lt;/li&gt;

&lt;li&gt;&lt;a href='http://pomodoro.ugolandini.com/'&gt;Pomodoro Desktop&lt;/a&gt; (Mac alkalmazás)&lt;/li&gt;

&lt;li&gt;&lt;a href='http://tomatoist.com'&gt;tomatoist.com&lt;/a&gt; (webalkalmazás)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ha felfedeztek valami jópofa alkalmazást, ami nem szerepel a listán, írjátok meg kommentben, és frissítem a posztot. Egyébként, ha valaki nyomon akarja követni új eszközök megjelenését, akkor a &lt;a href='http://groups.google.com/group/pomodorotechnique'&gt;pomodorotechnique&lt;/a&gt; és a &lt;a href='http://groups.google.com/group/pomodorotechnique-timer'&gt;pomodorotechnique-timer&lt;/a&gt; google group-okat érdemes figyelni.&lt;/p&gt;</content>
    </entry>
  
    <entry>
      <title>Memori, avagy szótanulás az iWiW-en!</title>
      <link href="http://hiperkocka.hu/blog/2009/04/21/memori.html"/>
      <updated>2009-04-21T00:00:00-07:00</updated>
      <id>http://hiperkocka.hu/blog/2009/04/21/memori.html</id>
      <content type="html">&lt;style&gt;
  #box-table td, #box-table th { 
    border: 1px solid black;
    padding: 2px 4px;
  }

  #screenshot-table td {
    padding: 20px 50px;
  }

  #screenshot-table td p {
    text-align: center;
  }
&lt;/style&gt;
&lt;p&gt;Ha minden igaz ma hajnalban élesbe áll az iWiW-re fejlesztett alkalmazásom, ami a keresztségben a Memori nevet kapta. Idegen nyelvű szavak, kifejezések tanulását támogatja a &lt;a href='http://en.wikipedia.org/wiki/Flashcard'&gt;Leitner módszer&lt;/a&gt; segítségével. A módszer egy pofonegyszerű algoritmus, aminek eredményeként a tanulásra szánt időnket hatékonyabban tudjuk kihasználni, mintha egy szótárfüzetből bifláznánk a szavakat. Mitől hatékony? Attól, hogy a számunkra könnyebb szavakat kevesebbszer, a nehezebbeket többször kérdezi. Lássuk a részleteket!&lt;/p&gt;

&lt;h2 id='a_leitner_mdszer'&gt;A Leitner módszer&lt;/h2&gt;

&lt;p&gt;Van N db dobozunk, megszámozva egytől N-ig. A tanulandó szavainkat kártyákra írjuk, egyik oldalára magyarul a másikra mondjuk angolul, és a dobozokba rakjuk, kezdetben az első dobozba. Gyakorlás során húzunk véletlenszerűen egy kártyát a k-dik dobozból, megnézzük a magyar kifejezést, majd megpróbáljuk felidézni az angolt. Ha nem sikerül visszatesszük az első dobozba, ha viszont igen, akkor egy időre félretesszük a kártyát pihentetni (minél magasabb számú dobozból vettük elő, annál nagyobb ez az idő), majd visszatesszük a k+1-dik számű dobozba.&lt;/p&gt;
&lt;p class='mar_top center'&gt;
  &lt;img src='/images/leitner.png' alt='leitner method' /&gt;
  &lt;p class='mar_bot' style='text-align: center;'&gt;&lt;small&gt;kártyák mozgása a tanulás során&lt;/small&gt;&lt;/p&gt;
&lt;/p&gt;
&lt;p&gt;A Memoriban 5 dobozunk van, és az idő, amíg a program egy sikeres gyakorlás után pihenteti a kártyát a következő táblázat szerint alakul:&lt;/p&gt;
&lt;div class='center'&gt;
  &lt;table class='mar_top mar_bot' id='box-table'&gt;
    &lt;tr&gt;&lt;th&gt;doboz száma&lt;/th&gt;&lt;th&gt;pihentetési idő&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;2. doboz&lt;/td&gt;&lt;td&gt;1 nap&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;3. doboz&lt;/td&gt;&lt;td&gt;3 nap&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;4. doboz&lt;/td&gt;&lt;td&gt;7 nap&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;5. doboz&lt;/td&gt;&lt;td&gt;30 nap&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Az első doboz nincs benne a táblázatban, hisz itt csak új, vagy sikertelenül gyakorolt szavak lehetnek, ezeket mindig kérdezi a program.&lt;/p&gt;

&lt;h2 id='hogy_is_nz_ki'&gt;Hogy is néz ki?&lt;/h2&gt;

&lt;p&gt;Az alábbi 4 képen a Memori legfontosabb funckiói láthatók. Az 1. ábrán lévő listában minden leckéhez található egy diagram, ez hivatott mutatni a szavak dobozonkénti eloszlását. Az első oszlop felel meg az első doboznak, a második a másodiknak, és így tovább. Piros szín jelzi azokat a kártyákat, amelyeket gyakorolnunk kell, a barna szín az inaktív kártyákat mutatja. (Inaktívak azok, melyeket legutóbb sikeresen ismételtünk, de még nem telt le a dobozukhoz tartozó pihentetési idő.)&lt;/p&gt;

&lt;p&gt;Gyakorlás során (4. kép) a felhasználó megnézi a kártya előlapját, megpróbálja felidézni a kifejezést, esetleg megnézi a hátoldalt ha szükséges, majd nyilatkozik, hogy tudta-e. Füllenteni nem érdemes, mert magunkat csapjuk be. :)&lt;/p&gt;

&lt;p&gt;Abban az esetben, ha tudjuk, hogy egy iWiW-es ismerősünk már felvitt egy olyan leckét, melyet gyakorolni szeretnénk, a szavak begépelését is megspórolhatjuk. Az ismerőseim menüpontban (3. kép) megkeressük az emberünket, s lehetőségünk van átvenni a leckéjét.&lt;/p&gt;
&lt;table class='mar_top mar_bot' id='screenshot-table'&gt;
  &lt;tr&gt;
    &lt;td class='bor_bot bor_rgt'&gt;
      &lt;a href='http://www.flickr.com/photos/28971311@N08/3463937458/'&gt;&lt;img src='http://farm4.static.flickr.com/3614/3463937458_0e7b1ced23_m.jpg' alt='memori screenshot' /&gt;&lt;/a&gt;
      &lt;p&gt;&lt;small&gt;1.kép - leckék listája&lt;/small&gt;&lt;/p&gt;
    &lt;/td&gt;
    &lt;td class='bor_bot'&gt;
      &lt;a href='http://www.flickr.com/photos/28971311@N08/3463937782/'&gt;&lt;img src='http://farm4.static.flickr.com/3643/3463937782_e7a9f32ddc_m.jpg' alt='memori screenshot' /&gt;&lt;/a&gt;
      &lt;p&gt;&lt;small&gt;2. kép - lecke szerkesztése&lt;/small&gt;&lt;/p&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class='bor_rgt'&gt;
      &lt;a href='http://www.flickr.com/photos/28971311@N08/3463937928/'&gt;&lt;img src='http://farm4.static.flickr.com/3597/3463937928_30627d2b56_m.jpg' alt='memori screenshot' /&gt;&lt;/a&gt;
      &lt;p&gt;&lt;small&gt;3. kép - ismerősök leckéi&lt;/small&gt;&lt;/p&gt;
    &lt;/td&gt;
    &lt;td&gt;
      &lt;a href='http://www.flickr.com/photos/28971311@N08/3463120961/'&gt;&lt;img src='http://farm4.static.flickr.com/3647/3463120961_05b3dd16eb_m.jpg' alt='memori screenshot' /&gt;&lt;/a&gt;
      &lt;p&gt;&lt;small&gt;4. kép - lecke gyakorlása&lt;/small&gt;&lt;/p&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;Remélem, hogy sikerült egy hasznos alkalmazást összekalapálnom. Jó sok időmet elvitte a fejlesztés, ezúton is köszönöm &lt;a href='http://pappkrisztina.hu'&gt;pkitti&lt;/a&gt; véget nem érő türelmét, amivel tolerálta az éjszakai kódoló szeánszokat. :)&lt;/p&gt;

&lt;p&gt;Rengeteg funkció implementálására már nem maradt idő, de ha a használati statisztika is úgy akarja majd, fogom még továbbfejleszteni a Memorit. Holnaptól a hibajavításé az elsődleges prioritás, ha bug-ot észleltek, jelezzétek itt a hozzászólásokban, vagy a memori kukac hiperkocka.hu email címen.&lt;/p&gt;

&lt;p&gt;Mindenkinek kellemes tanulást! :)&lt;/p&gt;</content>
    </entry>
  
    <entry>
      <title>Hiperkocka újra száguld</title>
      <link href="http://hiperkocka.hu/blog/2008/11/15/hiperk-ujratoltve.html"/>
      <updated>2008-11-15T00:00:00-08:00</updated>
      <id>http://hiperkocka.hu/blog/2008/11/15/hiperk-ujratoltve.html</id>
      <content type="html">&lt;p&gt;A hiperkocka.hu első verziója nem volt túl hosszú életű. 3 nap alatt 3 poszt augusztusban. A &lt;a href='http://blogger.com'&gt;Blogger.com&lt;/a&gt; jó választásnak tűnt, de mégsem vált be nálam. Nem bírtam megbarátkozni a böngészőben való szövegszerkesztéssel. Folyamatosan ment a copy-paste a Firefox és a desktop texteditor között. Ugyanez, ha a stylesheet-en akartam változtatni. Kissé nehézkes volt, így időlegesen abba is maradt az írás.&lt;/p&gt;

&lt;p&gt;De csak időlegesen, mert az elmúlt egy hétben ismét kézbe vettem a dolgokat. Azért csak most, mert szeptember, október kissé fullosra sikerült. A napi nyolc órás meló mellé beütött egy ruby-s fejlesztés, amire cirka 1 hónapunk volt. Aztán szívtunk az üzembeállítással is pár hetet, de jelenleg vígan muzsikál a cucc. Csak annyit mondok: &lt;a href='http://merbivore.org'&gt;Merb&lt;/a&gt; IBM Websphere-en!!! Az első pénzes ruby-s meló, kötelező volt elvállalni. Lesz még róla szó itt.&lt;/p&gt;

&lt;h2 id='az_jjszletst_segtette_webby'&gt;Az újjászületést segítette: &lt;a href='http://webby.rubyforge.org/'&gt;Webby&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Az &lt;a href='http://ruby.meetup.hu/blog/2008/10/23/budapest-rb-oktoberi-eloadasok.html'&gt;októberi Budapest.rb&lt;/a&gt;-n is volt szó a webby-ről, de már korábban felkeltette az érdeklődésemet eme frappáns megoldás. De miért is jó ez nekem?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a saját szövegszerkesztőmben írhatom a posztokat, faraghatom az oldalt&lt;/li&gt;

&lt;li&gt;az egészet verziókezelőben tarthatom (a bejegyszéseket is!!!)&lt;/li&gt;

&lt;li&gt;mivel a webby kimenetén statikus fájlok jönnek ki (html, css, js, xml), ezeket egy webszerverre felmásolva már megy is az oldal, nem kell se adatbázis, se ruby, se semmi a kiszolgáló gépre&lt;/li&gt;

&lt;li&gt;használhatok template nyelveket tetszés szerint (&lt;a href='http://haml.hamptoncatlin.com/docs/rdoc/classes/Sass.html'&gt;sass&lt;/a&gt;-t a stylesheet-ekhez, &lt;a href='http://haml.hamptoncatlin.com/tutorial/'&gt;haml&lt;/a&gt;-t, &lt;a href='http://hobix.com/textile/'&gt;textile&lt;/a&gt;-t, &lt;a href='http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/'&gt;erb&lt;/a&gt;-t a html-ekhez)&lt;/li&gt;

&lt;li&gt;mert ruby, és szeretem :)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A külcsín egyszerű lett, még faragom, de a tartalomra kellene innentől fogva koncentrálni.&lt;/p&gt;</content>
    </entry>
  
    <entry>
      <title>sqlplus command line history Linux alatt</title>
      <link href="http://hiperkocka.hu/blog/2008/08/10/sqlplus-command-line-history-linux-alatt.html"/>
      <updated>2008-08-10T00:00:00-07:00</updated>
      <id>http://hiperkocka.hu/blog/2008/08/10/sqlplus-command-line-history-linux-alatt.html</id>
      <content type="html">&lt;p&gt;Fel kell installálnunk az rlwrap programot. Ubuntura például így:&lt;/p&gt;
&lt;pre&gt;
$ sudo apt-get install rlwrap&lt;/pre&gt;
&lt;p&gt;Majd indítsuk az sqlplus-t az alábbi módon:&lt;/p&gt;
&lt;pre&gt;
$ rlwrap sqlplus&lt;/pre&gt;
&lt;p&gt;Ha valaki lusta készíthet rá aliast a .bashrc-ben:&lt;/p&gt;
&lt;pre&gt;
alias sqlplus='rlwrap sqlplus'&lt;/pre&gt;
&lt;p&gt;És készen is vagyunk. Have fun!&lt;/p&gt;</content>
    </entry>
  
    <entry>
      <title>Jogosultságok Oracle DB-ben</title>
      <link href="http://hiperkocka.hu/blog/2008/08/10/jogosultsagok-oracle-db-ben.html"/>
      <updated>2008-08-10T00:00:00-07:00</updated>
      <id>http://hiperkocka.hu/blog/2008/08/10/jogosultsagok-oracle-db-ben.html</id>
      <content type="html">&lt;p&gt;A minap szembesültem egy jogosultági problémával Oracle-ben, s mivel régen volt már az OCP vizsga, és én gyorsan felejtek, kénytelen voltam felfrissíteni ismereteimet a témában. Ha már így jártam, s mivel ketten is Oracle-ös posztokra nyilvánították ki igényüket a nyitóbejegyzés kommentjeiben, gondoltam írok a témáról.&lt;/p&gt;

&lt;h2 id='jogosultsgok_tpusai'&gt;Jogosultságok típusai&lt;/h2&gt;

&lt;p&gt;Két fajta jogosultság létezik Oracle-ben: objektum szintű (object privileges), és rendszer szintű (system privileges). A műveletet, amivel jogot adunk egy user-nek bizonyos dologra szép magyarul grantolásnak nevezzük, és meglepő mód a GRANT utasítással lehet elvégezni. Visszavonni a REVOKE-kal lehet.&lt;/p&gt;
&lt;dl&gt;

&lt;dt&gt;Rendszer szintű privilégiumok&lt;/dt&gt; 
&lt;dd&gt;
ilyen bizonyos műveletek végrehajtásának joga (pl.: csatlakozás az adatbázishoz, vagy táblatér létrehozása), és idetartoznak azon jogosultságok amik egy séma összes azonos típusú objektumára vonatkoznak (pl.: lekérdezés egy séma bármelyik táblájából).
&lt;/dd&gt;

&lt;dt&gt;Objektum szintű privilégiumok&lt;/dt&gt;
&lt;dd&gt;
egy bizonyos művelet végrehajtásának joga egy bizonyos séma egy bizonyos objektumán (pl.: sorok törlésének joga a HR user DEPARTMENTS tábláján). Bizonyos típusú objektumokhoz (CLUSTER, INDEX, TRIGGER, DATABASE LINK) nem tartoznak objektumszintű privilégiumok, hanem csak rendszer szintűek. Ha egy szinonímára grantolunk objektum szintű privilégiumot, akkor az egyenértékű azzal, mintha a szinoníma által hivatkozott objektumra grantolnánk. A szinoníma eldobása után a jog nem is fog elveszni.
&lt;/dd&gt;

&lt;/dl&gt;
&lt;h2 id='szerepek'&gt;Szerepek&lt;/h2&gt;

&lt;p&gt;Jogosultságokat adhatunk felhasználóknak (user) és szerepeknek (role). Mire jók a szerepek? Segítségükkel összefoghatunk privilégiumokat, és ezeket egyszerre oszthatjuk ki felhasználóknak, sőt akár más szerepeknek is, így egyszerűsíthetjük az adiminsztrációt.&lt;/p&gt;

&lt;p&gt;Szerepek munkamenet (session) szinten lehetnek ki- és bekapcsolt állapotban. SET ROLE utasítással tudjuk ezt megtenni. Fontos tudni, hogy Oracle-ön belüli programoknak (függvények, eljárások, csomagok) közvetlenül kell kiosztani a jogosultságokat, szerepeken keresztül kiosztott jogosultságot nem használhatnak. Hiszen fordítási időben nem tudhatja az adatbázis, hogy mikor majd a program futni fog, a szükséges szerep aktív állapotban lesz-e.&lt;/p&gt;

&lt;h2 id='with_admin_option_with_grant_option'&gt;with admin option, with grant option&lt;/h2&gt;

&lt;p&gt;Rendszer szintű privilégium és szerep esetén a WITH ADMIN OPTION megadásával megengedhetjük, hogy a felhasználó, aki kapta a jogot vagy szerepet, tovább is adhassa azt másoknak. Objektum szintű privilégiumok esetén a WITH GRANT OPTION-t kell használnunk, ha azt akarjuk, hogy tovább lehessen adni szerepeknek vagy felhasználóknak.&lt;/p&gt;

&lt;p&gt;Ha WITH ADMIN OPTION-nel jogot adtunk Bobónak, majd visszavonjuk, de ő addigra már tovább grantolta Benőnek, akkor a továbbadott jogot Benő nem fogja elveszíteni. Viszont objektum szintű privilégium esetén, ha WITH GRANT OPTION-nel kiosztottuk Bobónak valami, aki továbbadta Benőnek, ezután visszavonjuk Bobótól, akkor ezzel a mozdulattal Benőtől is visszavontuk. Fincsi mi?&lt;/p&gt;

&lt;h2 id='jogosultsgok_kiosztsa'&gt;Jogosultságok kiosztása&lt;/h2&gt;

&lt;p&gt;Objektum szintű jogosultságot adunk Bobo nevű kollégának, hogy módosíthassa a departments tábla department_name oszlopát.&lt;/p&gt;
&lt;pre&gt;
SQL&gt; GRANT UPDATE (department_name) ON departments TO bobo;&lt;/pre&gt;
&lt;p&gt;A looser_privs szerepnek jogot adunk, hogy bármilyen táblát eldobhasson, majd Bobo megkapja a looser_privs-t.&lt;/p&gt;
&lt;pre&gt;
SQL&gt; GRANT DROP ANY TABLE TO looser_privs;
SQL&gt; GRANT looser_privs TO bobo;&lt;/pre&gt;
&lt;p&gt;Majd rájövünk, hogy inkább visszavonunk mindent&lt;/p&gt;
&lt;pre&gt;
SQL&gt; REVOKE UPDATE ON departments FROM bobo;
SQL&gt; REVOKE DROP ANY TABLE FROM looser_privs;&lt;/pre&gt;
&lt;h2 id='jogosultsgok_lekrdezse'&gt;Jogosultságok lekérdezése&lt;/h2&gt;

&lt;p&gt;A következő nézetekből tudjuk lekérdezni, hogy kinek milyen jogosultságai vannak:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;DBA_USERS&lt;/dt&gt;&lt;dd&gt;adatbázisban található felhasználók.&lt;/dd&gt;
&lt;dt&gt;DBA_ROLES&lt;/dt&gt;&lt;dd&gt;adatbázisban található szerepek.&lt;/dd&gt;
&lt;dt&gt;DBA_TAB_PRIVS&lt;/dt&gt;&lt;dd&gt;felhasználóknak és szerepeknek kiosztott objektum szintű jogosultságok. Ne zavarjon meg senkit a tábla neve, az összes&lt;/dd&gt;
&lt;dt&gt;DBA_SYS_PRIVS&lt;/dt&gt;&lt;dd&gt;felhasználóknak és szerepeknek kiosztott rendszer szintű jogosultságok.&lt;/dd&gt;
&lt;dt&gt;DBA_ROLE_PRIVS&lt;/dt&gt;&lt;dd&gt;felhasználóknak és szerepeknek kiosztott szerepek.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;A végére pedig jöjjön három trükkös lekérdezés (&lt;a href='http://www.adp-gmbh.ch/ora/misc/recursively_list_privilege.html'&gt;forrás&lt;/a&gt;). Az első megadja, hogy egy user-nek, milyen szerepei vannak (rekurzívan) és a szerepeken keresztül milyen rendszerszintű privilégiumokkal rendelkezik.&lt;/p&gt;
&lt;script src='http://gist.github.com/26456.js' /&gt;
&lt;p&gt;Megkeresi egy adott rendszer szintű privilégiumhoz, hogy milyen szerepek rendelkeznek vele (rekurzívan) és ezek a szerepek milyen felhasználókhoz tartoznak.&lt;/p&gt;
&lt;script src='http://gist.github.com/26458.js' /&gt;
&lt;p&gt;Megkeresi, hogy adott séma adott objektumára milyen objektumszintű privilégiumok vannak kiosztva közvetlenül vagy szerepeken keresztül (rekurzívan).&lt;/p&gt;
&lt;script src='http://gist.github.com/26459.js' /&gt;</content>
    </entry>
  
    <entry>
      <title>A hiperkocka el van vetve</title>
      <link href="http://hiperkocka.hu/blog/2008/08/07/a-hiperkocka-el-van-vetve.html"/>
      <updated>2008-08-07T00:00:00-07:00</updated>
      <id>http://hiperkocka.hu/blog/2008/08/07/a-hiperkocka-el-van-vetve.html</id>
      <content type="html">&lt;p&gt;Pár hónapja merült fel az ötlet bennem, hogy kellene egy blogot indítanom. Ezt felindulásból elkövetett domainregisztráció követte, majd egy rövidebb szünet, mialatt fontos kérdesekre kerestem a választ.&lt;/p&gt;

&lt;h2 id='mirl'&gt;Miről?&lt;/h2&gt;

&lt;p&gt;Speciel ezen sokat nem kellett gondolkodnom. Arról írok amivel épp foglalkozom. Többnyire kocka, magyarul informatikai témák várhatók. De elképzelhető, hogy becsusszan néhány más témájú poszt: zene, film esetleg valami személyes. A kockatémák folyamatosan bővülő és korántsem teljes listája alfabetikus sorrendben: css, html, javascript, linux, oracle, rails, ruby.&lt;/p&gt;

&lt;h2 id='mirt'&gt;Miért?&lt;/h2&gt;

&lt;p&gt;Fő motiváció: a siker, pénz, csillogás. Mindemellett nem elhanyagolható, hogy az írás az adott poszt témájának alaposabb megismerésére ösztönöz. Mer hülyeséget terjeszteni nem akarok ugyebár. Másrészt hajlamos vagyok dolgokat hosszútávon elfelejteni, így gondolataim egy adott pillanatbeli állapotának dokumentációjától a jövőbeli &amp;#8220;Hogy a picsába is volt ez?&amp;#8221; típusú költői kérdések számának drasztikus csökkenését várom.&lt;/p&gt;

&lt;h2 id='hogyan'&gt;Hogyan?&lt;/h2&gt;

&lt;p&gt;Na ezen sokat töprengtem. A megoldásnak a következő szempontokat kellett kielégítenie:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;saját domain alatt kell futnia a blognak&lt;/li&gt;

&lt;li&gt;full control over HTML és CSS&lt;/li&gt;

&lt;li&gt;ráfordított költségek minimalizálása&lt;/li&gt;

&lt;li&gt;ráfordított munkamennyiség minimalizálása&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kacérkodtam a gondolattal, hogy saját kis VPS-emen (Slicehost) futattok egy blogalkalmazást, pl. Mephisto (PHP-hez nem értek, ezért Wordpress nem jött szóba). Ezzel az abszolút szabadságot kaptam volna, de a 4. pont erőteljes sérülése árán. Elvetve.&lt;/p&gt;

&lt;p&gt;Ígéretesnek tűnt a WPress.hu prémium blogszolgáltatása. Nagyon tetszik a Wordpress adminisztrációs felülete, és a Google Gears beépítése is folyamatban van (mekkora jóság lesz, ha offline is megírhatja a júzer kis posztját a böngészőben). Viszont 2500Ft + ÁFA a havidíj, amit számomra kicsit sok tekintetbe véve, hogy a blog olvasóinak száma ebben a pillanatban (még) nulla. Elvetve.&lt;/p&gt;

&lt;p&gt;Próbálkoztam még wordpress-com-mal is. Náluk 10 kredit a saját domainnév plusz 15 kredit a szerkeszthető CSS egy évre. Az 1kredit = 1 dolláros árfolyamon, ha jól számolom 25$. Ez nem is rossz, de mivel találtam még ennél is jobbat, csak az ezüstérmet tudták megszerezni. Elvetve.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And the Grammy goes túúúú:&lt;/em&gt; Blogger.com. Saját domainnév ingyér, teljesen hatalom a CSS és a HTML felett ingyér, és a hit abban, hogy a Google érti a dolgát elég volt a győzelemhez. (Megj.: az aranyéremhez az is kellett, hogy egy kis trükk segítségével el lehetett tüntetni a Blogger-es blogok tetején szokásos navbar-t)&lt;/p&gt;

&lt;p&gt;A blog fejlesztésénél az inkrementális elv érvényesül majd. Magyarul mindent később fogok majd megcsinálni. De hát posztot írni már lehet, RSS működik, minden más mellékes, szóval GO LIVE!!!&lt;/p&gt;</content>
    </entry>
  
</feed>
