Profile cover photo
Profile photo
Igor Naverniouk
Igor's posts

Post has attachment

Eddie and Midge are brother and sister. They love solving jigsaw puzzles together. Little Eddie really enjoys putting together corner and edge pieces to make borders. Midge lets her her younger brother do that while she works on the remaining middle pieces -- those that do not have any straight edges. At the end, they put Midge's completed chunk inside of Eddie's border and finish the puzzle. Teamwork!

For fairness, they only have puzzles whose pieces can be evenly split -- with Eddie and Midge getting the same number of pieces to work on. That way, one rarely has to wait for the other to finish.

Tonight, the parents need some quiet time, so they took all of the puzzles, shuffled them all together, and made a pile of pieces -- 372 in total -- in the middle of Eddie and Midge's room. That'll take 'em a while to finish!

How many empty jigsaw puzzle boxes are on the floor next to the pile of pieces?

Post has attachment
Post-it notes plus time.

Post has attachment

Google Code Jam 2016 Qualification Round has begun! We have some fun problems this year, as usual.

Post has attachment
After hearing a lot about the Rust programming language, I decided to spend a weekend learning it. Here are some of my first impressions, from the point of view of a professional systems programmer who knows a few programming languages, loves C++ and Python, but isn't a languages expert. So take this with a grain of bias.

Overall, I like it a lot more than Go. Both languages attempt to do the same thing -- replace C++. Go has already admitted defeat in that endeavor (see Rob Pike's post called "Less is exponentially more"; hint -- it isn't). Rust is still trying. The D language is another contender, but I don't know enough about it to comment on its chances.

Here are some things that Rust gets right in that regard, in my opinion. First, no garbage collector. You, the programmer, decide when memory is freed. Explicit memory management has always been my favourite feature of C++, and Rust agrees. The main benefit is a tiny runtime library, which means that Rust programs are typically small, fast, and simple. Rust borrows C++'s principle of "you pay for what you need and not much else." Great!

Next, you get generics. For real. Go's answer to generics is either "we're still working on those" or "you don't really need them", depending on who you ask. To me, it seems that they've had plenty of time to design those already, so the reality is -- they are probably not coming. And for a strongly-typed language, not having generics is rather unacceptable. In Rust, you can sort a vector of 64-bit integers using a simple call to .sort(). In Go, you have to implement 4 global functions. I wish I was joking.

Interfaces are an interesting feature of Go. A type implements an interface if it has the necessary methods. No explicit declaration is necessary. That's a little weird, and although Go loves to brag about this feature, I really don't see the point. In C++, I've never experienced the dire need to have a class I don't own implement an interface that I like. Maybe that's because I tend to work on a giant, monolithic code base, where I can edit all of my dependencies, if necessary. But I've never really had to do that either. So I've never bought into Go's idea of "imposable" interfaces being cool. Rust has traits, which are pretty much the same thing, but you have to explicitly declare them, which seems fine to me.

Now on to concurrency. Go's goroutines and channels are pretty sweet. Rust has those, too, but the syntax isn't nearly as cute because in Rust they aren't part of the language itself -- they are a part of the standard library. I can see both sides of the argument here. Multi-threading is what systems programming is all about these days, and Go's decision to bake it into the language is a strong statement that makes a lot of sense. Rust's approach is to double down on its core principle of minimalism and declare that these are things that don't absolutely have to be part of the language and can be adequately handled by the standard library. That's sensible, too. If I had to pick a winner, this one goes to Go, in my opinion. Threads and channels are useful enough that I'd be willing to pay for them in every program I write, if it saves me some code clarity when I do need them.

Now on to Rust's main claim to fame -- explicit ownership tracking. That really is the feature that explains Rust's existence. Every piece of memory has an owner, and this ownership is tracked by the compiler, which turns many run-time errors into compile-time errors. Problems like iterator invalidation and dangling pointers are declaratively forbidden by the Rust compiler. The way this is done is by imposing immutability as a default, and tracking all mutable and immutable references to objects at compile time. Rust replaces C++'s 'const' with a subtly different concept of 'mut'.

