<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4341013927520812102</id><updated>2012-02-16T15:06:57.194Z</updated><category term='Personal'/><category term='Popcap'/><category term='Python'/><category term='marathon'/><category term='nutrition'/><category term='donate'/><category term='Global Warming'/><category term='Solar'/><category term='Connemara'/><category term='Programming'/><category term='Code'/><category term='Source'/><category term='RoadID'/><category term='charity'/><category term='sports'/><category term='Project Euler'/><category term='Writing'/><category term='side projects'/><category term='Ecology'/><category term='App'/><category term='jQuery'/><category term='Wireframing'/><category term='UNICEF'/><category term='Data structures'/><category term='Design'/><category term='brain'/><category term='Earth Day'/><category term='Astronomy'/><category term='StencilsApp'/><category term='Science'/><category term='Green tech'/><category term='Algorithms'/><category term='Open Source'/><category term='Mockup'/><category term='running'/><category term='iPhone'/><category term='uplift.in'/><category term='Daily Notes'/><category term='Cocoa'/><category term='Treap'/><category term='random thoughts'/><category term='JavaScript'/><category term='Dublin marathon'/><category term='health'/><category term='ObjectiveC'/><category term='fitness'/><category term='Blog'/><category term='AppStore'/><category term='Vibram'/><category term='Erlang'/><category term='n-back'/><title type='text'>dragozov.com</title><subtitle type='html'>.: here be dragonz :.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.dragozov.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>21</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-2822637347938727021</id><published>2011-11-15T01:55:00.003Z</published><updated>2011-11-15T02:12:15.676Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Popcap'/><category scheme='http://www.blogger.com/atom/ns#' term='Daily Notes'/><category scheme='http://www.blogger.com/atom/ns#' term='Personal'/><title type='text'>Moving on</title><content type='html'>I'll be leaving &lt;a href="http://popcap.com"&gt;Popcap&lt;/a&gt; in the end of December. I'm halfway through my 3 months (!!!) notice and it's now just a question of winding up my work and spending the last few weeks with my colleagues.&lt;br /&gt;&lt;br /&gt;It's the fourth place in a row where I decide that I've had enough and it's time to move on (in fact, the only time when I didn't leave by choice is when they kicked me out for mixing alcohol and water at a bar where I worked as a student, but that's a different story). &lt;br /&gt;Maybe it's just me, but jobs feel like a snake's skin - sooner or later you reach the limit and the only way to grow is to throw it and get a new one. &lt;br /&gt;&lt;br /&gt;This time it's different though. Instead of looking for work at someone else's company, I'll focus on my own ideas and try to create products and a business around them. I won't be calling it a startup yet and don't want to hype it too much. It's just a few things I'd like to try and I'll spend the next 6-12 months looking for gold nuggets or getting my butt kicked by the universe.&lt;br /&gt;&lt;br /&gt;Thankfully the last 12 years gave me the experience to believe I know what I'm doing and enough savings to be able to afford an experiment or two. But probably the most important, I can count on my family for all the support and all the pressure I can wish for (and maybe a little more).&lt;br /&gt;Plus I've already done some crazy things that looked pretty impossible in the beginning. It can't be that much harder than loosing 40 kilograms or running a marathon. &lt;br /&gt;Right?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-2822637347938727021?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/2822637347938727021/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=2822637347938727021&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/2822637347938727021'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/2822637347938727021'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2011/11/moving-on.html' title='Moving on'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-2693222243815529838</id><published>2011-10-06T19:47:00.002+01:00</published><updated>2011-10-06T19:55:41.297+01:00</updated><title type='text'>R.I.P. Steve Jobs</title><content type='html'>A really sad day. &lt;br /&gt;&lt;iframe width="420" height="315" src="http://www.youtube.com/embed/UF8uR6Z6KLc" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-2693222243815529838?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/2693222243815529838/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=2693222243815529838&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/2693222243815529838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/2693222243815529838'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2011/10/rip-steve-jobs.html' title='R.I.P. Steve Jobs'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/UF8uR6Z6KLc/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-4993433421252123728</id><published>2011-09-16T23:58:00.002+01:00</published><updated>2011-09-24T18:08:05.188+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Daily Notes'/><category scheme='http://www.blogger.com/atom/ns#' term='random thoughts'/><title type='text'>Diversity</title><content type='html'>Why on earth are people so different?! &lt;br /&gt;What I see as the end, is the beginning for someone. &lt;br /&gt;And often my dreams are the nightmares for others.&lt;br /&gt;&lt;br /&gt;Thank god that people are so different!&lt;br /&gt;Or no one would take over when I've had enough.&lt;br /&gt;And my dreams would be all worn-out and crowded.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-4993433421252123728?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/4993433421252123728/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=4993433421252123728&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/4993433421252123728'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/4993433421252123728'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2011/09/diversity.html' title='Diversity'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-6216712441624154727</id><published>2011-09-07T22:17:00.001+01:00</published><updated>2011-09-10T22:53:00.629+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Daily Notes'/><title type='text'>What's next?</title><content type='html'>I haven't blogged much lately, mostly because I was busy, but also because some pretty &lt;a href="http://www.gamasutra.com/view/news/35828/Electronic_Arts_Confirms_750M_PopCap_Acquisition_550M_Earnout.php"&gt;exciting things&lt;/a&gt; were happening at my current job and I was waiting for things to settle.&lt;br /&gt;Now it's all done and dusted. And my life is completely upside-down!&lt;br /&gt;&lt;br /&gt;I've never imagined that being so free to choose what to do next would be that frightening.&lt;br /&gt;Should I pick some of the less risky options or do I just jump and do what I've always dreamed of? What if I choose wrong? What if I fail? Am I capable enough? Can I afford it?&lt;br /&gt;It's so much easier when there is someone or something to blame, when there are "good" reasons to delay your decisions and your plans for the future are in the future.&lt;br /&gt;&lt;br /&gt;So what will I do? &lt;br /&gt;Haven't quite decided yet. Though one thing is for sure - there will be changes. Soon! &lt;br /&gt;&lt;br /&gt;Until then I'll be doing lots of traveling, meeting people, talking to family and friends and figuring out things. &lt;br /&gt;Oh, and I'll be writing here much more frequently .&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-6216712441624154727?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/6216712441624154727/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=6216712441624154727&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/6216712441624154727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/6216712441624154727'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2011/07/i-havent-blogged-much-lately-mostly.html' title='What&apos;s next?'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-3056174147390815743</id><published>2011-06-22T21:57:00.003+01:00</published><updated>2011-06-22T23:08:10.740+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Daily Notes'/><category scheme='http://www.blogger.com/atom/ns#' term='uplift.in'/><category scheme='http://www.blogger.com/atom/ns#' term='side projects'/><title type='text'>uplift.in</title><content type='html'>I'm somewhat of a domain addict. If I encounter a nice unregistered or expiring domain and can think of a cool idea to match it, I'd register the name as a reminder. Then every time I have to do some maintenance at my registrar,  I'd go through the list of currently unused domains (it's just a few, I'm not a squatter) and for each idea revisit if I want to do something about it immediately, hold on it for a little longer or just forget it and drop the name.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://uplift.in"&gt;Uplift.in&lt;/a&gt; is one such domain that I bought last year with the idea of building a service for publishing only positive, feel-good, &lt;span style="font-weight:bold;"&gt;uplifting&lt;/span&gt; news. For one or another reason I feel like starting this now and pushed an initial version last night.&lt;br /&gt;It's a stock installation of &lt;a href="http://pligg.com/"&gt;Pligg&lt;/a&gt; at the moment, but I'll be working on the design and the content in the next few months. There may be also some additional cool features on the "roadmap". &lt;br /&gt;By the way I have no business plan about this and there won't be ads on the site. Just a nice community service to warm you up:)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-3056174147390815743?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/3056174147390815743/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=3056174147390815743&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/3056174147390815743'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/3056174147390815743'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2011/06/upliftin.html' title='uplift.in'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-1568674767981468744</id><published>2011-06-15T19:34:00.004+01:00</published><updated>2011-06-15T20:06:09.323+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='n-back'/><category scheme='http://www.blogger.com/atom/ns#' term='Science'/><category scheme='http://www.blogger.com/atom/ns#' term='Daily Notes'/><category scheme='http://www.blogger.com/atom/ns#' term='brain'/><title type='text'>IQ Pushups</title><content type='html'>I've been playing with &lt;a href="http://brainworkshop.sourceforge.net/"&gt;Brain Workshop&lt;/a&gt; lately. It's a free (open source) software that implements the &lt;span style="font-weight:bold;"&gt;dual task n-back&lt;/span&gt; exercise and lets you play with different levels of difficulty.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;What is n-back?&lt;span style="font-style:italic;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;According to some recent &lt;a href="http://blogs.discovermagazine.com/notrocketscience/2011/06/13/can-intelligence-be-boosted-by-a-simple-task-for-some/"&gt;research&lt;/a&gt; this is brain-training that actually works. Do it 20 minutes per day for a few weeks and chances are you'll be measurably smarter (for a very specific definition of smart)! &lt;br /&gt;Like with physical exercise mileage could vary, but it's still pretty fascinating news.&lt;br /&gt;&lt;br /&gt;So nothing surprising in the sudden spike of intelligence at this blog.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-1568674767981468744?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/1568674767981468744/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=1568674767981468744&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/1568674767981468744'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/1568674767981468744'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2011/06/iq-pushups.html' title='IQ Pushups'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-6262507172776616310</id><published>2011-06-14T21:06:00.006+01:00</published><updated>2011-06-14T21:57:33.261+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Astronomy'/><category scheme='http://www.blogger.com/atom/ns#' term='Science'/><category scheme='http://www.blogger.com/atom/ns#' term='Global Warming'/><category scheme='http://www.blogger.com/atom/ns#' term='Daily Notes'/><title type='text'>An ice age ahead?</title><content type='html'>I find this &lt;a href="http://news.discovery.com/space/is-the-sun-about-to-fizz-out-110614.html"&gt;piece of science news&lt;/a&gt; quite ironic. It's like the Universe is showing us its middle finger to remind us how small and insignificant we are. &lt;br /&gt;&lt;br /&gt;Surprising results from 3 projects researching the Sun point to a big drop in the solar activity for the next few decades. This may (or may not) trigger a global ice age for most of the century or at least could slow down the mess of a global warming we are causing to the planet. &lt;br /&gt;Not that it's going to solve much of our problems anyway. We'll still need lots of clean air, fresh water and food and who knows how much of the Earth's already struggling flora and fauna can survive a potential freeze. Plus we'll have to burn lots of coal and oil to keep those 7 billion and growing bodies warm.&lt;br /&gt;On the bright side the polar bears may be safe (for a while).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-6262507172776616310?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/6262507172776616310/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=6262507172776616310&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/6262507172776616310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/6262507172776616310'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2011/06/ice-age-ahead.html' title='An ice age ahead?'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-2082501727570607034</id><published>2011-06-14T00:21:00.002+01:00</published><updated>2011-06-14T00:50:39.581+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Daily Notes'/><category scheme='http://www.blogger.com/atom/ns#' term='Open Source'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>Monitoring the execution of asynchronous JavaScript callbacks</title><content type='html'>In JavaScript sometimes it's useful to know if an asynchronous callback function was called, how many times and if it completed or failed. Of course you could implement it by changing some state in the outside scope, but this means adding code to the function and it won't  work for existing 3rd party code.&lt;br /&gt;I've written a small jQuery extension, &lt;a href="https://github.com/dragozov/bits.and.pieces.js/blob/master/src/jquery.monitor.js"&gt;jquery.monitor.js&lt;/a&gt;, (there is no actual jQuery dependency in the implementation by the way) which creates a wrapper around the callback function that keeps the latest call status and history in a property called &lt;span style="font-weight:bold;"&gt;monitor&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;pre class="brush: js"&gt;&lt;br /&gt;var m = $.monitor(mycall);//wrap the callback, m.monitor.status is 'unused'&lt;br /&gt;$.getJSON("my.json", m()); //calling m() prepares a callback and sets m.monitor.status to 'queued'&lt;br /&gt;$.getJSON("another.json", m());&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When the callback starts, m.monitor.status will be set to 'called' and when it completes it will become 'completed' or 'failed' if it raised an exception.&lt;br /&gt;&lt;br /&gt;In addition there are 4 counters for the history of each state: monitor.queued, monitor.called, monitor.completed and monitor.failed (in the example above m.monitor.queued and m.monitor.called will be 2 and the sum of m.monitor.completed and m.monitor.failed will be equal to 2). &lt;br /&gt;To check if all queued calls have completed use the m.isPending method (for this to work the result from calling m() should not be reused for consecutive callbacks!!!) and to reset the monitor use the m.clearMonitor method.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-2082501727570607034?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/2082501727570607034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=2082501727570607034&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/2082501727570607034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/2082501727570607034'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2011/06/monitoring-execution-of-asynchronous.html' title='Monitoring the execution of asynchronous JavaScript callbacks'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-6456015683952213786</id><published>2011-06-12T12:47:00.003+01:00</published><updated>2011-06-13T01:43:04.063+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='marathon'/><category scheme='http://www.blogger.com/atom/ns#' term='Daily Notes'/><category scheme='http://www.blogger.com/atom/ns#' term='running'/><title type='text'>2011 marathons</title><content type='html'>My plan is to run 4 full marathons in 2011. I already did &lt;a href="http://www.connemarathon.com"&gt;Connemara&lt;/a&gt; in April and have finally decided on the other 3:&lt;br /&gt;1. The &lt;a href="http://www.galwaycitymarathon.com"&gt;Galway City Marathon&lt;/a&gt; on 28th August&lt;br /&gt;2. The &lt;a href="http://dublinmarathon.ie"&gt;Dublin Marathon&lt;/a&gt; on 31st October&lt;br /&gt;3. The &lt;a href="http://runclon.ie"&gt;Clonakilty Waterfront Marathon&lt;/a&gt; on 10th December&lt;br /&gt;&lt;br /&gt;The big goal is to run in less than 3:30h by the end of the year. It shouldn't be too hard, but I I'll need to get lighter and faster, which means loosing some weight (at least 10kg, but maybe even more) and doing some serious running (minimum 60km per week) in the next 6 months .&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-6456015683952213786?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/6456015683952213786/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=6456015683952213786&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/6456015683952213786'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/6456015683952213786'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2011/06/2011-marathons.html' title='2011 marathons'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-203127490401648151</id><published>2011-06-09T23:44:00.016+01:00</published><updated>2011-06-10T02:46:23.338+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Daily Notes'/><category scheme='http://www.blogger.com/atom/ns#' term='Open Source'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>jquery.defaults.js</title><content type='html'>JavaScript doesn't let you define default values for arguments of functions, which, considering their heavy use throughout the language, can be quite a pain. &lt;br /&gt;In addition, a very common pattern is to use one of the arguments of the function as a collection of name:value options and to add an object with their default values inside the function's scope. However repeating the same code every time is not that nice and adding it to external functions requires even more work.&lt;br /&gt;&lt;br /&gt;My new jQuery extension &lt;a href="https://github.com/dragozov/bits.and.pieces.js/blob/master/src/jquery.defaults.js"&gt;jquery.defaults.js&lt;/a&gt; to the rescue!&lt;br /&gt;It adds two functions to jQuery, &lt;span style="font-weight:bold;"&gt;defaults&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;options&lt;/span&gt;. They both return a wrapper around their first argument, with &lt;span style="font-weight:bold;"&gt;defaults&lt;/span&gt; setting default values for the arguments' list and &lt;span style="font-weight:bold;"&gt;options&lt;/span&gt; implementing the pattern described above.&lt;br /&gt;&lt;br /&gt;Examples:&lt;br /&gt;&lt;pre class="brush: js"&gt;var f1 = $.defaults(f, [1, undefined, "3"]);//using an array of default values&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;or&lt;br /&gt;&lt;pre class="brush: js"&gt;&lt;br /&gt;var f1 = $.defaults(f, {"0":1, 2: "3"});//the same using an object with the argument positions as keys&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Calling &lt;code&gt;f1()&lt;/code&gt; will pass &lt;code&gt;(1, undefined, "3")&lt;/code&gt; while calling &lt;code&gt;f1("a", 2)&lt;/code&gt; will pass &lt;code&gt;("a", 2, "3")&lt;/code&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: js"&gt;var f2 = $.options(f, {key:"value", a:"a"});//the position of the options argument is 0 by default&lt;br /&gt;var f3 = $.options(f, 2, {key1: "value1"});//but it can be explicitly declared as the 2nd argument&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Calling &lt;code&gt;f2({a:"b"})&lt;/code&gt; will pass &lt;code&gt;({a:"b", key:"value"})&lt;/code&gt;, while calling &lt;code&gt;f3(1)&lt;/code&gt; will pass &lt;code&gt;(1, undefined,  {key1: "value1"})&lt;/code&gt;.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The functions resulting from applying the two can be mixed and chained together as much as necessary for even cooler effects. &lt;br /&gt;&lt;br /&gt;Grab the code from my GitHub project &lt;a href="https://github.com/dragozov/bits.and.pieces.js"&gt;bits.and.pieces.js&lt;/a&gt; and check the unit tests in the &lt;span style="font-weight:bold;"&gt;test&lt;/span&gt; folder for more examples. There is also a minified version if you feel like using it in production.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-203127490401648151?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/203127490401648151/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=203127490401648151&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/203127490401648151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/203127490401648151'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2011/06/jquerydefaultsjs.html' title='jquery.defaults.js'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-4989561626909809754</id><published>2011-06-08T18:31:00.008+01:00</published><updated>2011-06-09T02:27:56.530+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Daily Notes'/><category scheme='http://www.blogger.com/atom/ns#' term='RoadID'/><category scheme='http://www.blogger.com/atom/ns#' term='running'/><title type='text'>RoadID</title><content type='html'>My &lt;a href="http://www.roadid.com"&gt;RoadID&lt;/a&gt; arrived with the mail this morning and it's had its first 10 km run already.  &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;What is it?&lt;/span&gt;&lt;br /&gt;It is one of those very simple, but clever ideas that make perfect sense once you've heard about them. A friend called it jokingly "a dog-tag" and it kinda does the same job. &lt;br /&gt;RoadID is a small metal tag with engraved important contacts and information, medical or anything else, that you wear on your wrist or ankle. I got the ankle version as it also doubles as a place for your timing chip when running in a competition. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Why you need it?&lt;/span&gt;&lt;br /&gt;I run 40-60 km every week (mostly country roads and forests when I'm home, or unfamilliar streets and parks when I'm travelling). With this little metal plate I have the peace of mind that all my details and my family will be immediately available in case of an emergency. And it's a pretty cool dog-tag too ;)&lt;br /&gt;&lt;br /&gt;&lt;img style="width: 299px; height: 400px;" src="http://3.bp.blogspot.com/-e4jkoDp767k/Te_ZmJf9vWI/AAAAAAAAALk/DBgXi9QGby4/s400/RoadID.jpg" border="0" alt="The RoadID around my ankle" id="BLOGGER_PHOTO_ID_5615946509762542946" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-4989561626909809754?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/4989561626909809754/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=4989561626909809754&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/4989561626909809754'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/4989561626909809754'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2011/06/roadid.html' title='RoadID'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-e4jkoDp767k/Te_ZmJf9vWI/AAAAAAAAALk/DBgXi9QGby4/s72-c/RoadID.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-5425039673165501678</id><published>2011-06-08T00:11:00.005+01:00</published><updated>2011-06-08T01:32:26.266+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Writing'/><category scheme='http://www.blogger.com/atom/ns#' term='Daily Notes'/><title type='text'>The Last Lecture</title><content type='html'>What better topic for my first "daily note" than &lt;a href="http://www.youtube.com/watch?v=ji5_MqicxSo"&gt;"The Last Lecture"&lt;/a&gt; of Prof. Randy Pausch? I happened to watch it for 3rd or 4th time this Saturday and it's still one of the most inspiring talks you could find online. &lt;br /&gt;&lt;br /&gt;It's not so much about what he says. Most of it has been said before. &lt;br /&gt;But the fact that he is a dying man with nothing to gain, makes it all sound so real and honest that it hurts. &lt;br /&gt;&lt;br /&gt;And it's totally amazing how you finish watching a little sad, but also smiling and full of energy and love for life. And even if you cried (I guess most people do) you've also laughed a lot. A cocktail of feelings that will stick in your brain for days.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-5425039673165501678?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/5425039673165501678/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=5425039673165501678&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/5425039673165501678'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/5425039673165501678'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2011/06/last-lecture.html' title='The Last Lecture'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-5857079822141677399</id><published>2011-06-07T23:53:00.005+01:00</published><updated>2011-06-13T09:59:40.718+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Writing'/><category scheme='http://www.blogger.com/atom/ns#' term='Daily Notes'/><category scheme='http://www.blogger.com/atom/ns#' term='Blog'/><title type='text'>Daily Notes</title><content type='html'>As a small experiment in self-discipline I will try to write a blog post every day. &lt;br /&gt;Starting now...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-5857079822141677399?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/5857079822141677399/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=5857079822141677399&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/5857079822141677399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/5857079822141677399'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2011/06/daily-notes.html' title='Daily Notes'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-2689665895779730210</id><published>2011-04-08T16:30:00.003+01:00</published><updated>2011-04-08T16:49:43.822+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vibram'/><category scheme='http://www.blogger.com/atom/ns#' term='marathon'/><category scheme='http://www.blogger.com/atom/ns#' term='Connemara'/><category scheme='http://www.blogger.com/atom/ns#' term='running'/><title type='text'>Connemarathon</title><content type='html'>I'm running in the 2011 &lt;a href="http://www.connemarathon.com/"&gt;Connemara marathon&lt;/a&gt; this Sunday (10th April). &lt;br /&gt;It's supposed to be the most scenic but also the hardest in Ireland. And I'm also running in Vibram FiveFingers so should be fun :)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-tA79cI3kYl8/TZ8r5NUsh_I/AAAAAAAAALQ/Ev2RhdStzNo/s1600/bikila.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 239px;" src="http://2.bp.blogspot.com/-tA79cI3kYl8/TZ8r5NUsh_I/AAAAAAAAALQ/Ev2RhdStzNo/s320/bikila.jpg" border="0" alt="Vibram FiveFingers" id="BLOGGER_PHOTO_ID_5593237524046448626" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-2689665895779730210?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/2689665895779730210/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=2689665895779730210&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/2689665895779730210'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/2689665895779730210'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2011/04/connemarathon.html' title='Connemarathon'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-tA79cI3kYl8/TZ8r5NUsh_I/AAAAAAAAALQ/Ev2RhdStzNo/s72-c/bikila.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-3177589595426692659</id><published>2010-10-18T18:58:00.001+01:00</published><updated>2011-03-25T07:54:33.129Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='marathon'/><category scheme='http://www.blogger.com/atom/ns#' term='Dublin marathon'/><category scheme='http://www.blogger.com/atom/ns#' term='sports'/><category scheme='http://www.blogger.com/atom/ns#' term='nutrition'/><category scheme='http://www.blogger.com/atom/ns#' term='charity'/><category scheme='http://www.blogger.com/atom/ns#' term='health'/><category scheme='http://www.blogger.com/atom/ns#' term='UNICEF'/><category scheme='http://www.blogger.com/atom/ns#' term='fitness'/><category scheme='http://www.blogger.com/atom/ns#' term='donate'/><category scheme='http://www.blogger.com/atom/ns#' term='running'/><title type='text'>Running</title><content type='html'>I'll be running in the &lt;a href="http://dublinmarathon.ie"&gt;Dublin marathon&lt;/a&gt; next Monday, 25th October.&lt;br /&gt;It's my first marathon, I've been training since April and my main goal is to finish. &lt;br/&gt;&lt;br /&gt;However I'm also raising funds for &lt;a href="http://unicef.ie"&gt;UNICEF&lt;/a&gt;, hoping to help their efforts to improve health, education and safety for the children of the world.&lt;br /&gt;You can support my run by donating here (or at the  &lt;a href="http://unicef.ie"&gt;UNICEF&lt;/a&gt; website if you are reading this after the event):&lt;br/&gt;&lt;br /&gt;&lt;a href="http://www.unicef.ie/fundraising/dragozov20101025.aspx"&gt;Donate Now!&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;UPDATE: I finished in 3:42 hours and it didn't feel hard at all. Now I'm totally hooked and will be doing it a few times per year.  &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-kkdVqe1R6v8/TYxKB425N-I/AAAAAAAAAKs/egPQjy4PqJY/s1600/711638-1076-0018.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 212px; height: 320px;" src="http://3.bp.blogspot.com/-kkdVqe1R6v8/TYxKB425N-I/AAAAAAAAAKs/egPQjy4PqJY/s320/711638-1076-0018.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5587922633962895330" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-3177589595426692659?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/3177589595426692659/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=3177589595426692659&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/3177589595426692659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/3177589595426692659'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2010/05/running.html' title='Running'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-kkdVqe1R6v8/TYxKB425N-I/AAAAAAAAAKs/egPQjy4PqJY/s72-c/711638-1076-0018.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-590600020747749639</id><published>2010-08-01T22:09:00.007+01:00</published><updated>2010-08-02T16:21:44.347+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Treap'/><category scheme='http://www.blogger.com/atom/ns#' term='Open Source'/><category scheme='http://www.blogger.com/atom/ns#' term='Data structures'/><category scheme='http://www.blogger.com/atom/ns#' term='Erlang'/><category scheme='http://www.blogger.com/atom/ns#' term='Algorithms'/><title type='text'>Treaps in Erlang</title><content type='html'>&lt;p&gt;After a few months break I'm back to working on a project written mainly in &lt;a href="http://www.erlang.org"&gt;Erlang&lt;/a&gt; and I'll be posting the most interesting pieces online to a small open-source project at Google Code, &lt;a href="http://code.google.com/p/erlaz"&gt;ErlAZ&lt;/a&gt; - Erlang A to Z.&lt;br/&gt;The first module I'm uploading is an implementation of the &lt;a href="http://en.wikipedia.org/wiki/Treap"&gt;Treap&lt;/a&gt; data structure.&lt;/p&gt;&lt;p&gt;What is a Treap?&lt;br/&gt;It's a binary search tree where each node, in addition to its key and value, contains a number, called priority, assigned to it at insertion time.&lt;br/&gt;All nodes are sorted horizontally by their key (so that a greater key is always to the right of a smaller one) and vertically by their priority (so that all parents of any given node up to the root have a higher priority than the node).&lt;br/&gt;By choosing the priorities uniformly distributed across all keys (for example randomly), in the long run the treap will have the characteristic of a well-balanced tree, without having to re-balance it periodically.&lt;/p&gt;&lt;p&gt;I implemented my version as a drop-in replacement for the &lt;a href="http://www.erlang.org/doc/man/dict.html"&gt;dict&lt;/a&gt; module, with all the &lt;em&gt;dict&lt;/em&gt; functions having exactly the same signiture and behaviour, but working on treaps and performing according to the underlying tree structure vs. the hashtable used in &lt;em&gt;dict&lt;/em&gt;.&lt;br/&gt;There are also a few additional functions that use the ordered nature of the tree to allow querying and iterating over the keys in a sorted manner (which is pretty much the point of using a treap anyway), as well as functions for splitting the treap in two by a key (the first sub-treap contains all nodes with keys less or equal to the given key and the second - all nodes with greater keys) and for merging back a splitted treap.&lt;/p&gt;&lt;p&gt;The &lt;em&gt;treap&lt;/em&gt; module comes with well documented functions and an extensive EUnit test suit (in a separate module treap_test), which contains tests and examples for the usage of each function.&lt;br/&gt;As always all the code I release is covered by the &lt;a href="http://www.opensource.org/licenses/bsd-license.php"&gt;New BSD License&lt;/a&gt; unless stated otherwise.&lt;br/&gt;This means you are free to use it in any way you like, so help yourself:&lt;br/&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/erlaz/source/browse/#svn/trunk"&gt;ErlAZ trunk&lt;/a&gt; - The ErlAZ project's root with the Makefile for building the code and its documentation.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/erlaz/source/browse/trunk/src/treap.erl "&gt;treap.erl&lt;/a&gt; - The &lt;em&gt;treap&lt;/em&gt; module.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/erlaz/source/browse/trunk/src/treap.erl "&gt;treap_test.erl&lt;/a&gt; - The &lt;em&gt;treap_test&lt;/em&gt; module with all the EUnit tests. &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-590600020747749639?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/590600020747749639/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=590600020747749639&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/590600020747749639'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/590600020747749639'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2010/08/treaps-in-erlang.html' title='Treaps in Erlang'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-2613003095076747951</id><published>2010-04-05T17:39:00.004+01:00</published><updated>2010-04-22T10:58:32.997+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Earth Day'/><category scheme='http://www.blogger.com/atom/ns#' term='Green tech'/><category scheme='http://www.blogger.com/atom/ns#' term='Global Warming'/><category scheme='http://www.blogger.com/atom/ns#' term='Ecology'/><category scheme='http://www.blogger.com/atom/ns#' term='Solar'/><title type='text'>Earth Day Sunshine</title><content type='html'>Just in time for the Earth Day 2010 I got a solar water-heating system fitted in our house. I'll be writing more about what it does, how it works, post pictures and first impression in a week or two, but in the spirit of the day I'm writing a few sentences about my reasons.&lt;br /&gt;&lt;br /&gt;Do I believe it makes any difference? Would it save the world? Stop global warming? Of course not.&lt;br /&gt;&lt;br /&gt;Do I think that teaching my kids and their friends about sustainability and giving a personal example is important? &lt;br /&gt;That showing my neighbors how solar technology is not a curiosity anymore, but an affordable alternative, is the best way to get their attention?&lt;br /&gt;Do I feel good about supporting a business that's investing and creating jobs in a green-tech industry?&lt;br /&gt;You bet!&lt;br /&gt;&lt;br /&gt;So Happy Earth Day and maybe focus less on the today's problems and more on the future solutions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-2613003095076747951?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/2613003095076747951/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=2613003095076747951&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/2613003095076747951'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/2613003095076747951'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2010/04/earth-day-sunshine.html' title='Earth Day Sunshine'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-9016797724529717742</id><published>2010-02-17T01:41:00.016Z</published><updated>2010-02-17T03:24:40.569Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Wireframing'/><category scheme='http://www.blogger.com/atom/ns#' term='AppStore'/><category scheme='http://www.blogger.com/atom/ns#' term='App'/><category scheme='http://www.blogger.com/atom/ns#' term='Mockup'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='StencilsApp'/><category scheme='http://www.blogger.com/atom/ns#' term='Design'/><title type='text'>Happy First App To Me</title><content type='html'>My first iPhone project &lt;a href="http://www.stencilsapp.com"&gt;StencilsApp&lt;/a&gt; was approved by Apple today and just appeared in the AppStore here in Ireland.&lt;br /&gt;Contrary to the widespread rumors, the approval process was a breeze, the review team was extremely professional and it all took less than 14 days.&lt;br /&gt;Considering the fact that &lt;span style="font-weight:bold;font-style:italic;"&gt;StencilsApp&lt;/span&gt; is a complex and rather unique tool, rich in content and text (you see what I'm doing here), my respect for what Apple have built in the last 3 years just grew even more. &lt;br /&gt;I'll definitely be sticking with their platform and the AppStore for the foreseeable future.&lt;br /&gt;&lt;br /&gt;What is &lt;span style="font-weight:bold;font-style:italic;"&gt;StencilsApp&lt;/span&gt;?&lt;br /&gt;It's a native prototyping (or wire-framing, mock-up etc) tool for the iPhone and the iPod Touch. Probably the first of its kind.&lt;br /&gt;It lets you design user interfaces and software using the native components of the device and produces sketches as close to the real app as you can get without programing it.&lt;br /&gt;The results simulate the complete work-flow of an iPhone application through UI transitions and annotations triggered by the user's taps or gestures on the screen.&lt;br /&gt;&lt;br /&gt;It's easy to use and you don't even have to know anything about programming. My 9 year old daughter is sketching with it quite successfully.&lt;br /&gt;I'm hoping it would be useful both for non-programmers to visualize and communicate their ideas and for iPhone developers to prototype, test and receive approval for their projects.&lt;br /&gt;&lt;br /&gt;It has lots of cool features, like 2D drawing, a large free icon library, a set of templates, app samples, online sharing etc. &lt;br /&gt;Just check the video tutorials that I've put on the &lt;a href="http://www.stencilsapp.com"&gt;web site&lt;/a&gt;.&lt;br /&gt;And if you own an iPhone or an iPod Touch, why not just grab it from the AppStore, while it's hot ;)&lt;br /&gt;It's a free download (with some optional stuff purchasable from inside the app if you feel like supporting my work):&lt;br /&gt;&lt;a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=352620611&amp;mt=8"&gt;iTunes Link&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I'll be writing more about my experience and the technology behind &lt;span style="font-weight:bold;font-style:italic;"&gt;StencilsApp&lt;/span&gt; in the next few weeks and I'll probably open-source some of the code when I get time to clean it up.&lt;br /&gt;But at the moment all I care for is to get my first decent sleep in the last 7 months. &lt;br /&gt;Yes, that's how long it took, but hey I'm a married guy with two kids and a busy, full-time job.&lt;br /&gt;Plus, as I said, it's quite a complex and powerful tool ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-9016797724529717742?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/9016797724529717742/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=9016797724529717742&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/9016797724529717742'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/9016797724529717742'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2010/02/happy-first-app-to-me.html' title='Happy First App To Me'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-6223641726780811802</id><published>2009-12-27T15:18:00.000Z</published><updated>2009-12-27T15:18:54.888Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Erlang'/><category scheme='http://www.blogger.com/atom/ns#' term='Project Euler'/><title type='text'>Diving into Erlang with Project Euler, Part 1</title><content type='html'>&lt;h2&gt;Project who?&lt;/h2&gt;&lt;a href="http://projecteuler.net/"&gt;Project Euler&lt;/a&gt; is probably the largest (270 problems as of December 2009) and best collection of brainteasers specifically designed for programmers. Unlike other puzzles they are not only fun and challenging, but also help you discover and develop new patterns and programming techniques. I'm a big fan of similar computational mind-benders and use them both in job interviews to see how a candidate approaches a real problem and as a way to balance the boring work that's frequently necessary for even the most interesting projects.&lt;br /&gt;I've been solving 1-2 problems every day and after completing number 25 today I got a nice message:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;"Bravo, dragozov! Now that you have solved 25 problems you have achieved what 80.04% of members have failed to do and have advanced to level 1. Good luck as you continue."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So I thought I'd describe my experience, especially considering that I'm using &lt;a href="http://erlang.org/"&gt;Erlang&lt;/a&gt;, a language that I'm currently trying to master and which could use a little more sample code and demos online.&lt;br /&gt;&lt;h2&gt;Why Erlang?&lt;/h2&gt;I'm working on a small side project and one of the decisions I made was to focus on learning new things and exploring technologies and problems that I find interesting, but are not useful or relevant to my day job. So I'm developing everything as a combination of Erlang and Python.&lt;br /&gt;Of course I have more pragmatic reasons. Erlang's unique features make lots of sense for some parts of my app and the two languages complement each other quite well. I also wanted to experiment a little more with functional programming and I find the mental shift required to code in Erlang quite enjoyable. I guess the recent hype around the language played its role too.&lt;br /&gt;Anyway I've been studying Erlang and OTP (the open source platform behind it) and use any chance to apply my new skills, so Project Euler was too good of an opportunity to miss.&lt;br /&gt;&lt;h2&gt;The Idea&lt;/h2&gt;In this and the follow-up articles I'm showing how to use Erlang to solve computational problems. As I advance from the simpler questions to the harder ones, I'll try to also move from the language's basics to more advanced topics.&lt;br /&gt;However this is not an introduction and I won't be explaining the syntax. There are a few good online tutorials and an excellent &lt;a href="http://www.amazon.com/Programming-Erlang-Software-Concurrent-World/dp/193435600X"&gt;book&lt;/a&gt;, so you might want to check them first.&lt;br /&gt;On the other hand I'll point out Erlang specific features and techniques and discuss their usage. I also keep the solutions as self-contained as possible, so in some cases there might be code implementing functionality that is already available in the standard libraries or functions copied between the modules. &lt;br /&gt;I've tried to find the best solutions I could think of and optimize the code as much as possible, but I haven't searched the Internet or checked the forums, so there might be better/faster algorithms. There is rarely a single correct way of doing things in programming and this is not an exception. &lt;br /&gt;I'll keep all solution sources in a Google Code project called &lt;a href="http://code.google.com/p/eulerl/"&gt;Eulerl&lt;/a&gt;. The license is BSD, if you care, so you are free to use them for anything you like.&lt;br /&gt;&lt;h2&gt;Level 1 (first 25 problems)&lt;/h2&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=1" target="_blank"&gt;Problem 1&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p1.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;This one is really easy, it just sums two arithmetic progressions, for which the formula is like this:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;SumM = 1*M + 2*M + ...+ K*M = M*(1+2+...K)=M*(K*(K+1)/2)&lt;/span&gt;&lt;br /&gt;We add the sums of the multiples of 3 and 5 and subtract the sum of the multiples of 15 as they were added twice.&lt;br /&gt;Not much to be seen here, just 2 simple function declarations and the use of the &lt;span style="font-weight: bold;"&gt;div&lt;/span&gt; operator for integer division.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=2" target="_blank"&gt;Problem 2&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p2.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;Here we implement a function that iterates through the Fibonacci numbers and sums the even ones.&lt;br /&gt;Although it's still a very simple problem, things get a little more interesting.&lt;br /&gt;First we have an example of a tail-recursion, the most common (and efficient) way of implementing iterations in Erlang. I use the function's arguments, including an accumulator (a very common pattern for keeping track of the result) to keep the recursion's state between subsequent calls. At each step of the iteration the function receives the complete information and returns the whole result.&lt;br /&gt;The code also demonstrates some basic usage of pattern matching and guard expressions. Although they don't make a big difference here, they can make the code for an algorithm shorter and more readable (my personal opinion, of course).&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=3" target="_blank"&gt;Problem 3&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p3.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;To find the prime factors of a number N iterate from 2 to N/2 checking if N is divisible by the current number. At each iteration collect the factor if testing positive and replace the number tested with the result of the division or, if negative, increment the factor to be tested.&lt;br /&gt;Similarly to problem 3 I use tail-recursion and pattern matching to code the solution. Note the &lt;span style="font-weight: bold;"&gt;rem&lt;/span&gt; operator, which is Erlang's operator for modulo (the remainder of the division of one number by another).&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=4" target="_blank"&gt;Problem 4&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p4.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;Problem 4 is the first where the solution requires some more coding (at least the solution that I came up with). A palindrome is a number that reads the same both ways. We can generate all palindromes of length 2*N and 2*N - 1 from the numbers with N digits. For example 123321 and 12321 can both be generated from 123.&lt;br /&gt;So to solve the problem I iterate backwards starting with 999 and ending with 100, generate all 6 and 5 digit palindromes and return the first that is a product of two 3 digit numbers.&lt;br /&gt;On the Erlang side the most interesting is the use of functions as first-class elements of the language. You can see them passed as arguments to other functions and assigned to local variables.&lt;br /&gt;Also note the syntax for declaring anonymous (fun) functions and how they have access to the enclosing context (the arguments of the &lt;span style="font-weight: bold;"&gt;factor/3&lt;/span&gt; function for example). One of the quirks of an anonymous function in Erlang is that it can't call itself directly, so to implement recursion I pass the function as one of its own arguments (Funself is my naming convention, not a rule).&lt;br /&gt;The &lt;span style="font-weight: bold;"&gt;palindrom_iterator&lt;/span&gt; function is interesting for a few reasons.&lt;br /&gt;First it shows a common approach in functional programming. It defines some generic functionality and lets you change the behavior later by accepting a function as one of its arguments. In this case &lt;span style="font-weight: bold;"&gt;palindrom_iterator&lt;/span&gt; iterates through the palindromes and applies the function to each one. Then based on the result it either returns it or continues with the next palindrome.&lt;br /&gt;Second it demonstrates how pattern matching can simplify complex logic. In this case the function iterates through all palindromes bellow a given size (although its not strictly a requirement for the solution). For example if we start with length 6, then we'll iterate through lengths 5, 4, 3 and 2. As it uses numbers half the length to generate the palindromes, there are two cases when it reaches the lowest number of a given length. If it was generating even length numbers, we need to run the same iteration but for odd length palindromes, else we need to reduce the length of the "template" numbers and switch to even palindromes. This is all encoded in only 4 lines at the 2nd and 3rd patterns of the function's declaration.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=5" target="_blank"&gt;Problem 5&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p5.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;To find the smallest number that is divided by every number in a list we need to collect the prime factors of all numbers in the list, then multiply them raised by their maximum powers. For example if we have 6, 8 and 18, all prime factors are 2 and 3 (6 = 2*3, 8 = 2&lt;sup&gt;3&lt;/sup&gt; and 18 = 2*(3&lt;sup&gt;2&lt;/sup&gt;)) with maximum powers 3 and 2 respectively. So the solution would be (2&lt;sup&gt;3&lt;/sup&gt;)*(3&lt;sup&gt;2&lt;/sup&gt;)=72.&lt;br /&gt;There are a few new concepts introduced in the Erlang code:&lt;br /&gt;- The use of a look-up table (in the max_count functions) implemented using the &lt;a href="http://www.erlang.org/doc/man/ets.html"&gt;ets&lt;/a&gt; module, an efficient library for storage and access of data in a table form.&lt;br /&gt;- List comprehensions (in the solution/1 method), Erlang's syntax for "functional" creation of lists.&lt;br /&gt;- The syntax for splitting a list into a "head" element and a "tail" sublist or constructing a list in a similar fashion ([H|T] = List and List = [H|T]).&lt;br /&gt;- The &lt;a href="http://www.erlang.org/doc/man/lists.html"&gt;lists&lt;/a&gt; module, one of the most used standard libraries.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=6" target="_blank"&gt;Problem 6&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p6.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;The square of a sum can be written as:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;(a+b+c +c...+y+z)&lt;sup&gt;2&lt;/sup&gt; = a&lt;sup&gt;2&lt;/sup&gt;+b&lt;sup&gt;2&lt;/sup&gt;+c&lt;sup&gt;2&lt;/sup&gt;...+y&lt;sup&gt;2&lt;/sup&gt; + z&lt;sup&gt;2&lt;/sup&gt; + 2*a*b + 2*a*c...+2*a*y+2*a*z + 2*b*c + ...+ 2*b*z + ...2*y*z&lt;/span&gt;&lt;br /&gt;so:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;(a+b+c+...+y+z)&lt;sup&gt;2&lt;/sup&gt; - (a&lt;sup&gt;2&lt;/sup&gt; + b&lt;sup&gt;2&lt;/sup&gt; + c&lt;sup&gt;2&lt;/sup&gt; +...+ y&lt;sup&gt;2&lt;/sup&gt; + z&lt;sup&gt;2&lt;/sup&gt;) = 2*(a*(b+c+...+y+z) + b*(c+...+y+z) + ...+y*z)&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The actual implementation is another example of a tail-recursive function, where the state of the computation is kept in the function's arguments. &lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=7" target="_blank"&gt;Problem 7&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p7.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;To solve this I implement a simple check for primality where I keep a list of all prime numbers found until now and test new candidates against the list.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=8" target="_blank"&gt;Problem 8&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p8.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;Iterate through the digits, keeping a first-in-last-out list of the last N digits and check if their product is the maximum until now.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=9" target="_blank"&gt;Problem 9&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p9.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;The solution is an example of a nested iteration. We have 2 conditions:&lt;br /&gt;(1) &lt;span style="font-weight:bold;"&gt;A&lt;sup&gt;2&lt;/sup&gt; + B&lt;sup&gt;2&lt;/sup&gt; = C&lt;sup&gt;2&lt;/sup&gt; &lt;/span&gt;&lt;br /&gt;(2) &lt;span style="font-weight:bold;"&gt;A + B + C = N&lt;/span&gt;&lt;br /&gt;If we postulate that A is the smallest and C the biggest number, we can extract two additional constraints:&lt;br /&gt;(3) &lt;span style="font-weight:bold;"&gt;A &amp;lt; N/3&lt;/span&gt;&lt;br /&gt;(4) &lt;span style="font-weight:bold;"&gt;B &amp;lt; N/2 &lt;/span&gt;&lt;br /&gt;I run an iteration through all possible A, for each run another nested iteration through all possible B and check if the resulting triplet {A, B, C} meets all the conditions and constraints (1,2,3 and 4).&lt;br /&gt;The code also demonstrates the use of tuples to return and unpack multiples values as a result of a function.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=10" target="_blank"&gt;Problem 10&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p10.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;Similar to problem 7, solved with a simple primality check and a tail-recursive iteration until we've collected the sum of the first N primes.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=11" target="_blank"&gt;Problem 11&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p11.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;My solution is to generate all possible subsquares of a given size, calculate all the different products of each subsqare (4 horizontal, 4 vertical and 2 diagonals in this case) and find the maximum one.&lt;br /&gt;The code introduces the &lt;a href="http://www.erlang.org/doc/man/array.html"&gt;array&lt;/a&gt; module, providing functions for working with arrays in Erlang (0 based unlike most other data structures). It's also an example of extensive use of anonymous (lambda) functions to simplify the implementation of complex logic.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=12" target="_blank"&gt;Problem 12&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p12.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;The N-th triangular number is equal to the sum of a simple arithmetic progression:&lt;br /&gt;(1) &lt;span style="font-weight:bold;"&gt;Tn = n*(n+1)/2&lt;/span&gt;&lt;br /&gt;n and n-1 can be written as products of prime factors:&lt;br /&gt;(2) &lt;span style="font-weight:bold;"&gt;n = 2&lt;sup&gt;p2&lt;/sup&gt;*3&lt;sup&gt;p3&lt;/sup&gt;...*N&lt;sup&gt;pN&lt;/sup&gt;&lt;/span&gt;&lt;br /&gt;(3) &lt;span style="font-weight:bold;"&gt;n+1 = 2&lt;sup&gt;q2&lt;/sup&gt;*3&lt;sup&gt;q3&lt;/sup&gt;...*M&lt;sup&gt;pM&lt;/sup&gt;&lt;/span&gt;&lt;br /&gt;so Tn:&lt;br /&gt;(4) &lt;span style="font-weight:bold;"&gt;Tn = 2&lt;sup&gt;(p2 + q2 - 1)&lt;/sup&gt;*3&lt;sup&gt;(p3 + q3)&lt;/sup&gt;*...*K&lt;sup&gt;(pK+qK)&lt;/sup&gt;&lt;/span&gt;, K is the max of M and N and pi,qi &amp;gt;= 0&lt;br /&gt;If the prime factors of x are:&lt;br /&gt;(5) &lt;span style="font-weight:bold;"&gt;x = 2&lt;sup&gt;s2&lt;/sup&gt;*3&lt;sup&gt;s3&lt;/sup&gt;*...*L&lt;sup&gt;sL&lt;/sup&gt;&lt;/span&gt;&lt;br /&gt;then all possible divisors of x have the form:&lt;br /&gt;(6) &lt;span style="font-weight:bold;"&gt;D = 2&lt;sup&gt;t2&lt;/sup&gt;*3&lt;sup&gt;t3&lt;/sup&gt;*...*L&lt;sup&gt;tL&lt;/sup&gt;&lt;/span&gt;, where 0 &amp;lt;= ti &amp;lt;= si&lt;br /&gt;So the total number of unique divisors of x is:&lt;br /&gt;(7) &lt;span style="font-weight:bold;"&gt;Divisors(x) = (s2 + 1)*(s3+1)*...*(sL+1)&lt;/span&gt;, adding 1 for the case where ti = 0 (see 6 above)&lt;br /&gt;From 4 and 7:&lt;br /&gt;(8) &lt;span style="font-weight:bold;"&gt;Divisors(Tn) = (p2 + q2)*(p3+q3+1)*...*(pk+qK+1)&lt;/span&gt;&lt;br /&gt;First I implement a method that returns all the prime factors and their powers. Then I iterate through the triangular numbers and calculate expression 8 for each until I finds the first that meets the problem's condition. &lt;br /&gt;The code is another example of a recursive function, with the optimization of reusing (through the function's arguments) the calculated factors and their powers for each number in two consecutive calls, as the (n+1) in one triangular number is the n in the next.&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=13" target="_blank"&gt;Problem 13&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p13.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;Yet another example of a recursive function and the use of pattern matching to implement a solution. Just sum the digits from right to left, keeping the addition carry in the function's arguments and storing the resulting digits in an "accumulator" list.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=14" target="_blank"&gt;Problem 14&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p14.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;My solution is to iterate through all numbers bellow 1 Million and calculate their chain lengths, but using a look-up table to reuse the results in longer chains that contain previously computed shorter ones.&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=15" target="_blank"&gt;Problem 15&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p15.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;An N x N grid, contains (N+1)x(N+1) nodes. The number of paths from a node to the bottom-right corner is equal to the sum of the number of paths from its right and bottom neighbor nodes (if they exist). As some nodes have to be counted multiple times a look-up table is used (the &lt;a href="http://www.erlang.org/doc/man/ets.html"&gt;ets&lt;/a&gt; module to the rescue again).&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=16" target="_blank"&gt;Problem 16&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p16.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;I implement a function that takes a number as a list of its digits and returns a list of the digits of the number multiplied by 2. Then getting the digits of any power of 2 means, starting with 1 (2&lt;sup&gt;0&lt;/sup&gt;), repeatedly calling the function with the result of its previous call. Nothing much else to be seen here.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=17" target="_blank"&gt;Problem 17&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p17.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;This is an example of using Erlang's pattern matching syntax to implement a set of facts. The solution then uses these facts to iterate through all numbers and calculate the sum.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=18" target="_blank"&gt;Problem 18&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p18.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;To solve this problem I'm building a tree-like data structure with Erlang (it's not a real tree as each node except the root has two parents). &lt;br /&gt;Every node is represented by a tuple of four items. First the value of the node itself, then the tuples of the left and right children (or empty tuples if it's the bottom row) and then the "weight" of the node - the sum of the its value with the maximum weight of its children (as a matter of fact we only need to keep the weights). Building the tree from the bottom up gives the solution as the weight of its root.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=19" target="_blank"&gt;Problem 19&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p19.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;Another example of using pattern matching to encode the facts of the problem. Then iterate through all the 1-st days of the months of the 20th century's years and check if they were Sundays.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=20" target="_blank"&gt;Problem 20&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p20.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;Very similar to problem 16, but this time I implement a method that multiplies an arbitrary number to another and returns the result as a list of its digits.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=21" target="_blank"&gt;Problem 21&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p21.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;From the expression for an arbitrary divisor of a number (problem 12, formula 6) we can calculate the sum of all possible divisors:&lt;br /&gt;(1) &lt;span style="font-weight:bold;"&gt;DivisorsSum(x) = (p2&lt;sup&gt;0&lt;/sup&gt; +p2&lt;sup&gt;1&lt;/sup&gt; +...+p2&lt;sup&gt;k2&lt;/sup&gt;)*(p3&lt;sup&gt;0&lt;/sup&gt; +p3&lt;sup&gt;1&lt;/sup&gt; +...+p3&lt;sup&gt;k3&lt;/sup&gt;)*...(pN&lt;sup&gt;0&lt;/sup&gt; +pN&lt;sup&gt;1&lt;/sup&gt; +...+pN&lt;sup&gt;kN&lt;/sup&gt;)&lt;/span&gt;, where k2,k3, ...kN are the powers of each prime factor of x&lt;br /&gt;Using this we can iterate through all numbers and check if they are amicable and meet the other conditions of the problem, then sum them into the result.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=22" target="_blank"&gt;Problem 22&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p22.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;The solution is very straightforward on a technical level.&lt;br /&gt;However the code introduces some important libraries and concepts:&lt;br /&gt;- Working with files is usually done using the &lt;a href="http://www.erlang.org/doc/man/file.html"&gt;file&lt;/a&gt; module (and a few others usually prefixed with file_).&lt;br /&gt;- The binary syntax and the pattern matching are a very powerful combination frequently used as a replacement for the standard (and somewhat limited) representation of strings as lists of integers. They make it really easy to parse and construct streams of bytes, while keeping the code short and readable. A personal favorite of mine.&lt;br /&gt;I could have probably used standard libraries for a few of the functions, but chose to implement them myself:&lt;br /&gt;- The qsort function demonstrates a very cool (but not optimal) one-line implementation of the QSort algorithm using list comprehensions, guard expressions and recursion.&lt;br /&gt;- The a2i function demonstrates the syntax for retrieving the integer value of a character by prefixing it with a '$'.&lt;br /&gt;- The split function demonstrates the binary syntax as discussed above.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=23" target="_blank"&gt;Problem 23&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p23.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;The sum of all numbers that CAN'T be represented as a sum of 2 abundant ones in a given range is equal to the sum of all numbers in the range minus the sum of the numbers that CAN be represented like this:&lt;br /&gt;(1)&lt;span style="font-weight:bold;"&gt; SumNA(Max) = Sum(Max) - SumA(Max) = Max*(Max + 1) /2 - SumA(Max)&lt;/span&gt;&lt;br /&gt;If we know all abundant numbers in the range their sum can be calculated like this:&lt;br /&gt;(2) &lt;span style="font-weight:bold;"&gt;SumA(Max) = (2*A1 + 2*A2 + ...+ 2*AN + (A1 + A2) + (A1 + A3) + ...+ (A1+AN) + (A2+A3) +...)&lt;/span&gt;, where A1,...,AN are all abundant numbers bellow Max&lt;br /&gt;So my solution is to iterate through all numbers in the range, check if they are abundant and update their sum according to formula 2 above. Then the solution is computed using formula 1.&lt;br /&gt;The code is a combination of previous techniques, so nothing much to be explained.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=24" target="_blank"&gt;Problem 24&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p24.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;Basic combinatorics. The number of permutations of N unique items is N!. Using this I compute every digit of the I-th permutation noting that the digit at position P changes at every (P-1)! permutations.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="problem"&gt;&lt;div class="problem_h"&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=25" target="_blank"&gt;Problem 25&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_s"&gt;&lt;a href="http://code.google.com/p/eulerl/source/browse/trunk/p25.erl" target="_blank"&gt;Solution&lt;/a&gt;&lt;/div&gt;&lt;div class="problem_c"&gt;Another Fibonacci numbers problem solved with a tail recursive iteration until the problem's conditions are met.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;h2&gt;Conclusion of Level 1&lt;/h2&gt;This was the first post about my experience as I move through the problems. It's a demonstration of the sequential style of programming in Erlang. In the future I intend to focus on the parallel and distributed concepts of the language, which is what makes it so different. I hope that the problems will get a little harder and less repetitive so that I'll be also able to introduce and experiment a little more with the OTP modules.&lt;br /&gt;&lt;h2&gt;Links&lt;/h2&gt;&lt;a href="http://projecteuler.net/"&gt;http://projecteuler.net/&lt;/a&gt; - the home page of Project Euler.&lt;br /&gt;&lt;a href="http://erlang.org/"&gt;http://erlang.org/&lt;/a&gt; - the home page of the language.&lt;br /&gt;&lt;a href="http://code.google.com/p/eulerl/"&gt;http://code.google.com/p/eulerl/&lt;/a&gt; - my project at Google Code, where I keep all the sources.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-6223641726780811802?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/6223641726780811802/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=6223641726780811802&amp;isPopup=true' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/6223641726780811802'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/6223641726780811802'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2008/12/diving-into-erlang-with-project-euler.html' title='Diving into Erlang with Project Euler, Part 1'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-7135900426011615070</id><published>2009-12-13T22:34:00.004Z</published><updated>2009-12-14T00:05:26.203Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='Code'/><category scheme='http://www.blogger.com/atom/ns#' term='Algorithms'/><title type='text'>Random Subset of Combinations</title><content type='html'>I was solving an interesting problem today and thought I'd write about it and post some nice code.&lt;br /&gt;Imagine you have a list of fields with a discrete set of possible values each. Example:&lt;br /&gt;&lt;pre class="brush:xml;wrap-lines: false; gutter: false"&gt;&lt;br /&gt;&lt;person&gt;&lt;br /&gt; &lt;name&gt;one of [John, Paul, Marie, ….]&lt;/name&gt;&lt;br /&gt; &lt;surname&gt;one of [Turner, Conner, Lennon…]&lt;/surname&gt;&lt;br /&gt; &lt;date_of_birth&gt;a date between 01 January and 31 December&lt;/date_of_birth&gt;&lt;br /&gt; &lt;nationality&gt;one of [USA, Canada, Germany, France...]&lt;/nationality&gt;&lt;br /&gt;&lt;/person&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The number of possible combinations is equal to the multiplication of the number of possible values for each field and grows very fast.&lt;br /&gt;So now imagine that you want a way to randomly generate a small number of combinations, where there are no repetitions (like 100 random, unique people from the example above) and you want it done in an optimal way.&lt;br /&gt;My solution (I have the source in Python so don't freak out from my attempt at explaining):&lt;br /&gt;1. Map every combination to an integer in the range between 0 and the total number of combinations (so the first possible person has id of 0 and the last one has id of TOTAL - 1).&lt;br /&gt;2. Generating a random combination is equivalent to generating a random id between 0 and TOTAL - 1 and then building the corresponding combination. &lt;br /&gt;3. The mapping is done by representing the combinations as points in a multidimensional space using each field as a dimension. The index of the value of the field in the set of all possible value is the coordinate in this dimension.&lt;br /&gt;4. Lets say that we have N fields each with a list of possible values, L1, …, LN and sizes Size1, …, SizeN.&lt;br /&gt;The number of all combinations in a space is the multiplication of all the sizes:&lt;br /&gt;TOTAL = Size1*Size2…*SizeN&lt;br /&gt;5. If we remove the Nth field we are left with a space with a lower dimension and a total of:&lt;br /&gt;TotalN-1 = Size1*Size2*…SizeN-1&lt;br /&gt;We can call this the Subtotal of N or SubN. With some calculations it's clear that&lt;br /&gt;SubN = SizeN-1*SubN-1&lt;br /&gt;and we set Sub1 = 1&lt;br /&gt;6. Lets name the index of the value of the i-th field of a combination Xi. Then the id of a combination can be calculated like this:&lt;br /&gt;ID = XN*SubN + XN-1*SubN-1 + …+ X1 * Sub1&lt;br /&gt;7. If we have the ID we can calculate X1, …XN like this:&lt;br /&gt;XN = ID/SubN (/ is integer division, i.e we ignore the remainder)&lt;br /&gt;XN-1 = (ID % SubN)/SubN-1 (% is modulo i.e. the remainder of the division)&lt;br /&gt;…&lt;br /&gt;X1 = ((ID % SubN)%SubN-1)…%Sub2&lt;br /&gt;8. So this gives us a way to quickly generate a random combination, but still doesn't solve the initial problem of getting a whole subset of non-repeating, random combinations. &lt;br /&gt;This is equivalent to generating a list of random, non-repeating numbers in the range 0 - (TOTAL - 1).&lt;br /&gt;9. I wasn't sure if this can be done optimally, but after some reading (&lt;a href="http://www.techuser.net/randpermgen.html"&gt;Great article on k-permutations&lt;/a&gt;) it seemed that there is a very efficient algorithm. &lt;br /&gt;For a subset of size K from N numbers it is possible to do it in O(K) both for space and speed. After I implemented the algorithm I found out that Python has a method that can do this (random.sample) so I'm using it in my code, but my implementation is also there (shuffle_range) if you need to do it in a different language or would like to appreciate how short and beautiful it is ;-)&lt;br /&gt;10. The idea of the algorithm is to take all the numbers from 1 to N (bare with me, it gets optimized later) and shuffle them. Then get the first K numbers and throw the rest.&lt;br /&gt;The shuffling is done by putting the numbers in a big array, iterating through them and for each position generating a random number between 0 and n-1 then swapping the value at the current position with the value at the random position.&lt;br /&gt;The optimization that I mention allows this to be reduced from an O(N) to an O(K) algorithm both for space and speed.&lt;br /&gt;Instead of creating an array of size N we use a hash table with the rule that if the table contains a value for a position this is the value at that position, else the value is equal to the index of the position. Then we only iterate from 0 to K-1 and generate the result using the above rule.&lt;br /&gt;&lt;br /&gt;And after this long explanation, which will either put you to sleep or make you have nightmares in the next few nights, here is the source code, which I hope will clarify things a bit:&lt;br /&gt;&lt;pre class="brush:python;wrap-lines: false; gutter: false"&gt;&lt;br /&gt;"""Generation of a random subset of all possible combinations for a list&lt;br /&gt;of list of options.&lt;br /&gt;&lt;br /&gt;This code is released in the public domain, meaning it is free for any&lt;br /&gt;use.&lt;br /&gt;2009 Plamen Dragozov&lt;br /&gt;"""&lt;br /&gt;import random&lt;br /&gt;&lt;br /&gt;class Combinator(object):&lt;br /&gt;    """Manages a list of lists and generates combinations of the elements of these lists.&lt;br /&gt;    """&lt;br /&gt;    def __init__(self, lists):&lt;br /&gt;        """Initialize with the given lists and pre-calculate the subtotals.&lt;br /&gt;&lt;br /&gt;        Subtotals are the number of combinations of all lists without the last one,&lt;br /&gt;        so subtotal3 is equal to Size2*Size1.&lt;br /&gt;        Total is the number of all possible combinations.&lt;br /&gt;        """&lt;br /&gt;        subtotals = []    &lt;br /&gt;        total = 1&lt;br /&gt;        for l in lists:&lt;br /&gt;            subtotals.append(total)&lt;br /&gt;            total = total * len(l)&lt;br /&gt;        &lt;br /&gt;        self.total = total&lt;br /&gt;        self.lists = lists&lt;br /&gt;        self.subtotals = subtotals&lt;br /&gt;        &lt;br /&gt;    def combination(self, n):&lt;br /&gt;        """ A combination is a list where the element at position 'i' is one of the elements in list 'i'.&lt;br /&gt;&lt;br /&gt;        All possible combinations (with a count of Total) can be mapped to the first Total integers.&lt;br /&gt;        This method returns the n-th combination, calculating all element indices in the lists.&lt;br /&gt;        """&lt;br /&gt;        result = []&lt;br /&gt;        for i in range(len(self.lists) - 1, -1, -1):#iterate backwards, from the last to the 1st&lt;br /&gt;            subtotal = self.subtotals[i]&lt;br /&gt;            pos = n / subtotal&lt;br /&gt;            result.append(self.lists[i][pos])&lt;br /&gt;            n = n % subtotal&lt;br /&gt;        result.reverse()&lt;br /&gt;        return result&lt;br /&gt;&lt;br /&gt;    def random(self, count):&lt;br /&gt;        """Generate 'count' random combinations without repetition.&lt;br /&gt;        """&lt;br /&gt;        ids = random.sample(xrange(self.total), min(count, self.total))&lt;br /&gt;        return [self.combination(i) for i in ids]&lt;br /&gt;    &lt;br /&gt;def shuffle_range(n, k = None):&lt;br /&gt;    """Creates a random sub-permutation of size k for the first n integers.&lt;br /&gt;&lt;br /&gt;    This is pretty much equivalent to random.sample.&lt;br /&gt;    """&lt;br /&gt;    if (not k) or (k &gt; n):&lt;br /&gt;        k = n&lt;br /&gt;    hashT = {}&lt;br /&gt;    for i in xrange(k):&lt;br /&gt;        j = random.randint(0, n - 1)&lt;br /&gt;        #swap whats at i with what's at j and vice versa&lt;br /&gt;        hashT[i], hashT[j] = hashT.get(j, j), hashT.get(i, i)&lt;br /&gt;&lt;br /&gt;    return [hashT.get(i, i) for i in xrange(k)]&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-7135900426011615070?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/7135900426011615070/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=7135900426011615070&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/7135900426011615070'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/7135900426011615070'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2009/12/random-subset-of-combinations.html' title='Random Subset of Combinations'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4341013927520812102.post-592864979009982429</id><published>2009-10-25T13:36:00.009Z</published><updated>2009-10-25T17:50:25.727Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='Source'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><category scheme='http://www.blogger.com/atom/ns#' term='Code'/><category scheme='http://www.blogger.com/atom/ns#' term='ObjectiveC'/><title type='text'>Hit testing for arbitrary paths on the iPhone</title><content type='html'>&lt;p&gt;I'm doing something cool for the iPhone. Can't tell yet, but I'll be posting hacks and interesting code as I go.&lt;br /&gt;For the first one all credit goes to Graham Cox of &lt;a href="http://apptree.net/drawkitmain.htm"&gt;DrawKit&lt;/a&gt; (an awesome open-source project). I just ported his idea to the iPhone and tweaked it to match my problem.&lt;/p&gt;&lt;p&gt;I've been working on an algorithm for detecting a finger touch over a random, complex path. It was quickly clear that it's not a trivial problem and my requirement for the path to have a stroke (border) of significant width made it even harder. &lt;br /&gt;So I was searching and reading forums and documentation and even had some ideas and rudimentary code when suddenly I found this &lt;a href="http://osdir.com/ml/cocoa-dev/2009-06/msg01882.html"&gt;post&lt;/a&gt;. Such a beautiful idea that I had to try it. And once I got the code to work I felt I should share it with everyone.&lt;/p&gt;&lt;p&gt;I represent the finger as a rectangle around the touch point, so my problem is reduced to checking for intersection between a rectangle and a path. Here is the algorithm:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Filter all trivial cases to avoid unnecessary calculations.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Get the intersection between the bounding box of the path and the rectangle (of the finger).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If that's a non-zero rectangle, smaller than the bounding box (else the path and the rect intersect), draw the intersection into a 1x1 off-screen, alpha-only, bitmap buffer&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If the resulting pixel is non-zero the two intersect, i.e. the intersection contains at least one non-transparent pixel from the path.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Integrate into your code, test and feel totally awesome ;)&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;And bellow is the code (the implementation part only, assuming the class name is GraphicsUtil!):&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:cpp;wrap-lines: false; gutter: false"&gt;&lt;br /&gt;&lt;br /&gt;//check if the rect contains any non transparent part of the path&lt;br /&gt;//as it is drawn on the screen&lt;br /&gt;+ (BOOL)rect: (CGRect)rect &lt;br /&gt;intersectsPath: (CGPathRef)path &lt;br /&gt; strokeWidth: (CGFloat)strokeWidth&lt;br /&gt; strokeColor: (UIColor *)strokeColor&lt;br /&gt;       fillColor: (UIColor *)fillColor;&lt;br /&gt;{    &lt;br /&gt;    CGRect bbox = [GraphicsUtil boundingBoxForPath: path&lt;br /&gt;                                   withStrokeWidth: strokeWidth&lt;br /&gt;                                       strokeColor: strokeColor&lt;br /&gt;                                         fillColor: fillColor];&lt;br /&gt;    CGRect intersection = CGRectIntersection(rect, bbox);&lt;br /&gt;    BOOL result = NO;&lt;br /&gt;    &lt;br /&gt;    if (intersection.size.width &amp;gt; 0.0f &amp;&amp; intersection.size.height &amp;gt; 0.0f)&lt;br /&gt;    {&lt;br /&gt;        // if the rect contains the path then we are sorted&lt;br /&gt;        if( CGRectEqualToRect(intersection, bbox))&lt;br /&gt;        {&lt;br /&gt;            return YES;&lt;br /&gt;        }&lt;br /&gt;        else&lt;br /&gt;        {&lt;br /&gt;            //Take the intersection rect and find out if it contains at least one&lt;br /&gt;            // non 0 pixel. &lt;br /&gt;            //Scale the pixels from the intersection into an 1x1 &lt;br /&gt;            //image context&lt;br /&gt;            &lt;br /&gt;            //cache these so they are created once and then cleared&lt;br /&gt;            static CGContextRef bitmap1x1 = NULL;&lt;br /&gt;            static uint8_t pixels[8]; //some unused padding&lt;br /&gt;            static CGRect rect1x1 = {{0, 0},{1, 1}};&lt;br /&gt;            &lt;br /&gt;            if( bitmap1x1 == NULL )&lt;br /&gt;            {&lt;br /&gt;                bitmap1x1 = CGBitmapContextCreate(pixels, 1, 1, 8, 1, NULL, &lt;br /&gt;                                                  kCGImageAlphaOnly);&lt;br /&gt;                CGContextSetInterpolationQuality(bitmap1x1, kCGInterpolationNone);&lt;br /&gt;                CGContextSetShouldAntialias(bitmap1x1, NO);&lt;br /&gt;                CGContextSetShouldSmoothFonts(bitmap1x1, NO);&lt;br /&gt;            }&lt;br /&gt;            &lt;br /&gt;            pixels[0] = 0;&lt;br /&gt;            &lt;br /&gt;            [self drawPath: path &lt;br /&gt;                    fromRect: intersection &lt;br /&gt;                        inRect: rect1x1 &lt;br /&gt;                   inContext: bitmap1x1 &lt;br /&gt;                strokeWidth: strokeWidth &lt;br /&gt;                strokeColor: strokeColor &lt;br /&gt;                      fillColor: fillColor];&lt;br /&gt;            &lt;br /&gt;            result = ( pixels[0] != 0 );&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    return result;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//Draws a rectangular part of the path into another rectangular&lt;br /&gt;//region scaling it to fit.&lt;br /&gt;+ (void)drawPath: (CGPathRef)path&lt;br /&gt;            fromRect:(CGRect)srcRect&lt;br /&gt;                inRect: (CGRect)destRect &lt;br /&gt;           inContext: (CGContextRef)context&lt;br /&gt;        strokeWidth: (CGFloat)strokeWidth&lt;br /&gt;         strokeColor: (UIColor *)strokeColor&lt;br /&gt;              fillColor: (UIColor *)fillColor;&lt;br /&gt;{ &lt;br /&gt; NSAssert( destRect.size.width &amp;gt; 0.0 &amp;&amp; destRect.size.height &amp;gt; 0.0, @"destination rect has zero size");&lt;br /&gt; CGRect bbox = [GraphicsUtil boundingBoxForPath: path &lt;br /&gt;                                   withStrokeWidth: strokeWidth &lt;br /&gt;                                       strokeColor: strokeColor &lt;br /&gt;                                         fillColor: fillColor];&lt;br /&gt; if (CGRectEqualToRect(srcRect, CGRectZero))&lt;br /&gt; {&lt;br /&gt;  srcRect = bbox;&lt;br /&gt;     }&lt;br /&gt; else&lt;br /&gt;     {&lt;br /&gt;  srcRect = CGRectIntersection(srcRect, bbox);&lt;br /&gt;     }&lt;br /&gt;    &lt;br /&gt; if( CGRectEqualToRect(srcRect, CGRectZero))&lt;br /&gt;     {&lt;br /&gt;  return;&lt;br /&gt;     }&lt;br /&gt;    &lt;br /&gt; CGContextSaveGState(context);&lt;br /&gt;     CGContextClipToRect(context, destRect);&lt;br /&gt;    &lt;br /&gt; CGContextConcatCTM(context, [GraphicsUtil mapFrom: srcRect to: destRect]);&lt;br /&gt;     CGContextAddPath(context, path); &lt;br /&gt;    &lt;br /&gt; CGContextSetLineWidth(context, strokeWidth);&lt;br /&gt;    &lt;br /&gt; CGPathDrawingMode mode;&lt;br /&gt;     if(strokeColor)&lt;br /&gt;     {&lt;br /&gt;  CGContextSetStrokeColorWithColor(context, strokeColor.CGColor);&lt;br /&gt;         mode= kCGPathStroke;&lt;br /&gt;     }&lt;br /&gt;    &lt;br /&gt; if(fillColor)&lt;br /&gt;     {&lt;br /&gt;  CGContextSetFillColorWithColor(context, fillColor.CGColor);&lt;br /&gt;         if(strokeColor)&lt;br /&gt;         {&lt;br /&gt;   mode = kCGPathFillStroke;&lt;br /&gt;         }&lt;br /&gt;         else &lt;br /&gt;         {&lt;br /&gt;   mode = kCGPathFill;&lt;br /&gt;         }&lt;br /&gt; }&lt;br /&gt;    &lt;br /&gt; CGContextDrawPath(context, mode);    &lt;br /&gt; CGContextRestoreGState(context);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//The strokes on the iPhone are drawn so that half of the stroke is on &lt;br /&gt;//one side of the path edge and half is on the other&lt;br /&gt;//So the actual bounding box is bigger than the one returned by the API&lt;br /&gt;//Or I may be smoking something and there could be an official//better &lt;br /&gt;//way to calcualate this. &lt;br /&gt;//Worked for me!!!&lt;br /&gt;+ (CGRect)boundingBoxForPath: (CGPathRef)path &lt;br /&gt;             withStrokeWidth: (CGFloat)strokeWidth&lt;br /&gt;                 strokeColor: (UIColor *)strokeColor &lt;br /&gt;                   fillColor: (UIColor *)fillColor&lt;br /&gt;{&lt;br /&gt;    BOOL noStroke = (strokeColor == nil || &lt;br /&gt;                     strokeWidth &amp;lt;= 0 || &lt;br /&gt;                     [strokeColor isEqual:[UIColor clearColor]]);&lt;br /&gt;    if((fillColor == nil || [fillColor isEqual:[UIColor clearColor]]) &amp;&amp;&lt;br /&gt;       noStroke)&lt;br /&gt;    {&lt;br /&gt;        return CGRectZero;&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;        CGRect bbox = CGPathGetBoundingBox(path);&lt;br /&gt;        if(!noStroke)&lt;br /&gt;        {&lt;br /&gt;            CGFloat border = ceil(strokeWidth/2.0f);&lt;br /&gt;            bbox = CGRectMake(bbox.origin.x - border, &lt;br /&gt;                              bbox.origin.y - border, &lt;br /&gt;                              bbox.size.width + 2*border, &lt;br /&gt;                              bbox.size.height + 2*border);&lt;br /&gt;        }&lt;br /&gt;        return bbox;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//Create an affine transform that transitions the source rectangle&lt;br /&gt;//into the destination one.&lt;br /&gt;+ (CGAffineTransform) mapFrom:(CGRect)src to:(CGRect)dst&lt;br /&gt;{&lt;br /&gt; CGFloat a = (dst.size.width/src.size.width);&lt;br /&gt; CGFloat b = 0.0;&lt;br /&gt; CGFloat tX = dst.origin.x - a*src.origin.x;&lt;br /&gt; CGFloat c = 0.0;&lt;br /&gt; CGFloat d = (dst.size.height/src.size.height);&lt;br /&gt; CGFloat tY = dst.origin.y - d*src.origin.y;&lt;br /&gt; return CGAffineTransformMake(a, b, c, d, tX, tY);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4341013927520812102-592864979009982429?l=www.dragozov.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.dragozov.com/feeds/592864979009982429/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4341013927520812102&amp;postID=592864979009982429&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/592864979009982429'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4341013927520812102/posts/default/592864979009982429'/><link rel='alternate' type='text/html' href='http://www.dragozov.com/2009/10/hit-testing-for-arbitrary-paths-on.html' title='Hit testing for arbitrary paths on the iPhone'/><author><name>Plamen Dragozov</name><uri>http://www.blogger.com/profile/01916912704086561904</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
