<?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-6679696301566560047</id><updated>2012-02-10T14:46:53.546-08:00</updated><category term='C++'/><category term='computational complexity'/><category term='education'/><category term='Vim'/><category term='math'/><category term='refactoring'/><category term='C'/><category term='programming'/><category term='book review'/><category term='OOP'/><category term='TopCoder'/><category term='video lectures'/><category term='code'/><category term='testing'/><category term='algorithms'/><category term='misc'/><title type='text'>Computer Science and Programming Haven</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://cs-haven.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://cs-haven.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>buda</name><uri>http://www.blogger.com/profile/04145572779602673421</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>13</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6679696301566560047.post-6994097707613326444</id><published>2012-02-07T11:20:00.000-08:00</published><updated>2012-02-08T00:56:58.320-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='algorithms'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='math'/><title type='text'>Efficiently computing the order of an element in a multiplicative group</title><content type='html'>&lt;p&gt;A few weeks ago, I stumbled upon an algorithmic problem that I was able to reduce to finding the order of a specific member of the multiplicative group modulo &lt;code&gt;N&lt;/code&gt;. In this post I'll talk about three different ways of doing that, from the naive way, the fairly obvious one and finally to the less obvious way which is also the fastest of the tree. I'm writing about this even though I'm not a mathematician because I've been unable to find the proof for the fastest algorithm by searching online, even though it's quite elementary. I'll write about the original problem itself in a separate post because it is interesting in its own right. You can find the code that I used to benchmark these algorithms &lt;a href="http://dl.dropbox.com/u/5412078/blog/group_order.cpp"&gt;here&lt;/a&gt;, and read the whole story in the rest of this (long) post, if you're interested.&lt;/p&gt;&lt;p&gt;So, the problem we're addressing is the following: given numbers &lt;code&gt;K&lt;/code&gt; and &lt;code&gt;N&lt;/code&gt;, compute the order of &lt;code&gt;K&lt;/code&gt; in the multiplicative group modulo &lt;code&gt;N&lt;/code&gt;, i.e. the smallest positive integer &lt;code&gt;e&lt;/code&gt; such that &lt;code&gt;K^e = 1 (mod N)&lt;/code&gt;. This is supposed to work quickly, say in few hundred milliseconds, for &lt;code&gt;N&lt;/code&gt; as big as one billion, i.e. 10^9. It's often instructive to think about these boundaries when looking for an algorithm because we want the simplest algorithm that will be fast enough. With &lt;code&gt;N&lt;/code&gt; in the billions, we're usually looking for something that's &lt;code&gt;O(sqrt(N))&lt;/code&gt;, possibly with a logarithmic factor. This restirction immediately eliminates the naive algorithm, which would just repeatedly multiply by &lt;code&gt;K&lt;/code&gt; in the group until the order was found, and is therefore &lt;code&gt;O(N)&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;To start off, it's instructive to think about some meaningful restrictions on &lt;code&gt;K&lt;/code&gt;. Obviously, &lt;code&gt;K&lt;/code&gt; must itself be a member of this group to have an order in it, and that means it has to be relatively prime with &lt;code&gt;N&lt;/code&gt; (and obviously smaller than &lt;code&gt;N&lt;/code&gt; as well). Furthermore, all the members of this group (call it &lt;code&gt;G_N&lt;/code&gt;) have this property and there are &lt;code&gt;phi(N)&lt;/code&gt; of them, where &lt;code&gt;phi&lt;/code&gt; is &lt;a href="http://en.wikipedia.org/wiki/Euler's_totient_function"&gt;Euler's totient function&lt;/a&gt;. Not to stray too much off topic, I'll just say that &lt;code&gt;phi(N)&lt;/code&gt; can easily be computed in &lt;code&gt;O(sqrt(N))&lt;/code&gt; time by decomposing &lt;code&gt;N&lt;/code&gt; into prime factors, so from now on we can assume that we know &lt;code&gt;n = phi(N)&lt;/code&gt;, the cardinality of our group &lt;code&gt;G_N&lt;/code&gt; (and we're still on target in terms of complexity). Here is some code that computes &lt;code&gt;n&lt;/code&gt;.&lt;/p&gt;&lt;pre name="code" class="cpp"&gt;&lt;br /&gt;int mod_group_order(int N) {&lt;br /&gt;    int d = 2;&lt;br /&gt;    int n = 1; // this will be the order of the group&lt;br /&gt;    while (d &amp;lt;= N/d) {&lt;br /&gt;        if (N%d == 0) { // d is a prime p&lt;br /&gt;            int num = 1; // accumulate p^k&lt;br /&gt;            do {&lt;br /&gt;                N /= d;&lt;br /&gt;                num *= d;&lt;br /&gt;            } while (N%d == 0);&lt;br /&gt;            n *= (num - num/d); // totient(p^k) = p^k-p^(k-1)&lt;br /&gt;        }&lt;br /&gt;        ++d;&lt;br /&gt;    }&lt;br /&gt;    if (N &amp;gt; 1) { // this is a prime, totient(p) = p - 1&lt;br /&gt;        n *= N - 1;&lt;br /&gt;    }&lt;br /&gt;    return n;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Having &lt;code&gt;n&lt;/code&gt;, we can now use &lt;a href="http://en.wikipedia.org/wiki/Lagrange's_theorem_(group_theory)"&gt;Lagrange's theorem&lt;/a&gt; to get a much faster algorithm for computing the order of an element than the naive algorithm mentioned at the beginning. Lagrange's theorem states that the cardinality of any subgroup of a finite group (such as our &lt;code&gt;G_N&lt;/code&gt;) must divide the cardinality of the group. Now, the order of an element &lt;code&gt;K&lt;/code&gt; is actually the cardinality of a &lt;a href="http://en.wikipedia.org/wiki/Cyclic_group"&gt;cyclic group&lt;/a&gt; generated by &lt;code&gt;K&lt;/code&gt; which is obviously a subgroup of &lt;code&gt;G_N&lt;/code&gt;. Therfore, the order of &lt;code&gt;K&lt;/code&gt; must be a divisor of &lt;code&gt;n&lt;/code&gt;. Since &lt;code&gt;n = phi(N)&lt;/code&gt; is &lt;code&gt;O(N)&lt;/code&gt; and we can find all the divisors of &lt;code&gt;n&lt;/code&gt; in &lt;code&gt;O(sqrt(n))&lt;/code&gt; by trial division, we have an algorithm that might hit our target. Also note that any multiple of the order of an element also takes that element to one, i.e. &lt;code&gt;K^n&lt;/code&gt; will always be &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;&lt;pre name="code" class="cpp"&gt;&lt;br /&gt;int order_divisors(int N, int K, int n) {&lt;br /&gt;    int up_order = n; // this works for sure&lt;br /&gt;    for (int d=2; d&amp;lt;=n/d; ++d) {&lt;br /&gt;        if (n%d == 0) {&lt;br /&gt;            if (fastexp_mod(K, d, N) == 1) {&lt;br /&gt;                return d; // found it!&lt;br /&gt;            }&lt;br /&gt;            if (d*d&amp;lt;n &amp;&amp; fastexp_mod(K, n/d, N)==1) {&lt;br /&gt;                // can't return here&lt;br /&gt;                up_order = n/d;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    return up_order;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The order of &lt;code&gt;K&lt;/code&gt; can either be less than or equal to &lt;code&gt;sqrt(n)&lt;/code&gt;, or it can be greater. In the former case, we can just return the smallest exponent that takes &lt;code&gt;K&lt;/code&gt; to one (line 6), but in the latter we can't yet be sure that there are no smaller exponents that will do the same thing so we must go on (line 9). The &lt;code&gt;fastexp_mod&lt;/code&gt; function raises its first argument to the second argument power modulo the third argument in logarithmic time. Therefore, the complexity of this algorithm is &lt;code&gt;O(sqrt(n)*log(n))&lt;/code&gt;. More precisely, this algorithm is &lt;code&gt;O(sqrt(n) + d(n)*log(n))&lt;/code&gt;, where &lt;code&gt;d(n)&lt;/code&gt; is the number of divisors of &lt;code&gt;n&lt;/code&gt;. Obviously, when the order of an element is very small, this algorithm will be very fast but when it is larger than &lt;code&gt;sqrt(n)&lt;/code&gt; it will actually be &lt;code&gt;Theta(sqrt(n) + d(n)*log(n))&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;The third algorithm to consider is based on the prime decomposition of &lt;code&gt;n&lt;/code&gt;, i.e. the order of the group. Assume that &lt;code&gt;n = p_0^q_0 * p_1^q_1 * ... * p_m^q_m&lt;/code&gt; is the prime decomposition of &lt;code&gt;n&lt;/code&gt;. Then the order of &lt;code&gt;K&lt;/code&gt; is the product of &lt;code&gt;p_i^(q_i - f(K, p_i, n))&lt;/code&gt; for all &lt;code&gt;i&lt;/code&gt;, where &lt;code&gt;f(K, p_i, n)&lt;/code&gt; is the largest exponent &lt;code&gt;e_i&lt;/code&gt; no greater than &lt;code&gt;q_i&lt;/code&gt; such that &lt;code&gt;K^(n/(p_i^e_i)) = 1 (mod N)&lt;/code&gt;. We will prove this is true in the remainder of this post and then see how this algorithm stacks up against the divisor-based one in terms of efficiency. Before that, here is the code that implements this algorithm (see the &lt;a href="http://dl.dropbox.com/u/5412078/blog/group_order.cpp"&gt;whole program&lt;/a&gt; for comments).&lt;/p&gt;&lt;pre name="code" class="cpp"&gt;&lt;br /&gt;int f(int p, int lim, int num, int n, int K, int N) { &lt;br /&gt;    while (lim &amp;gt; 0) {&lt;br /&gt;        if (fastexp_mod(K, n/num, N) == 1) {&lt;br /&gt;            return lim;&lt;br /&gt;        }&lt;br /&gt;        --lim;&lt;br /&gt;        num /= p;&lt;br /&gt;    }&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int order_primes_iter(int N, int K, int n) {&lt;br /&gt;    int sol = 1;&lt;br /&gt;    int t = n;&lt;br /&gt;    int d = 2;&lt;br /&gt;    while (d &amp;lt;= t/d) {&lt;br /&gt;        if (t%d == 0) {&lt;br /&gt;            int cnt = 0;&lt;br /&gt;            int num = 1;&lt;br /&gt;            do {&lt;br /&gt;                num *= d;&lt;br /&gt;                t /= d;&lt;br /&gt;                ++cnt;&lt;br /&gt;            } while (t%d == 0);&lt;br /&gt;            sol *= fastexp(d, cnt-f(d, cnt, num, n, K, N));&lt;br /&gt;        }&lt;br /&gt;        ++d;&lt;br /&gt;    }&lt;br /&gt;    if (t &amp;gt; 1) {&lt;br /&gt;        sol *= fastexp(t, 1 - f(t, 1, t, n, K, N));&lt;br /&gt;    }&lt;br /&gt;    return sol;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;So, after having introduced &lt;code&gt;e_i&lt;/code&gt; as the value returned by the function &lt;code&gt;f&lt;/code&gt;, we can rewrite the formula for the order of &lt;code&gt;K&lt;/code&gt; as the product of &lt;code&gt;p_i^(q_i - e_i)&lt;/code&gt; for all &lt;code&gt;i&lt;/code&gt;, and this is actually &lt;code&gt;n&lt;/code&gt; divided by the product of &lt;code&gt;p_i^e_i&lt;/code&gt;. We need to prove two things: that this number actually takes &lt;code&gt;K&lt;/code&gt; to one in te group and that there is no smaller number that does.&lt;/p&gt;&lt;p&gt;Theorem: If &lt;code&gt;K^(n/a) = 1 (mod N)&lt;/code&gt; and &lt;code&gt;K^(n/b) = 1 (mod N)&lt;/code&gt; and &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; are relatively prime, then &lt;code&gt;K^(n/ab) = 1 (mod N)&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;This theorem would allow us to compose what we know about the individual &lt;code&gt;e_i&lt;/code&gt; numbers into the formula we're trying to prove. Let &lt;code&gt;u = K^(n/ab)&lt;/code&gt;. Then both &lt;code&gt;u^a = 1 (mod N)&lt;/code&gt; and &lt;code&gt;u^b = 1 (mod N)&lt;/code&gt; by assumption. This can only be true if &lt;code&gt;u = 1&lt;/code&gt; or if &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; share a common factor larger than one, i.e. are both multiples of the order of &lt;code&gt;u&lt;/code&gt;. By the assumption that &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; are relatively prime, it must be that &lt;code&gt;u = 1&lt;/code&gt; which completes the proof.&lt;/p&gt;&lt;p&gt;We know by the definition of &lt;code&gt;e_i&lt;/code&gt; that &lt;code&gt;n/(p_i^e_i)&lt;/code&gt; takes &lt;code&gt;K&lt;/code&gt; to one for all &lt;code&gt;i&lt;/code&gt;. Using the above theorem, we can compose all the &lt;code&gt;p_i^e_i&lt;/code&gt; factors and easily prove by induction that the suggested formula indeed takes &lt;code&gt;K&lt;/code&gt; to one. It remains to be proven that no smaller number does so. Assume that there is such a number, and call it &lt;code&gt;L&lt;/code&gt;. We know that &lt;code&gt;L&lt;/code&gt; must be a divisor of our &lt;code&gt;n/(\prod p_i^e_i)&lt;/code&gt;, which means that at least one of the &lt;code&gt;e_i&lt;/code&gt; numbers in it is larger. Choose any one of those, say &lt;code&gt;g_i &amp;gt; e_i&lt;/code&gt;. Since every multiple of &lt;code&gt;L&lt;/code&gt; also takes &lt;code&gt;K&lt;/code&gt; to one, consider &lt;code&gt;n/(p_i^g_i)&lt;/code&gt;. This is obviously a multiple of &lt;code&gt;L&lt;/code&gt; and therefore &lt;code&gt;K^(n/(p_i^g_i)) = 1 (mod N)&lt;/code&gt;. However, we know by definition of &lt;code&gt;e_i&lt;/code&gt; that it must hold that &lt;code&gt;g_i &amp;lt;= e_i&lt;/code&gt; and therefore we conclude that &lt;code&gt;n/(\prod p_i^e_i)&lt;/code&gt; is indeed the smallest number that takes &lt;code&gt;K&lt;/code&gt; to one, i.e. the order of &lt;code&gt;K&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;So what is the complexity of this algorithm? It is easy to come up with a loose upper bound but it would be fairly difficult to compare this with the complexity of the divisor-based algorithm since the time required to execute either algorithms depends heavily on the properties of &lt;code&gt;N&lt;/code&gt; and the order we're looking for. Instead, I wrote &lt;a href="http://dl.dropbox.com/u/5412078/blog/group_order.cpp"&gt;a program&lt;/a&gt; to measure the running time cumulatively for the 200k values of &lt;code&gt;N&lt;/code&gt; above 99800000 and random &lt;code&gt;K&lt;/code&gt;. This algorithm outperformed the divisor-based one by about a factor of 19 on my computer (it ran for about 1s versus about 19s for the divisor-based algorithm). I also tried some optimizations in the implementation of the algorithm, namely special treatment of two (which allows the main loop to skip even numbers) and precomputing a list of primes and both of theese yield about a 10% improvement. Check out the code if you're interested.&lt;/p&gt;&lt;p&gt;I'd be very interested to know if someone can find a nice way to asymptotically quantify this difference between the algorithms. The runtime of the faster algorithm depends on both the number of prime factors in a number and the exponents of those factors. Therefore, I don't expect it is possible to relate that back to &lt;code&gt;n&lt;/code&gt; in a tight bound, but there might be meaningful to compare the amortized cost of these algorithms over some distribution of &lt;code&gt;N&lt;/code&gt; and &lt;code&gt;K&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Thanks if you read this far, and sorry about not using LaTeX :).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6679696301566560047-6994097707613326444?l=cs-haven.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cs-haven.blogspot.com/feeds/6994097707613326444/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cs-haven.blogspot.com/2012/02/efficiently-computing-order-of-element.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/6994097707613326444'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/6994097707613326444'/><link rel='alternate' type='text/html' href='http://cs-haven.blogspot.com/2012/02/efficiently-computing-order-of-element.html' title='Efficiently computing the order of an element in a multiplicative group'/><author><name>buda</name><uri>http://www.blogger.com/profile/04145572779602673421</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-6679696301566560047.post-4537801034441783436</id><published>2012-02-04T07:05:00.000-08:00</published><updated>2012-02-08T00:56:24.735-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vim'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Why Vim is great (Exhibit 2: Vim is scriptable)</title><content type='html'>&lt;p&gt;One great feature of Vim is that it is scriptable, which allows pretty much infinite customizability. I already &lt;a href="http://cs-haven.blogspot.com/2009/04/vim-c-macro-like-expansion-script.html"&gt;blogged about&lt;/a&gt; a plugin I wrote for speeding up C++ coding, but there are many other &lt;a href="http://www.vim.org/scripts/index.php"&gt;far more useful plugins&lt;/a&gt;&amp;nbsp;out there. The point is, if you're a programmer and you want to speed up something you're doing often, you can easily do it yourself if an appropriate plugin doesn't already exist or you can't find it. My example above is obviously covered by some excellent plugins, but they are much more heavyweight than what I wanted to do.&lt;/p&gt;&lt;p&gt;Another example where an existing script (probably) doesn't exist and that I encountered recently was reformatting some context free grammars encoded in LaTeX. I was helping organize all the exam problems from the last several years of our compiler design course into a problem book to give out to students for practice. There were probably more than 50 grammars in these problems, written in several different styles of marking nonterminals, listing rules etc. For example, these were three of the styles we had originally:&lt;br&gt;&lt;pre&gt;&lt;br /&gt;S \(\to\) aAbBa | bBaAb&lt;br /&gt;A \(\to\) AaBb | Ba | a&lt;br /&gt;B \(\to\) Ab | b&lt;br /&gt;&lt;br /&gt;S \(\to\) A a A b&lt;br /&gt;A \(\to\) A b&lt;br /&gt;A \(\to\) d B&lt;br /&gt;A \(\to\) f&lt;br /&gt;B \(\to\) f&lt;br /&gt;&lt;br /&gt;S \(\to\) AB | dC     A \(\to\) aCB | \(\varepsilon\) &lt;br /&gt;B \(\to\) eS | bC     C \(\to\) c | aB&lt;br /&gt;&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;We obviously wanted to have a uniform style for all these grammars, so I wrote a &lt;a href="http://dl.dropbox.com/u/5412078/blog/grammar.vim"&gt;short script&lt;/a&gt; that reads in a grammar in any of the original styles and reformats it. Obviously, you could write a program in any language to do that, but since these grammars were part of a large document, you'd have to delimit them somehow for the external program or copy/paste them around. If you think about it, the problem was an exact fit for an editor because it is part of &lt;i&gt;editing a document&lt;/i&gt;. Also, it's not really possible to do this with a macro that doesn't itself contain some code. In any case, writing the script took probably less than 20 minutes; far less than it would have taken me to manually convert all the grammars, not to mention far less error prone.&lt;/p&gt;&lt;p&gt;So how do you write these scripts? Vim has a buit-in scripting language (commonly referred to just as Vimscript) which is a dynamic language that feels sort of like Python, but has somewhat clunky syntax. I'm not going to talk about the language very much here because it's covered well elsewhere, for example in a series of &lt;a href="http://www.ibm.com/developerworks/linux/library/l-vim-script-1/index.html"&gt;IBM DeveloperWorks articles&lt;/a&gt;, and in Vim's help by typing &lt;code&gt;:help script&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;The other thing to note is that you can actually script Vim using several other (better) languages, namely Python, Ruby, Perl, Scheme and Tcl. You can find great info on these in Vim's help under &lt;code&gt;python&lt;/code&gt;, &lt;code&gt;ruby&lt;/code&gt;, &lt;code&gt;perl&lt;/code&gt;, &lt;code&gt;mzscheme&lt;/code&gt; and &lt;code&gt;tcl&lt;/code&gt;, respectively. I've only tried the Python interface myself and found it more enjoyable than using Vimscript. However, there are some unfortunate caveats. First, you'll need Vim compiled with the appropriate flag set to enable each interface (for example &lt;code&gt;+python&lt;/code&gt; or &lt;code&gt;+python3&lt;/code&gt;). This in itself motivates people to write plugins in Vimscript since it is the only language guaranteed to be supported (I read somewhere that Python was supposedly included in all the binaries after Vim 7.0, but I haven't been able to verify that right now). Furthermore, debugging these external scripts is a lot harder as the error messages you get aren't very helpful.&lt;/p&gt;&lt;p&gt;In any case, scriptability is a great feature that opens up a lot of opportunities for increased productivity, and that's what we're all after :). Happy Vimming!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6679696301566560047-4537801034441783436?l=cs-haven.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cs-haven.blogspot.com/feeds/4537801034441783436/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cs-haven.blogspot.com/2011/11/why-vim-is-great-exhibit-2-vim-is.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/4537801034441783436'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/4537801034441783436'/><link rel='alternate' type='text/html' href='http://cs-haven.blogspot.com/2011/11/why-vim-is-great-exhibit-2-vim-is.html' title='Why Vim is great (Exhibit 2: Vim is scriptable)'/><author><name>buda</name><uri>http://www.blogger.com/profile/04145572779602673421</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-6679696301566560047.post-1499686411034529571</id><published>2010-03-11T02:32:00.000-08:00</published><updated>2010-03-11T03:27:03.338-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vim'/><title type='text'>Why Vim is great (Exhibit 1: macros across multiple buffers)</title><content type='html'>I'll give a little bit of an introduction to my Vim experience in the next paragraph and an introduction to a real life problem that I solved using this Vim "trick" recently in the paragraph after that. You can skip to paragraph four if you don't care about that and just want to see the "trick" (it should be more or less self-standing).&lt;br /&gt;&lt;br /&gt;I've been using Vim on a daily basis for about four years now, and I'm really happy that I took the time to learn to use it and stuck it out when it was rough. There used to be a class in the first semester at my college that had a lab in Vi basics, but it wasn't really taught in a meaningful way but rather left the students to "try it out" which resulted in people trying to type something and "getting stuck" in some mode without knowing how to do anything. At the end, everyone (including me) hated it, thought it was an old editor that nobody should ever use. Later, I tried getting into it a few times and finally made it stick. I have by no means mastered it, but I feel pretty comfortable using it and I hope I can show you a few tricks that are not too basic and well known (I'm hoping to make a series of posts out of this).&lt;br /&gt;&lt;br /&gt;I recently started maintaining a site (&lt;span style="font-style:italic;"&gt;pro bono&lt;/span&gt; :) that was abandoned around 2007. The whole thing is mostly HTML only with a few PHP scripts here and there. Unfortunately, it is structured in a way that requires a lot of duplicated effort since most files are referenced in several places. Since the updates are not very frequent (about one a week) and there is a lot of existing content that is important, I decided (for now) not to port it to a CMS and just stick to the old system. I've since developed a few scripts and tools that make the update process pretty simple. The central item of the site are trip reports that include some text and a link to a picture gallery. We now use &lt;a href="http://picasaweb.google.com"&gt;Picasa&lt;/a&gt; to host the pictures. Every report includes a link to the appropriate album (or several) at the bottom. This contains a clickable thumbnail of the album cover and a clickable album name below it. Both these links open the album in the same window (no &lt;code&gt;target&lt;/code&gt; attribute). I got complaints that once you start browsing through the gallery, there's no easy way to get back to the main site. I didn't notice this because I have a habit of always using right click-&gt;open in new tab on all links. Unfortunately, Picasa doesn't allow you to add a link to your album (from searching around, it seems like a very requested feature). I thought my best option was to simply add &lt;code&gt;target="_blank"&lt;/code&gt; to every gallery link so that it would open in a separate window. Now, since I'd uploaded two years worth of content (a lot of reports), there were a lot of links to fix.&lt;br /&gt;&lt;br /&gt;So on to Exhibit 1: I have a ton of files that all contain two links to an album hosted on Picasa and I want them to start opening in a new window, i.e. need to add target="_blank" (there are other ways to fix this, but they all require at least some change in the link HTML). I remembered seeing a video of a similar problem a few months ago and how it could be solved with Vim. I downloaded all the files into a directory and opened them all with &lt;code&gt;vim *&lt;/code&gt;. Then I recorded a macro to register a (with &lt;code&gt;qa&lt;/code&gt;). The goal was to somehow identify the gallery link. Fortunately, this turned out to be really easy since both these links start with &lt;code&gt;&amp;lt;a href="http://picasaweb&lt;/code&gt;. So I did a simple substitute command typing&lt;br /&gt;&lt;br /&gt;&lt;code&gt;:%s#&amp;lt;a \zs\zehref="http://picasaweb#target="_blank" #g&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The only nontrivial part of this command are &lt;code&gt;\zs&lt;/code&gt; and &lt;code&gt;\ze&lt;/code&gt; which basically define where the substitute text (the target attribute) will be inserted.&lt;br /&gt;&lt;br /&gt;And now the "magic" part. After applying this command, I typed &lt;code&gt;:wn&lt;/code&gt; to store the changes and move to the next buffer and pressed &lt;code&gt;q&lt;/code&gt; to stop recording. At this point, I looked at the number of remaining buffers and applied the macro that many times (&lt;code&gt;50@a&lt;/code&gt;). The screen started blinking as Vim was crunching away and after a second or so stopped with the message "Cannot go beyond last file" which is expected due to the &lt;code&gt;:wn&lt;/code&gt; command on the last file.&lt;br /&gt;&lt;br /&gt;And that was it. The whole thing took me about a minute to do. Sure, I could have written a script that did the same thing but it would have probably taken a few more minutes, and, after all, Vim was made for these sort of things. I tried searching for the video that taught me this (i.e. that mentioned it - once you hear about it, it is very obvious) to give due credit, and managed to find it &lt;a href="http://vimeo.com/4456458"&gt;here&lt;/a&gt; (it's by Derek Wyatt). Till next time, happy Vimming :).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6679696301566560047-1499686411034529571?l=cs-haven.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cs-haven.blogspot.com/feeds/1499686411034529571/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cs-haven.blogspot.com/2010/03/why-vim-is-great-exhibit-1-macros.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/1499686411034529571'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/1499686411034529571'/><link rel='alternate' type='text/html' href='http://cs-haven.blogspot.com/2010/03/why-vim-is-great-exhibit-1-macros.html' title='Why Vim is great (Exhibit 1: macros across multiple buffers)'/><author><name>buda</name><uri>http://www.blogger.com/profile/04145572779602673421</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>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6679696301566560047.post-8964719503440100027</id><published>2010-02-22T01:15:00.000-08:00</published><updated>2010-02-22T01:41:34.538-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='education'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Top 25 Most Dangerous Programming Errors and what we're doing about them in education</title><content type='html'>The other day I stumbled upon &lt;a href="http://cwe.mitre.org/top25/"&gt;this list&lt;/a&gt; of 25 most dangerous programming errors. The list was supposedly compiled based on data from 20 different organizations. Of course, this doesn't really tell us anything and by no means implies that the list is "correct", but it is somewhat in line with what is commonly talked about in the computer security literature.&lt;br /&gt;&lt;br /&gt;The point of this post is not to discuss these errors in detail, but to see what we can do about them in CS college education. The common denominator of most of these errors is assuming user input is safe and friendly, yet this is something that I feel is not talked about during education nearly enough. At the same time, the two last items on the list (broken/risky crypto algorithm and race conditions) are something we devote a lot of time to. Specifically, a large part of the operating systems course talks about avoiding race conditions and we have a specialized course that deals with cryptography. Additionally, there's a post-graduate computer security course that also fails to address any of the errors in the "user input" category, but also focuses on cryptography and authentication. To make matters worse, the "user input" errors are much easier to understand and deal with than these more "advanced" errors.&lt;br /&gt;&lt;br /&gt;There are other aspects to this that I won't go into now, but I'm sure that every person with a CS college degree should know about all of these errors so we need to start covering them all in class (it is too important to be left for self-study).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6679696301566560047-8964719503440100027?l=cs-haven.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cs-haven.blogspot.com/feeds/8964719503440100027/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cs-haven.blogspot.com/2010/02/top-25-most-dangerous-programming.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/8964719503440100027'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/8964719503440100027'/><link rel='alternate' type='text/html' href='http://cs-haven.blogspot.com/2010/02/top-25-most-dangerous-programming.html' title='Top 25 Most Dangerous Programming Errors and what we&apos;re doing about them in education'/><author><name>buda</name><uri>http://www.blogger.com/profile/04145572779602673421</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>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6679696301566560047.post-3883131940299093738</id><published>2009-04-22T22:53:00.000-07:00</published><updated>2012-02-03T07:33:52.295-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='book review'/><category scheme='http://www.blogger.com/atom/ns#' term='computational complexity'/><title type='text'>Book Review: M. Garey, D. Johnson: Computers and Intractability: A Guide to the Theory of NP-Completeness</title><content type='html'>Today I'll review the wonderful &lt;a href="http://www.amazon.com/gp/product/0716710455?ie=UTF8&amp;amp;tag=compscieandpr-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0716710455"&gt;Computers and Intractability: A Guide to the Theory of NP-Completeness&lt;/a&gt;&lt;img alt="" border="0" height="1" src="http://www.assoc-amazon.com/e/ir?t=compscieandpr-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=0716710455" style="border: none !important; margin: 0px !important;" width="1" /&gt;. I first heard about this book while watching Steven Skiena's online video lectures (which I &lt;a href="http://cs-haven.blogspot.com/2009/04/computer-science-video-lectures-worth.html"&gt;blogged about recently&lt;/a&gt;) three or four years ago, where he recommends it as the best book on the topic (and actually uses it in class). I've since read it several times and used it as reference many more, and before going into the details, I'll just say I think it's awesome.&lt;br /&gt;&lt;br /&gt;And now for the details :). This is not your standard "read before sleep" book. It's more like a math book (and math books are read with pen and paper in hand :). When I first tried reading it (that was when I had just a basic grasp on the topic), I found it pretty hard going, and had to restart a few times. This is not to say it's not well written; on the contrary, the writing is great. It just took me a while to get into the right mindset for it. If you're a fan of formalisms and Turing machines, you'll have no problems whatsoever. If you're not, but still want to understand this stuff, you'll have to make more of an effort, but I think it's well worth it. The book doesn't force formalisms down your throat for no reason, but develops the theory from the formal to the informal and more intuitive (but still correct) in a very elegant way.&lt;br /&gt;&lt;br /&gt;The book is logically divided into three parts. In the first part, you'll learn why complexity matters and some basic terminology regarding Turing machines, languages, encoding schemes, decision problems and "real problems" (and how they all relate to each other) and the all important polynomial transformation between problems. Then you'll read about what it means for a problem to be in P and NP. After this introduction, the authors present Cook's theorem that is basically the origin of the whole story, in which the famous satisfiability problem is defined and proved to be NP-complete. What follows are proofs (via polynomial transformation) that "6 basic" NP-complete problems are indeed NP-complete. These are 3-satisfiability, 3-dimension matching, vertex cover, clique, hamiltonian circuit and partition. These transformations are a bit more involved then most (since you don't have many problems to choose from when you start building up the NP-complete set), as is the proof of Cook's theorem, but I find them mathematically beautiful (and in general, constructing NP-completeness proofs is a nice mind "game", not to mention useful in many cases :). However, on your first reading, you'll probably want to skim these and just get the intuition behind them and understand "the big picture".&lt;br /&gt;&lt;br /&gt;After that, the authors take a step back and try to define three general techniques for constructing NP-completeness proofs (restriction, local replacement and component design) and show a few examples of each. You are then presented with fourteen exercise problems on which to try the techniques out. This ends the first part of the book (about 65 pages).&lt;br /&gt;&lt;br /&gt;The second part of the book starts with exploring how the NP-completeness of a problem changes when you constrain it or change it. Then it explains what it means for a problem to be NP-complete in the strong sense and what are Turing reducibility and NP-hardness. The next chapter gives some basic information about dealing with NP-complete problems through approximation algorithms, but what I think is far more interesting (in the context of this book), they show how using the theory of NP-completeness you can prove that some problems can't even be approximated well (for certain definitions of "a good approximation" which I won't go into here) in polynomial time (unless P = NP). The second part ends with expanding the complexity hierarchy with some more advanced concepts like co-NP, gama-reductions and gama-completeness, #P-completeness, PSPACE, DLOGSPACE, EXPTIME etc. (these are all covered with examples and provide solid intuition about what these things are on the first reading, but need to be studied a bit more carefully for full understanding).&lt;br /&gt;&lt;br /&gt;Finally, the third part of the book is a catalog of about 300 NP-complete problems (sorted into several categories). This is a great reference! If you have an NP-complete problem on your hands, chances are it has a name and it's on this list :) Given the age of this book, I'd imagine the current list of known NP-complete problems is somewhat bigger, but this one is comprehensive enough that you can probably at least find a problem that is close enough to your problem that you'll be able to construct a proof yourself.&lt;br /&gt;&lt;br /&gt;So to summarize, this is an awesome book. NP-complete problems pop up just about everywhere, and it's important to be able to recognize them (and not waste too much time trying to solve them to optimality quickly). My advice for a reading algorithm: read the first part, skimming over the proofs for intuition, then reread it a month later going through the proofs with pen and paper. Then read the second part (it's not as important so you can skim it or read it for full comprehension, depending on how much you want to get out of it) and skim the catalog to get a feel for which problems are there (so you can use it as a reference). You'll recognize quite a few of them, probably some you've met at work :). Also, even if you're not in Computer Science, you might like this book from an epistemological perspective ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6679696301566560047-3883131940299093738?l=cs-haven.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cs-haven.blogspot.com/feeds/3883131940299093738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cs-haven.blogspot.com/2009/04/book-review-m-garey-d-johnson-computers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/3883131940299093738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/3883131940299093738'/><link rel='alternate' type='text/html' href='http://cs-haven.blogspot.com/2009/04/book-review-m-garey-d-johnson-computers.html' title='Book Review: M. Garey, D. Johnson: Computers and Intractability: A Guide to the Theory of NP-Completeness'/><author><name>buda</name><uri>http://www.blogger.com/profile/04145572779602673421</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-6679696301566560047.post-2864234008107704586</id><published>2009-04-19T00:01:00.000-07:00</published><updated>2009-04-19T01:51:40.390-07:00</updated><title type='text'>Book Review: Andrew Tanenbaum: Computer Networks (4th edition)</title><content type='html'>Today I'm going to review the classic &lt;a href="http://www.amazon.com/gp/product/0130661023?ie=UTF8&amp;tag=compscieandpr-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0130661023"&gt;Computer Networks (4th Edition)&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=compscieandpr-20&amp;l=as2&amp;o=1&amp;a=0130661023" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt; by &lt;a href="http://www.cs.vu.nl/~ast/"&gt;Andrew Tanenbaum&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I first read a significant portion of this book a few years ago when I took a class in computer networks at the University (it's a 4th year graduate course, considered by most to be one of the hardest in the program) that was mostly based on it. Since I'm a big fan of reading books cover to cover (which is BTW the ideal way to read this particular book), I took some time the last few weeks and did just that. Having read most of it before, and dealing with networks quite a lot in my work and spare time, I read it mostly for review value.&lt;br /&gt;&lt;br /&gt;As the title suggests, this is a very general book, and as such holds real value. After all, in today's world, who can ignore networking? If anything, networks will become more and more important, and understanding them is already pretty much mandatory for anyone in ICT. This book will give you a great framework for dealing with all sorts of networks you might come across in the wild. For the most part, it explains how networks are built in layers, with each layer offering services to the layer above it and consuming the services of the layer below it. Two major reference models are covered: the &lt;abbr title="Open Systems Interconnection"&gt;OSI&lt;/abbr&gt;/&lt;abbr title="International Organization for Standardization"&gt;ISO&lt;/abbr&gt; one and the TCP/IP one. You will get a solid understanding of just how much politics influences standard's bodies and better understand why some things are not as good as they could be :).&lt;br /&gt;&lt;br /&gt;For the most part, the book then goes through the layers (of something that I've heard called the "Tanenbaum hybrid model" which is basically what is used in practice (in the Internet for example). You will learn some basic things about the physical layer like the kinds of cables in use and their characteristics, fiber, radio, microwave and satellite transmission..., encoding bits with volts. After the physical layer, there's a high level explanation of how the telephone system works. Then he goes on a detailed tour of the data link layer (which is basically a direct "wire-like" connection between two machines), talking about error correction codes (Hamming code, &lt;abbr title="Cyclic Redundancy Check"&gt;CRC&lt;/abbr&gt;), framing and flow control. Here he also discusses Bluetooth, Ethernet (in some detail), WLAN etc. In covering the network layer, the main focus is on routing, congestion control and internetworking. There's also a relatively detailed discussion of the network layer in the Internet where IPv4 and IPv6 are discussed (among other things). Then he goes on to cover the transport layer which mainly deals with establishing connections, retransmissions and congestion control. Here he talks a bit about &lt;abbr title="User Datagram Protocol"&gt;UDP&lt;/abbr&gt; and &lt;abbr title="Transport Control Protocol"&gt;TCP&lt;/abbr&gt;, which are the "main" transport layer protocols in the Internet. Finally, there's a chapter about the application layer that features pretty much anything you've heard about, from DNS and e-mail to the World Wide Web and its protocols, to multimedia.&lt;br /&gt;&lt;br /&gt;The book finishes with about 200 pages on network security, which covers your basic cryptography and different protocols in the different layers that implement various measures. There is also a great section on further reading per topic.&lt;br /&gt;&lt;br /&gt;One final note. Although this is the 4th edition of the book, the book was released in 2002. which is (in computer terms) ancient. To put things in perspective, Wikipedia was started in 2001., YouTube in 2005., social networks didn't really exists in 2002. etc. Still, the things covered in this book have not changed that much so this should not worry you too much.&lt;br /&gt;&lt;br /&gt;So to summarize, this is an awesome book that I think everyone in ICT should read. It's OK as a reference, although you'll probably want to consult specialized literature for specific topics (like the relevant &lt;abbr title="Request For Comments"&gt;RFCs&lt;/abbr&gt; for Internet related stuff). It's pretty expensive, so you might want to get a used copy, but it's worth owning!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6679696301566560047-2864234008107704586?l=cs-haven.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cs-haven.blogspot.com/feeds/2864234008107704586/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cs-haven.blogspot.com/2009/04/book-review-andrew-tanenbaum-computer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/2864234008107704586'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/2864234008107704586'/><link rel='alternate' type='text/html' href='http://cs-haven.blogspot.com/2009/04/book-review-andrew-tanenbaum-computer.html' title='Book Review: Andrew Tanenbaum: Computer Networks (4th edition)'/><author><name>buda</name><uri>http://www.blogger.com/profile/04145572779602673421</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-6679696301566560047.post-4706700670902153934</id><published>2009-04-17T10:09:00.000-07:00</published><updated>2010-02-22T01:14:37.241-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>Using vector and deque "the right way"</title><content type='html'>If you're using the &lt;abbr title="Standard Templates Library"&gt;STL&lt;/abbr&gt;, chances are you're using &lt;code&gt;vector&lt;/code&gt; and &lt;code&gt;deque&lt;/code&gt; a lot. They are two of the three sequences defined in section 21.1.1 of the C++ standard (the third one being &lt;code&gt;list&lt;/code&gt; which I won't talk about in this post).&lt;br /&gt;&lt;br /&gt;The nice thing about dealing with these sequences is that they manage their memory automatically when you're using &lt;code&gt;push_back&lt;/code&gt; and &lt;code&gt;pop_back&lt;/code&gt; and you don't really have to think about it. Naturally, I did a search to see if this has been beaten dead, and sure enough, I found &lt;a href="http://www.ddj.com/cpp/184401375"&gt;a great article&lt;/a&gt; about it by &lt;a href="http://www.acceleratedcpp.com/authors/koenig/"&gt;Andrew Koenig&lt;/a&gt; and &lt;a href="http://www.acceleratedcpp.com/authors/moo/index.html"&gt;Barbara Moo&lt;/a&gt; of &lt;a href="http://www.amazon.com/gp/product/020170353X?ie=UTF8&amp;tag=compscieandpr-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=020170353X"&gt;Accelerated C++: Practical Programming by Example (C++ In-Depth Series)&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=compscieandpr-20&amp;l=as2&amp;o=1&amp;a=020170353X" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt; fame (also see &lt;a href="http://en.wikipedia.org/wiki/Argument_dependent_name_lookup"&gt;Koenig lookup&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Instead of repeating everything that's in there, I'll just recap the main point. The C++ standard  (in section 23.2.4.1) guarantees amortized constant time insert and erase at the end for vector. This basically means that you can grow a &lt;code&gt;vector&lt;/code&gt; from empty to size &lt;code&gt;O(n)&lt;/code&gt; in &lt;code&gt;O(n)&lt;/code&gt; time using &lt;code&gt;push_back&lt;/code&gt;, although some individual &lt;code&gt;push_back&lt;/code&gt; calls might take linear time (the ones that cause reallocation, which consists of allocating a new block of memory, copying the old objects, destroying them and deallocating the old memory block). One subtle thing to note here is that reallocation (which should mostly be transparent and not something you worry about) invalidates pointers and iterators into the sequence.&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;vector&lt;/code&gt; class offers some facilities that let you take a more active role in this memory management process. These first function is &lt;code&gt;void reserve(size_type n)&lt;/code&gt; which makes the &lt;code&gt;vector&lt;/code&gt; allocate enough memory for &lt;i&gt;at least&lt;/i&gt; &lt;code&gt;n&lt;/code&gt; items, effectively making all &lt;code&gt;push_back&lt;/code&gt; calls up to &lt;code&gt;n&lt;/code&gt; items take constant time. The other function is &lt;code&gt;size_type capacity() const&lt;/code&gt; that lets you know the currently allocated memory for the &lt;code&gt;vector&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;The standard doesn't define how this is to be implemented, but by reading around and looking and source code, it seems most implementations grow the vector exponentially, with factor between 1.5 and 2 (although there might be others). Fortunately, even if you can't access the source of your implementation, you can easily test it out with a program like this:&lt;br /&gt;&lt;pre name="code" class="cpp"&gt;&lt;br /&gt;#include &amp;lt;cstdio&gt;&lt;br /&gt;#include &amp;lt;vector&gt;&lt;br /&gt;&lt;br /&gt;int main() {&lt;br /&gt;    std::vector&amp;lt;int&amp;gt; v;&lt;br /&gt;&lt;br /&gt;    std::vector&amp;lt;int&gt;::size_type old_capacity = v.capacity();&lt;br /&gt;    for (int i=0; i&amp;lt;1000; ++i) {&lt;br /&gt;        v.push_back(i);&lt;br /&gt;        const std::vector&amp;lt;int&amp;gt;::size_type new_capacity = v.capacity();&lt;br /&gt;        if (old_capacity != new_capacity) {&lt;br /&gt;            std::printf("%4u %4u\n", (unsigned)v.size(), (unsigned)v.capacity());&lt;br /&gt;            old_capacity = new_capacity;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    std::puts("growth done");&lt;br /&gt;    for (int i=0; i&amp;lt;1000; ++i) {&lt;br /&gt;        v.pop_back();&lt;br /&gt;        const std::vector&amp;lt;int&amp;gt;::size_type new_capacity = v.capacity();&lt;br /&gt;        if (old_capacity != new_capacity) {&lt;br /&gt;            std::printf("%4u %4u\n", (unsigned)v.size(), (unsigned)v.capacity());&lt;br /&gt;            old_capacity = new_capacity;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    std::puts("shrink done");&lt;br /&gt;&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;On my machine, this outputs&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   1    1&lt;br /&gt;   2    2&lt;br /&gt;   3    4&lt;br /&gt;   5    8&lt;br /&gt;   9   16&lt;br /&gt;  17   32&lt;br /&gt;  33   64&lt;br /&gt;  65  128&lt;br /&gt; 129  256&lt;br /&gt; 257  512&lt;br /&gt; 513 1024&lt;br /&gt;growth done&lt;br /&gt;shrink done&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see, the factor here is obviously two. Two other points are of interest. First, the &lt;code&gt;vector&lt;/code&gt; starts out with no allocated memory. Secondly, the memory is not released when the size shrinks. This means that the memory will be allocated until the object is destroyed, unless you explicitly call &lt;code&gt;clear&lt;/code&gt; or &lt;code&gt;resize&lt;/code&gt;. Also, if you use &lt;code&gt;reserve&lt;/code&gt; with some amount just before the loop, you'll basically seed the sequence with something other then one. The point here is that you get a lot of small reallocations at the start, which does seem like a waste.&lt;br /&gt;&lt;br /&gt;The standard actually recommends using vector "by default" (section 23.1.1.2). Browsing around &lt;a href="http://herbsutter.wordpress.com/"&gt;Herb Sutter's&lt;/a&gt; &lt;a href="http://www.gotw.ca/gotw/index.htm"&gt;Guru of the Week&lt;/a&gt; I stumbled upon &lt;a href="http://www.gotw.ca/gotw/054.htm"&gt;an entry&lt;/a&gt; where he recommends using &lt;code&gt;deque&lt;/code&gt; as the default. So, for a bit of background, a &lt;code&gt;deque&lt;/code&gt; is a sequence that supports constant time insert and erase operations on both the front and the end (via &lt;code&gt;push&lt;/code&gt;/&lt;code&gt;pop&lt;/code&gt; &lt;code&gt;front&lt;/code&gt;/&lt;code&gt;back&lt;/code&gt;). It also supports random access iterators and random access via &lt;code&gt;operator[]&lt;/code&gt; and &lt;code&gt;at()&lt;/code&gt;, but random access is not constant time since a &lt;code&gt;deque&lt;/code&gt; is basically a linked list of fixed size memory chunks. This works quite well for memory management as the memory chunks are small and no reallocations are required when the sequence needs to grow. Still, the point Herb is making is kind of defeated by the timing data he includes in the post since &lt;code&gt;vector&lt;/code&gt; outperforms &lt;code&gt;deque&lt;/code&gt; in pretty much everything (I'd say, as expected). Still, &lt;code&gt;deque&lt;/code&gt; is a great sequence and is actually used by both &lt;code&gt;stack&lt;/code&gt; and &lt;code&gt;queue&lt;/code&gt; by default (for good reason) and is a great structure for implementing 0-1 &lt;abbr title="breadth first search"&gt;BFS&lt;/abbr&gt;.&lt;br /&gt;&lt;br /&gt;Going back to &lt;code&gt;vector&lt;/code&gt;, I'm wondering how people use &lt;code&gt;reserve&lt;/code&gt; in "real life". Often, I'll have a pretty good idea of how big a &lt;code&gt;vector&lt;/code&gt; will end up after a loop, and using &lt;code&gt;reserve&lt;/code&gt; in those cases seems like the right thing to do.&lt;br /&gt;&lt;pre name="code" class="cpp"&gt;&lt;br /&gt;std::vector&amp;lt;int&amp;gt; v;&lt;br /&gt;v.reserve(n);&lt;br /&gt;for (int i=0; i&amp;lt;n; ++i) {&lt;br /&gt;  v.push_back(i);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Should be better then&lt;br /&gt;&lt;pre name="code" class="cpp"&gt;&lt;br /&gt;std::vector&amp;lt;int&amp;gt; v(n);&lt;br /&gt;for (int i=0; i&amp;lt;n; ++i) {&lt;br /&gt;  v[i] = i;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;because the latter actually initializes n ints to zero in the constructor (and the benefit would increase when the items in the vector are objects with more state and possibly elaborate default constructors).&lt;br /&gt;&lt;br /&gt;Now the strange bit. Even though I've been programming in C++ for about five years now and I feel I know it really well and consider it my "main language", I've never used it on a multi-person project. In fact, I've never done a project over a few thousand lines in it, although doing a quick grep on the code I have on my home machine shows about 95k lines of C++ code I wrote. Due to strange circumstance, I've only had a chance to work on smallish sized projects (~5k lines) in C#, JavaScript, Python, PHP and Java, and on a medium (~30k lines) project in Java. So, I'm asking you, C++ developers, what are your experiences with using &lt;code&gt;vector&lt;/code&gt; and &lt;code&gt;deque&lt;/code&gt; in real projects? Is &lt;code&gt;reserve&lt;/code&gt; used and how do you estimate the right size to use? Thanks!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6679696301566560047-4706700670902153934?l=cs-haven.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cs-haven.blogspot.com/feeds/4706700670902153934/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cs-haven.blogspot.com/2009/04/using-vector-and-deque-right-way.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/4706700670902153934'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/4706700670902153934'/><link rel='alternate' type='text/html' href='http://cs-haven.blogspot.com/2009/04/using-vector-and-deque-right-way.html' title='Using vector and deque &quot;the right way&quot;'/><author><name>buda</name><uri>http://www.blogger.com/profile/04145572779602673421</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-6679696301566560047.post-1383073821073408760</id><published>2009-04-15T00:21:00.000-07:00</published><updated>2009-04-15T01:02:36.770-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='book review'/><category scheme='http://www.blogger.com/atom/ns#' term='OOP'/><title type='text'>Book Review: Matt Weisfeld: The Object-Oriented Thought Process</title><content type='html'>Today I'll write a quick review of the ambitiously titled &lt;a href="http://www.amazon.com/gp/product/0672330164?ie=UTF8&amp;tag=compscieandpr-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0672330164"&gt;The Object-Oriented Thought Process (3rd Edition) (Developer's Library)&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=compscieandpr-20&amp;l=as2&amp;o=1&amp;a=0672330164" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;.&lt;br /&gt;&lt;br /&gt;Just by browsing through the table of contents (which is always a nice way to start thinking about buying or reading a book), you'll see that this book attempts to cover a lot of ground. In fact, on the second edition cover, the subtitle said "An introduction to object-oriented concepts for programmers looking to &lt;i&gt;master&lt;/i&gt; modern application development tools, including Java and .NET" (my emphasis), but thankfully, they decided to remove that :). In reality, this book scratches the very surface of a lot of facets of "modern application development", but lacks any depth that could lead you to mastering anything. What you get is basically a lesson in object-oriented terminology. You'll hear about classes, objects, encapsulation, inheritance, composition and all the usual suspects, and then see a few (standard and very artificial) examples modeled with &lt;abbr title="Class-Responsibility-Collaborator"&gt;CRC&lt;/abbr&gt; cards and &lt;abbr title="Unified Modeling Language"&gt;UML&lt;/abbr&gt;.&lt;br /&gt;&lt;br /&gt;Unfortunately, the book then gets sidetracked into relational databases, XML, HTML, CSS, JavaScript, JavaBeans, CORBA and Web Services (you get about two to three pages about each). Finally, there's a twenty page chapter on design patterns that tells you what they are and lists a few. You can skip this whole part.&lt;br /&gt;&lt;br /&gt;To it's credit, the book is short, well written and (for the most part) correct. If you've just heard of object-oriented programming this book will give you a nice overview of what it's about, and possibly keep you from forming some misconceptions. On the other hand, if you're already familiar with &lt;abbr title="Object Oriented Programming"&gt;OOP&lt;/abbr&gt;, you won't really benefit much. I also think this might be a good book for people who aren't really planing on being developers but will be talking to developers in their work (like managers and marketers) as it is lightweight enough and doesn't really require previous knowledge (there's some Java and C# code in there, but it's very basic and not very important either). Finally, since this book doesn't hold any value as a reference and reading it more then once doesn't make much sense, if you want to read it, I recommend you lend it at the library and save some money. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6679696301566560047-1383073821073408760?l=cs-haven.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cs-haven.blogspot.com/feeds/1383073821073408760/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cs-haven.blogspot.com/2009/04/book-review-matt-weisfeld-object.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/1383073821073408760'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/1383073821073408760'/><link rel='alternate' type='text/html' href='http://cs-haven.blogspot.com/2009/04/book-review-matt-weisfeld-object.html' title='Book Review: Matt Weisfeld: The Object-Oriented Thought Process'/><author><name>buda</name><uri>http://www.blogger.com/profile/04145572779602673421</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-6679696301566560047.post-5677184842817446173</id><published>2009-04-11T22:38:00.001-07:00</published><updated>2009-04-15T00:21:18.715-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='book review'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><category scheme='http://www.blogger.com/atom/ns#' term='OOP'/><category scheme='http://www.blogger.com/atom/ns#' term='refactoring'/><title type='text'>Book Review: M. Feathers: Working Effectively With Legacy Code</title><content type='html'>First off all, happy Easter!&lt;br /&gt;&lt;br /&gt;For my first book review, I decided to write about a wonderful book I discovered about a year ago that I think not too many people know about, and that is &lt;a href="http://www.amazon.com/gp/product/0131177052?ie=UTF8&amp;tag=compscieandpr-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0131177052"&gt;Working Effectively with Legacy Code (Robert C. Martin Series)&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=compscieandpr-20&amp;l=as2&amp;o=1&amp;a=0131177052" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;.&lt;br /&gt;&lt;br /&gt;I got this book in my first week as a Google intern. Since I had some spare time in the evenings and on the weekends I read it right away and found it absolutely amazing. It basically talks about how to deal with the fact of changing requirements. In the early days of OOP, there was a tendency to over-engineer a project (trying to predict every possible change ahead of time, overuse of inheritance etc.). People soon realized that, while proper design is essential, you just can't predict every possible change, and sometimes you'll have to change your design to accommodate the new requirements. This is where the idea of refactoring code comes in. It's a process in which you change your code while preserving behavior, making it "nicer", in an attempt to make the behavior easier to change in a later step.&lt;br /&gt;&lt;br /&gt;The main problem here is preserving behavior while changing things. This can lead to all sorts of headaches and problems, but can be made a lot easier if your code has tests. This is also the main premise of this book; the author loosely defines legacy code as code without tests (and also code that's older then three months or so, which is probably a lot shorter than most people would think). There has been some controversy over tests a few months ago in the "blogosphere", mainly in &lt;a href="http://www.joelonsoftware.com/items/2009/01/31.html"&gt;posts&lt;/a&gt; and &lt;a href="http://blog.stackoverflow.com/2009/01/podcast-38/"&gt;podcasts&lt;/a&gt; by &lt;a href="http://www.joelonsoftware.com/"&gt;Joel Spolsky&lt;/a&gt; and &lt;a href="http://www.codinghorror.com/blog/"&gt;Jeff Attwod&lt;/a&gt; on one side, and &lt;a href="http://www.objectmentor.com/omTeam/martin_r.html"&gt;Robert Martin&lt;/a&gt; on the other, all of whom are well respected (for good reason) in the community. Basically, Joel and Jeff argue that Test Driven Development is going too far, and test can make your code harder to change (because you have to change your tests as well). While this might be true sometimes, I don't think it's a valid point if you design your test right. You should be testing your APIs and not your implementations (which is certainly not always possible, but should be a goal). Sure, writing a piece of code (a class for example) will take a bit longer initially because you'll need to write tests for it, but you get several benefits from that. First, you write code that uses your class, therefore exposing some possible weak spots in your API. Second, once you're done, you can be reasonably sure that your class does what you want. Also, when it comes time to change the implementation (or the API, which is not too big a deal if it's a small internal API - and someone else might be making the change, or it's been a year since you wrote the initial code), you'll have a safety-net since you'll be able to tell early if you broke something (there might of course be things you miss, but a lot fewer of them). On the other hand, you just can't unit test everything, but that's OK too. You can do some tests manually, or use specialized tools to automate that as much as possible. I feel that unit tests also provide great documentation for what the API is doing and how to use it (still, you should write more formal docs for external APIs :).&lt;br /&gt;&lt;br /&gt;One area especially where I think unit tests are extremely important are scripting languages. Many people used to think (or still do) that programs in scripting tend to be harder to change or more prone to "silly" bugs due to typos that don't get detected by the compiler. While this can be somewhat mitigated with using good IDE-s, having solid unit tests will pretty much eliminate these kinds of bugs and you'll be dealing with much the same bugs you were dealing with in compiled languages.&lt;br /&gt;&lt;br /&gt;So back to the book... This book will show you a wealth of options for creating this testing safety-net where there isn't any through a series of realistic examples in Java, C++ and C (although most of the techniques presented are applicable to most languages). It starts of by talking about breaking dependencies as the crucial step in getting (parts of) legacy code under tests. BTW, there is a lot of great material on dependency (and dependency injection) and how testing can make your code less coupled in the first place on the &lt;a href="http://googletesting.blogspot.com/"&gt;Google Testing Blog&lt;/a&gt;. Well worth reading and watching the YouTube videos.&lt;br /&gt;&lt;br /&gt;Then it introduces fakes and mocks that let you replace complex objects and interactions in your tests with simple ones, thus making tests faster (connecting to a fake database locally, vs. connecting to a database over the network for example), more focused and less flaky (they won't fail if the network fails or the database dies). Then Feathers talks about seams, which are ways to change behavior of some code without editing in that place. He introduces a lot of techniques that range from fairly obscure (like preprocessing and linking seams) to the more common object seams.&lt;br /&gt;&lt;br /&gt;In the next third of the book, he discusses how to deal with things like big classes that do a ton of things, how to go about understanding how objects interact in a complicated system and things like that. This part is mostly about creating the right mindset for dealing with legacy code, although most of the techniques presented are quite practical.&lt;br /&gt;&lt;br /&gt;Finally, the third part of the book contains the dependency breaking techniques the first two parts have been building up to in a really nice catalog that can be a great reference. You should read this book once from cover to cover to get it, and then skim it a few times in the following year to index the techniques better into your brain (and of course use the book as a reference).&lt;br /&gt;&lt;br /&gt;In conclusion, I think this book is definitely worth reading (if not owning). Even if you don't deal with legacy code on a day to day basis (which is probably rare), it will change the way you look at the new code you're writing, and hopefully convince you that you should be writing unit tests. Try it! :) (if you can get someone to review your code as well, you'll sleep even better, but that's another topic :).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6679696301566560047-5677184842817446173?l=cs-haven.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cs-haven.blogspot.com/feeds/5677184842817446173/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cs-haven.blogspot.com/2009/04/book-review-m-feathers-working.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/5677184842817446173'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/5677184842817446173'/><link rel='alternate' type='text/html' href='http://cs-haven.blogspot.com/2009/04/book-review-m-feathers-working.html' title='Book Review: M. Feathers: Working Effectively With Legacy Code'/><author><name>buda</name><uri>http://www.blogger.com/profile/04145572779602673421</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-6679696301566560047.post-6870981313765194425</id><published>2009-04-10T06:32:00.000-07:00</published><updated>2011-07-15T12:06:55.684-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Standard C function for reading arbitrarily long lines from files</title><content type='html'>This is a function I wrote back when I was learning C (and understanding why standards matter, thanks mostly to the wonderful Usenet group comp.lang.c). I translated the variable names and comments from Croatian to English and thought I'd post it here in case someone might find it useful. What it does basically is read a file one character at a time attempting to allocate more memory as needed. It's written in standards compliant C, and packed in a small test driver program. I'm not including a header file for it since it's only one function, but you can write one easily yourself.&lt;br /&gt;&lt;br /&gt;You can compile it with something like&lt;br /&gt;&lt;code&gt;&lt;br /&gt;gcc read_line.c -W -Wall -ansi -pedantic&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;and should get no warnings. If you want to test it, you should probably reduce &lt;code&gt;ALLOC_INCREMENT&lt;/code&gt; to something like &lt;code&gt;4&lt;/code&gt; or so.&lt;br /&gt;&lt;br /&gt;Most of the code is self explanatory and has detailed comments. There are a few design decisions I'd like to talk about. First off, the function returns the number of characters read as an &lt;code&gt;int&lt;/code&gt;, which is not really in line with the standard library which uses &lt;code&gt;size_t&lt;/code&gt; for buffer sizes. The simple reason is that I personally don't like working with unsigned values, except when doing modulo 2^n arithmetic and doing bitmask handling. It's also a nice way to report an error by returning &lt;code&gt;-1&lt;/code&gt; (although you could return (size_t)-1, but that is less nice). Also, in contexts where I use this function, &lt;code&gt;int&lt;/code&gt; is more then enough to represent all the possible line sizes.&lt;br /&gt;&lt;br /&gt;Second, the final amount of allocated memory might be higher then the number of bytes read. You can solve this easily by creating a wrapper function, similar to this one&lt;br /&gt;&lt;pre name="code" code="cpp"&gt;&lt;br /&gt;int read_line_with_realloc(char **s, FILE *fp) {&lt;br /&gt;  char *p = NULL;&lt;br /&gt;  int len = read_line(s, fp);&lt;br /&gt;  if (len == 0) {&lt;br /&gt;    return 0;&lt;br /&gt;  } else {&lt;br /&gt;    p = realloc(*s, len + 1); /* room for '\0' */&lt;br /&gt;    if (p == NULL) {&lt;br /&gt;      free(*s);&lt;br /&gt;      return -1;&lt;br /&gt;    }&lt;br /&gt;    *s = p;&lt;br /&gt;    return len;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Finally, there's no way to reuse the memory already allocated in a buffer, that is, it is assumed that the passed buffer is initially empty. This is basically to keep the interface clean, but can also be easily fixed with a wrapper.&lt;br /&gt;&lt;br /&gt;You can get the code &lt;a href="http://dl.dropbox.com/u/5412078/blog/read_line.c"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I've used this function many times, but as always (even with trivial code), there might be some errors in there. If you find any, please let me know.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6679696301566560047-6870981313765194425?l=cs-haven.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cs-haven.blogspot.com/feeds/6870981313765194425/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cs-haven.blogspot.com/2009/04/standard-c-function-for-reading.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/6870981313765194425'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/6870981313765194425'/><link rel='alternate' type='text/html' href='http://cs-haven.blogspot.com/2009/04/standard-c-function-for-reading.html' title='Standard C function for reading arbitrarily long lines from files'/><author><name>buda</name><uri>http://www.blogger.com/profile/04145572779602673421</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-6679696301566560047.post-1986168857333291424</id><published>2009-04-09T05:06:00.000-07:00</published><updated>2011-11-14T06:58:06.038-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='video lectures'/><category scheme='http://www.blogger.com/atom/ns#' term='algorithms'/><title type='text'>Computer Science video lectures worth watching</title><content type='html'>In this post I'm going to list a few great courses from the world's top CS Universities that have video lectures of the whole course.&lt;br /&gt;&lt;br /&gt;There are three excellent algorithm courses of this kind I'm aware of. First, there's the &lt;a href="http://ocw.mit.edu/OcwWeb/Electrical-Engineering-and-Computer-Science/6-046JFall-2005/VideoLectures/index.htm"&gt;MIT Introduction to Algorithms&lt;/a&gt; course, thought by &lt;a href="http://people.csail.mit.edu/cel/"&gt;Charles Leiserson&lt;/a&gt; and &lt;a href="http://erikdemaine.org/"&gt;Eric Demaine&lt;/a&gt;. Both these professors are great lecturers, with Eric Demaine being one of the best I've seen (it's really unfortunate that his other courses like &lt;a href="http://courses.csail.mit.edu/6.851/spring07/"&gt;Advanced Data Structures&lt;/a&gt; don't have video lectures). The course is based on the &lt;a href="http://www.amazon.com/gp/product/0262032937?ie=UTF8&amp;tag=compscieandpr-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0262032937"&gt;Introduction to Algorithms&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=compscieandpr-20&amp;l=as2&amp;o=1&amp;a=0262032937" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt; book, commonly known as CLRS (which are the initials of the authors). The L in CLRS is Charles Leiserson. As an aside, the R is &lt;a href="http://people.csail.mit.edu/rivest/"&gt;Ron Rivest&lt;/a&gt;, who is also the R in RSA. I'll probably do a review of this book some time, but it is considered by many to be the best introductory algorithms book out there (and in this sense, introductory basically means general algorithm design and analysis). It is mathematically pretty rigorous, very well written with lots of great exercises and problems and is very comprehensive (for example, it describes pretty much all the "textbook algorithms" you'll ever need at TopCoder). The course doesn't cover the whole book, but gives a great introduction to asymptotic analysis, sorting, randomized algorithms, hashing, self-balancing tree structures, greedy algorithms, dynamic programming and shortest paths algorithms. There's also a nice introduction to amortized analysis (which is sort of an advanced topic). The course ends with a series of lectures about "hot topics" in algorithms today, namely caching and parallelism in algorithms. Only the 2005 course has video lectures, which is unfortunate since they change the topics of these last lectures every time (you can still find the lecture notes though). Also, recitation which covers some interesting stuff is also not available in video (although it used to be, but the files were removed a while ago).&lt;br /&gt;&lt;br /&gt;As motivation for the course, prof. Leiserson mentions that it is believed that you can become a great programmer by programming for 10 years, or by programming for 2 years and taking an algorithms course. While this comment is a half-joke, there's no question that understanding algorithms makes you a better programmer. As far as the 10 years of programming, check out the classic post by &lt;a href="http://norvig.com"&gt;Peter Norvig&lt;/a&gt; called &lt;a href="http://norvig.com/21-days.html"&gt;Teach Yourself Programming in Ten Years&lt;/a&gt; (if you managed to miss it until now :). The number is pretty arbitrary, but it's probably not off by much.&lt;br /&gt;&lt;br /&gt;The second, less known course about algorithms is &lt;a href="http://www.youtube.com/watch?v=zWg7U0OEAoE"&gt;Data Structures and Algorithms&lt;/a&gt; from &lt;a href="http://www.iitd.ac.in/"&gt;IIT Delhi&lt;/a&gt; (the link is to the first lecture). The lectures are in clear English (except occasional burst of the local language :) and also follow CLRS. The course consists of 36 lectures and covers things from basic data structures like stacks and queues to hashing, sorting, self-balancing tree structures and graph algorithms. The lectures are for the most part pretty independent, and they cover some things that are not covered in the MIT course or in CLRS (for example AVL trees which are covered through exercises in the book).&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://www.cs.sunysb.edu/~algorith/video-lectures/"&gt;third algorithms course&lt;/a&gt; is the one by &lt;a href="http://www.cs.sunysb.edu/~skiena/"&gt;Steven Skiena&lt;/a&gt; from Stony Brook. This one is quite different from the previous two in the approach it takes (although the recommended course textbook is also CLRS). It far less mathematically rigorous and doesn't try so hard to prove everything. This might sound like a bad thing, but the emphasis of the course is on understanding how algorithms work and on general techniques for algorithm design. This is in line with Skiena's book &lt;a href="http://www.amazon.com/gp/product/1848000693?ie=UTF8&amp;tag=compscieandpr-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=1848000693"&gt;The Algorithm Design Manual&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=compscieandpr-20&amp;l=as2&amp;o=1&amp;a=1848000693" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;. This is not really an introductory book as it glosses over a lot of the details you might want to know, but if you're already familiar with algorithms it's a great read. It also contains a great algorithms catalog that contains enough information to recognize the problem you're facing and get an idea what to do (it used to be available online, but I can't find it right now). The course ends with a great introduction to complexity theory and identifying and tackling intractable problems, which is Skiena's primary research area.&lt;br /&gt;&lt;br /&gt;Finally, I'll mention one non-algorithms course, namely &lt;a href="http://webcast.berkeley.edu/course_details.php?seriesid=1906978500"&gt;CS 61C Machine Structures&lt;/a&gt; from &lt;a href="http://berkeley.edu/"&gt;UC Berkley&lt;/a&gt;. They post video lectures for this course every semester, but the one I'm linking to is held by &lt;a href="http://www.eecs.berkeley.edu/Faculty/Homepages/garcia.html"&gt;Dan Garcia&lt;/a&gt; who is the best lecturer I've ever seen. Apart from that, the course is so fundamental to Computer Science that I think it's the one course everyone should take. In my University program, we had about three or four courses that cover the the individual parts of this course in greater depth, but I feel adding this kind of all-in-one course would actually be great. This is an awesome course to learn about some of the key abstractions in computers. It starts with an introduction to C and basic programming, then moves on to MIPS and some low-level programming. Then there's a basic lecture about compiling where people get a feeling of how the things they write in C get converted to MIPS. After that there's a short and elementary lecture on basic electronics (basically how you move from the abstraction level of electrons and protons to the level of transistors and electronic circuits) and several lectures on digital logic elements. Here they explain how you make things like adders and registers from gates. Then they use this elements to create a functional, pipelined CPU, explain caching and virtual memory, and connect the hardware with the MIPS code through the powerful idea of the ISA (Instruction Set Architecture). After listening to this course, it's really easy to understand how computers work "from the ground up" at an elementary level. There are a few lectures in the course that are sort of out of place, like the one on networking (and it's not very good either) and optimization, but you can skip those.&lt;br /&gt;&lt;br /&gt;If you know a good course that I missed, let me know! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6679696301566560047-1986168857333291424?l=cs-haven.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cs-haven.blogspot.com/feeds/1986168857333291424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cs-haven.blogspot.com/2009/04/computer-science-video-lectures-worth.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/1986168857333291424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/1986168857333291424'/><link rel='alternate' type='text/html' href='http://cs-haven.blogspot.com/2009/04/computer-science-video-lectures-worth.html' title='Computer Science video lectures worth watching'/><author><name>buda</name><uri>http://www.blogger.com/profile/04145572779602673421</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>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6679696301566560047.post-1873886189308470164</id><published>2009-04-07T08:53:00.000-07:00</published><updated>2011-07-15T12:13:19.829-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vim'/><category scheme='http://www.blogger.com/atom/ns#' term='TopCoder'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>Vim C++ macro-like expansion script</title><content type='html'>Hi again!&lt;br /&gt;&lt;br /&gt;Today I'll release a Vim script I wrote a few weeks ago (and have been planing to write for a long time). What it does is enable fast typing of idiomatic things like for loops, STL container declarations etc. The philosophy behind using a script like this is in line with the general philosophy of Vim, which is to make editing as fast as possible (fewest keystrokes to achieve a result). Also, writing idiomatic code is known to be error prone (ever typed ++i in an inner loop instead of ++j?) and is definitely tedious.&lt;br /&gt;&lt;br /&gt;Another reason for writing this script are &lt;a href="http://www.topcoder.com/tc"&gt;TopCoder&lt;/a&gt; competitions. Unlike most algorithm competitions, at TopCoder speed is a big factor. You only have 75 mintes to solve 3 problems (of increasing difficulty) and your submissions are timed from the moment you open the problem statement. Also, there is no partial credit for problems. After the coding phase, there's a short intermission and then a 15 minute challenge phase where other coders get a chance to view your source code and construct legal inputs that will break it (thus getting additional points for themselves and bringing your point total for that problem to 0). Finally, if your code survives the challenge phase, it has to pass all the automated system tests (some of which are "random", and some of which are specifically constructed to trip up wrong approaches). Some people at TopCoder use macros to achieve pretty much the same effect as this script. The main problem I have with this option is that it makes the code look ugly (sort of obfuscated). This makes it unnecesarilly hard for other people to challenge (although that's probably not the main intention) and, more importantly, it's bad style. Of course, using this script (or the macro method) probably won't increase your TopCoder rating; TopCoder algorithm competitions are primarily about quicky inventing (or applying) the correct algorithm, and the implementing it correctly and with reasonable efficiency. Still, being able to type code faster is always a good thing :).&lt;br /&gt;&lt;br /&gt;So let me finally give you a short tour of what exaclty the script does (for the full list, see the comment on top of the file). The current functionality can be seperated into two groups: loop/block expansion and containers and type expansions.&lt;br /&gt;&lt;br /&gt;Very often, you'll want to loop through an STL container, or repeat something n times. To do this, you'll write something like this:&lt;br /&gt;&lt;pre name="code" class="cpp"&gt;&lt;br /&gt;for (int i=0; i&amp;lt;(int)my_vec.size(); ++i) {&lt;br /&gt;  // per-item code goes here&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that in "real" code you might use &lt;code&gt;size_t&lt;/code&gt; or, better yet, &lt;code&gt;vector&amp;lt;int&amp;gt;::size_type&lt;/code&gt;. Also notice the &lt;code&gt;int&lt;/code&gt; cast on the container size. Comparing a signed to an unsigned value is not entirely safe in C++ (The &lt;code&gt;int&lt;/code&gt; gets converted to an &lt;code&gt;unsigned&lt;/code&gt; (assuming &lt;code&gt;vector&amp;lt;int&amp;gt;::size_type&lt;/code&gt; is &lt;code&gt;size_t&lt;/code&gt; and &lt;code&gt;size_t&lt;/code&gt; is a &lt;code&gt;typedef&lt;/code&gt; for &lt;code&gt;unsigned&lt;/code&gt;, as is common on PCs) in what is called the &lt;i&gt;usual arithmetic conversions&lt;/i&gt;. This can cause problems if the value of the &lt;code&gt;int&lt;/code&gt; is negative, in which case, on a 2s complement machine, becomes a positive number and you get the "wrong answer".). Still, in idiomatic code like this, using a cast is an OK option IMO.&lt;br /&gt;&lt;br /&gt;Anyway, to write the above loop with this script, you'd write:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;@f i #my_vec&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;and press &amp;lt;F2&amp;gt; (I'll talk about the keyboard mappings in a sec). Vim will then expand the line to the above code (without the &lt;code&gt;// per-item code goes here&lt;/code&gt; comment, of course :) and (if you were in insert mode) position the cursor at the "right" place (one indent level inside the block) so you can continue hacking.&lt;br /&gt;&lt;br /&gt;If you want to loop to a value (or variable), and not trough a container, you'd write something like this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;@f i n&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;and get&lt;br /&gt;&lt;pre name="code" class="cpp"&gt;&lt;br /&gt;for (int i=0; i&amp;lt;n; ++i) {&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You probably guessed it, but the general syntax is:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;@f index_var_name upper_limit&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Where the upper limit can be preceded by a &lt;code&gt;#&lt;/code&gt; to produce the size of a container.&lt;br /&gt;&lt;br /&gt;If you want the loop condition to be less than or equal, prefix the upper limit with an equals sign like:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;@f index_var_name =upper_limit&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;There's also a version that lets you specify a non-zero lower limit&lt;br /&gt;&lt;code&gt;&lt;br /&gt;@f index_var_name lower_limit upper_limit&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;and versions for looping downward&lt;br /&gt;&lt;code&gt;&lt;br /&gt;@fd index_var_name [lower_limit] upper_limit&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;(the square brackets indicate that the &lt;code&gt;lower_limit&lt;/code&gt; is optional).&lt;br /&gt;&lt;br /&gt;Finally, there are similar expressions for &lt;code&gt;while&lt;/code&gt; and &lt;code&gt;do-while&lt;/code&gt; loops, as well as for &lt;code&gt;if&lt;/code&gt; branches:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;@w expression&lt;br /&gt;@d expression&lt;br /&gt;@i expression&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Finally, there is also support for &lt;code&gt;for&lt;/code&gt; loops with iterators through containers. The syntax for this is (I'll explain what &lt;code&gt;&amp;lt;container_expression&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;expanded_container_expression&amp;gt;&lt;/code&gt; are in the next paragraph):&lt;br /&gt;&lt;code&gt;&lt;br /&gt;@iter iter_name &amp;lt;container_expression&amp;gt; container_name&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;which generates&lt;br /&gt;&lt;pre name="code" class="cpp"&gt;&lt;br /&gt;for (&amp;lt;expanded_container_expression&amp;gt;::iterator iter_name=container_name.begin(); iter_name!=container_name.end(); ++iter_name) {&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;There's also a &lt;code&gt;@iterc&lt;/code&gt; version that generates a &lt;code&gt;::const_iterator&lt;/code&gt; iteration.&lt;br /&gt;&lt;br /&gt;The second part of the functionality is container and type expansions. Basically, for:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;@vi&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;(and &amp;lt;F2&amp;gt;) you get:&lt;br /&gt;&lt;pre name="code" class="cpp"&gt;&lt;br /&gt;vector&amp;lt;int&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This works in all parts of the line (except in double quotes and comments), unlike the loop/block expansions that only work on the start of lines (modulo whitespace characters). I won't list all the supported expansions, but all the &lt;code&gt;vector&lt;/code&gt;, &lt;code&gt;set&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt; and &lt;code&gt;pair&lt;/code&gt; that I tend to use frequently are supported. A few examples:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;@vvi&lt;br /&gt;@sd&lt;br /&gt;@msi&lt;br /&gt;@pllll&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;expands to:&lt;br /&gt;&lt;pre name="code" class="cpp"&gt;&lt;br /&gt;vector&amp;lt; vector&amp;lt;int&amp;gt; &amp;gt;&lt;br /&gt;set&amp;lt;double&amp;gt;&lt;br /&gt;map&amp;lt;string, int&amp;gt;&lt;br /&gt;pair&amp;lt;long long, long long&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Keyboard mappings are defined at the end of the script (so you can easily change it, if you like).&lt;br /&gt;&lt;code&gt;&lt;br /&gt;nmap &amp;lt;F2&amp;gt; :call BudaCppExpand()&amp;lt;Enter&amp;gt;&lt;br /&gt;imap &amp;lt;F2&amp;gt; &amp;lt;Esc&amp;gt;:call BudaCppExpand()&amp;lt;Enter&amp;gt;A&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I have some further ideas that I'm going to add in the short term. Since this post has gotten very long, I won't discuss them here except to say that you can read about them in the comment on top of the script :).&lt;br /&gt;&lt;br /&gt;One important thing in Vim is&lt;a href="http://video.google.com/videoplay?docid=2538831956647446078"&gt; making a habit&lt;/a&gt; out of things (so you don't have to think about whether or not you're going to press 'i' or 'a' or 'A' etc.). Since this script is pretty new I still haven't really gotten into the habit of using it as much as I'd like, but I'm trying :).&lt;br /&gt;&lt;br /&gt;Without further ado, you can get the script &lt;a href="http://dl.dropbox.com/u/5412078/blog/c_expansion.vim"&gt;here&lt;/a&gt;. To use it, you can put it into the ftplugins Vim directory.&lt;br /&gt;&lt;br /&gt;If you find the script useful, have any suggestions about improvements and possible further additions or find a bug, please let me know!&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;Edit:&lt;br /&gt;While writing this post, I noticed that it might be useful (and in line with the style of the script) to be able to expand things after &lt;code&gt;} else&lt;/code&gt; to form &lt;code&gt;if/else&lt;/code&gt; blocks properly which wasn't possible with the version I posted. I fixed that now so you should be able to do things like&lt;/i&gt;&lt;br /&gt;&lt;pre name="code" class="cpp"&gt;&lt;br /&gt;if (a &gt; b) {&lt;br /&gt;  // do something&lt;br /&gt;} else @i a+b+c &gt; 42&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;i&gt;and get it expanded into&lt;/i&gt;&lt;br /&gt;&lt;pre name="code" class="cpp"&gt;&lt;br /&gt;if (a &gt; b) {&lt;br /&gt;  // do something&lt;br /&gt;} else if (a+b+c &gt; 42) {&lt;br /&gt;  &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/6679696301566560047-1873886189308470164?l=cs-haven.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cs-haven.blogspot.com/feeds/1873886189308470164/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cs-haven.blogspot.com/2009/04/vim-c-macro-like-expansion-script.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/1873886189308470164'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/1873886189308470164'/><link rel='alternate' type='text/html' href='http://cs-haven.blogspot.com/2009/04/vim-c-macro-like-expansion-script.html' title='Vim C++ macro-like expansion script'/><author><name>buda</name><uri>http://www.blogger.com/profile/04145572779602673421</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-6679696301566560047.post-8984669199062398227</id><published>2009-04-06T03:34:00.000-07:00</published><updated>2009-04-08T02:18:51.541-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='misc'/><title type='text'>Getting started</title><content type='html'>Hi there!&lt;br /&gt;&lt;br /&gt;This is my first blog post ever, and I'll use to to introduce myself and talk a bit about what I plan to write about and why. Unfortunately, it will probably be a bit dry, but I have to start somewhere :)&lt;br /&gt;&lt;br /&gt;I'm a 24 year old Research Assistant and PhD student at the &lt;a href="http://www.fer.hr/en"&gt;School of Electrical Engineering and Computer Science&lt;/a&gt;, University of Zagreb, Croatia in the Computer Science department. I graduated about a year ago and shared the "student of the generation" award with another colleague in the CS department. During college, I took part in several software projects, most notably in the design and implementation of a SmartHome system for Microsoft's Imagine Cup 2007, and in the Ericsson Nikola Tesla (the Croatian branch of Ericsson) Summer Camp 2007 where I helped implement a two way SIP/SOAP gateway for general purpose SIP/SOAP integration (primarily to enable SIP-aware mobile devices to consume Web Services on the Internet).&lt;br /&gt;&lt;br /&gt;Just before graduation, I took part in a 3-month internship at Google HQ in Mountain View, CA where I worked in the OpenSocial group. If you're not familiar with &lt;a href="http://www.opensocial.org/"&gt;OpenSocial&lt;/a&gt;, it's basically a social networking platform backed and developed by Google, Yahoo!, MySpace, hi5 and a bunch of other social network sites (pretty much anyone that's not Facebook). My time at Google was probably one of the best times in my life. The work experience there is really nothing like anything I've had a chance to experience before (or since).&lt;br /&gt;&lt;br /&gt;I try to keep my interests broad, but if I had to choose just a few (professional ones), it would have to be distributed systems, Web technologies, algorithm design and analysis, discrete math, programming languages and compilers, and complexity theory (still pretty broad :). Most of these coincide really well with the University classes I'm a TA on. I currently work on the &lt;a href="http://geppeto.fer.hr/"&gt;Geppeto&lt;/a&gt; project in the &lt;a href="http://ccl.fer.hr/"&gt;Consumer Computing Lab&lt;/a&gt; at my University. Geppeto is basically a Gadget composition tool designed for consumers (i.e. people with no specialist knowledge about computer programming and Web technologies). If you're using &lt;a href="http://www.google.com/ig"&gt;iGoogle&lt;/a&gt; and Firefox 3, you can &lt;a href="http://geppeto.fer.hr/install.html"&gt;install&lt;/a&gt; the current version of Geppeto and see what it's all about.&lt;br /&gt;&lt;br /&gt;When I'm not working, I enyoj solving algorithmic problems on sites like &lt;a href="http://www.topcoder.com/tc"&gt;TopCoder&lt;/a&gt;. Unfortunately, I rarely get a chance to compete in online events, but they give access to all the problems and automatic testing of solutions after each contest. The community is also really awesome, and all the problems get editorials that discuss how the problem can be solved which can be helpful if you get stuck.&lt;br /&gt;&lt;br /&gt;So, after covering the boring bits, I'll set out the plan for this blog. Basically, I'll try to release code snippets for doing various useful stuff (Vim scripts, algorithm/data structure implementations, WoW addons etc.). I also plan to do pretty regular book reviews on the relevant CS/programming/math book I've read. Finding good reviews online is hard, and I feel they can really be useful since buying and reading a bad book is a big waste of time. Finally, I'll write about all sorts of stuff I stumble upon that might be interesting.&lt;br /&gt;&lt;br /&gt;That's it for my first post! Take care :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6679696301566560047-8984669199062398227?l=cs-haven.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cs-haven.blogspot.com/feeds/8984669199062398227/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cs-haven.blogspot.com/2009/04/getting-started.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/8984669199062398227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6679696301566560047/posts/default/8984669199062398227'/><link rel='alternate' type='text/html' href='http://cs-haven.blogspot.com/2009/04/getting-started.html' title='Getting started'/><author><name>buda</name><uri>http://www.blogger.com/profile/04145572779602673421</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>