My verdict is -- I'm not buying it. I'm a big fan of 'const', and I didn't like that Java got rid of it in favour of a mostly useless 'final'. Rust's immutability rules are very strict, so much so that most beginner Rust programmers spend a lot of their time fighting the compiler just so they can get get some basic things done. And the canonical examples that the official Rust docs cite as reasons for these draconian rules don't convince me that the strictness is worth the pain. Iterator invalidation and dangling references are real problems, but they are generally quite rare, and C++ compilers are quite good at catching them. And even when compilers do fail, these errors tend to be quite obvious in practice -- your most basic unit tests will crash, and you'll fix the bug pretty quickly.

Rust's standard library introduces some complicated concepts like Box and Cell, just to work around its own strict rules that govern memory ownership. So in practice, lots of Rust code engages in all kinds of shenanigans behind the scenes, making it look as if mutability rules are working as intended, while in reality, memory is being mutated all over the place. It's a bit like saying in C++ that everything is 'const', but using 'mutable' behind the scenes everywhere -- you can smile while describing your code, but you know deep down that you're just lying to yourself.

And finally, I come to the worst thing about Rust, in my opinion -- its standard library. The standard library is extremely important to the survival of a language. Experienced programmers choose programming languages based on just two things, really -- what their coworkers know, and whether the standard library helps solve the problem at hand. While playing around with the language, I tried implementing just two simple things, and I ran into serious issues with both.

First, I wanted to implement Go's canonical thread-and-channel example -- create 100,000 threads and pass an integer between all of them, in a chain, adding one to the integer in each thread. Go likes to brag about being able to do this at lightning speed. Rust can't quite do 100,000 threads with a channel between each pair of adjacent threads, but it can do 30,000 in under a second. At 40,000, it crashes with a memory error. That's quite good, but  here is the problem I ran into. To test various chain lengths, I wanted to make the number of threads a command line parameter. It was easy enough to find a StackOverflow post on the topic of command line arguments, and it pointed me to the 'docopt' crate (crates are Rust's packages). Installing the crate was beautifully simple, but the thing didn't work at all. After falling into the rabbit hole of dependencies, I eventually gave up trying to use named command line arguments using 'docopt' and went back to parsing the command line somewhat manually using 'env::args". That wasn't a big deal -- maybe 'docopt' was just a badly maintained package.

But the pattern repeated itself when I tried writing my next program -- a trivially simple HTTP web server. All I wanted to do is serve a static HTML string in response to a GET request. I went to to look for an HTTP server crate, and found a crate called 'hyper'. Once again, installing and using it was trivially simple. Great! But when I copied the very first example from the docs and tried to run it, I got a crash inside of a C compiler inside a file called openssl_shim.c: "openssl/hmac.h: No such file or directory". Sigh. Now what? Evidently, 70,000 people have downloaded the 'hyper' crate before. I'm assuming that most of them are successfully using it.

Of course, StackOverflow solves everything -- I just had to apt-get install openssl-dev, but that's not cool at all. I could not have possibly known that a Rust package would need a rather obscure Debian package to be installed on my system. That kind of stuff doesn't fill me with confidence that Rust crates are as self-contained as they claim to be. That's zero for two on crates so far.

After I fixed the dependency error, I got the program to start, but I couldn't access the server from anywhere but 'localhost'. I had to change the http() IP address parameter to my computer's network IP address to make that work. The 'hyper' docs say nothing about this.

So overall, judging by my minuscule sample of just two crates, Rust's package library needs a lot of work. Maybe I just happened to download two of the worse crates, but how could I possibly have known which other ones I should have downloaded instead?

In conclusion, I love the language design principles. I think that Rust made a few correct decisions where Go had gone the wrong way. The memory ownership management system doesn't thrill me, but I can see myself getting used to its pain. It's the that is my least favourite feature of Rust so far, but it has to improve over time -- if a language has to have a problem, that's the best kind of problem to have. It's also an extremely important problem to have. I'm one of those crazy people who think that C++ is the best language invented so far, as long as you know which parts to use and which ones to avoid. The thing about C++ that desperately needs an improvement though is discoverability of packages, and if Rust does that part right, it could be the language that wins the post-C++ battle. No one has won that battle so far.

As I was backing up an old hard drive, I found old notes from medical research I once did on myself.

In early 2009, I started having occasional headaches, once or twice a month. Some were quite severe. So I started keeping diaries for days when I had headaches, in hopes of identifying a pattern and finding a cause. Here are those notes.

  1 Sunday, March 29, 2009.
  2 - 11:00 woke up
  3 - bad food for lunch
  4 - minigolf
  5 - ice cream
  6 - hike in Saratoga
  7 - headache
  8 - lots of Turkish food
  9 - bad headache
 10 - 2 episodes of Lost
 11 - 23:30 very bad headache
 13 Sunday, April 5, 2009.
 14 - 10:00 woke up
 15 - 2 mandarin oranges
 16 - 3 hour hike in Castle Rock
 17 - mild headache
 18 - bad food for lunch
 19 - ice cream
 20 - headache
 21 - movie, 2 episodes of Lost
 22 - bad headache
 23 - Indian food, bubble tea
 24 - headache
 26 Sunday, April 19, 2009.
 27 - 8:40 woke up
 28 - TC SRM
 29 - Frankfurters and milk for breakfast
 30 - mini golf in 30-degree heat
 31 - smoothies and ice cream
 32 - 4 episodes of Lost
 33 - headache
 34 - french food
 35 - 21:00 bad headache
 37 Saturday, August 15, 2009.
 38 - 10:30 woke up
 39 - banana and apple juice for breakfast
 40 - 2.5 hours of volleyball in scorching heat
 41 - lunch at Chevy's, including 2 margaritas
 42 - mild headache
 43 - stuff
 44 - mild headache
 46 Saturday, September 5, 2009
 47 - 11:00 woke up
 48 - banana for breakfast
 49 - some house cleaning with Clorox
 50 - lunch at Pasta?
 51 - some more house cleaning
 52 - mild headache
 53 - That 70s Show
 54 - fried potatoes, ice cream, smoothie
 55 - Magnolia
 56 - bad headache
 58 Sunday, October 11, 2009
 59 - 13:00 woke up
 60 - chocolate mousse
 61 - halibut for lunch
 62 - mini golf under the sun
 63 - more chocolate mousse
 64 - mild headache
 65 - Grey's anatomy
 66 - bad headache
 67 - beef and rice for dinner
 68 - more Grey's anatomy and Pushing Daisies
 69 - a fucker of a headache
 71 Saturday, November 14, 2009
 72 - 12:10 woke up
 73 - Pasta?
 74 - open house
 75 - grocery shopping
 76 - Civ Rev
 77 - cooking
 78 - pork and mashed potatoes
 79 - headache
 80 - American Psycho
 81 - bad headache
 82 - turned off the lights, IYKWIM
 83 - mild headache
 85 Saturday, January 16, 2010
 86 - 8:30 woke up
 87 - banana
 88 - 10:00-12:45 volleyball
 89 - shower
 90 - Pasta?
 91 - shopping at a crowded Walmart
 92 - headache
 93 - cleaning
 94 - 2 hours alone in the dark
 95 - mild headache
 96 - Mad About You, Friends
 98 Saturday, March 27, 2010
 99 - 12:00 woke up
100 - stuff
101 - mild headache
102 - stuff
103 - better

There were certainly patterns that appeared eventually -- lots of desserts, lots of time spent outside in the sun, lots of TV watching. But it took me a whole year to finally see the main clue -- I only got headaches on weekends! How could that possibly be relevant?

The jump from there wasn't obvious, but when I saw it, it was a real epiphany. I drink coffee every morning at work, on week days. And I almost never drink soft, carbonated drinks. I do have tea at home occasionally on weekends, but not every day. Could it be caffeine withdrawal?

Next time I got a headache, I made myself a cup of strong coffee, and the headache disappeared almost immediately. It worked like magic. Since then, I have been drinking coffee every morning, and I haven't had a headache like that since.

Post has attachment
Google Code Jam live stream is here:

Post has attachment
Richard Feynman's 1985 lecture on computer science. It's fascinating to watch it now, when we already know the answers to all of the questions he was wondering about at the time -- can computers beat humans at chess? can computers recognize patterns in images? is machine learning just a fun curiosity or a huge breakthrough? And of course, Feynman being the genius that he was, he gets the answers to all of these questions exactly right.

Post has attachment
Backyard visitor. We have a tall fence all around, so the opossum must have climbed it.
Wait while more posts are being loaded