Chad Perrin: SOB

28 March 2008

10 steps to 99 bottles: simple program dev 101

Filed under: Geek — Tags: , , , — apotheon @ 12:07

Thinking back, one of the most difficult things for me to really get the hang of at first when I initially started learning to program was how to get off to a good, orderly start when writing a simple program. I’m reminded of this by someone who popped up on the ruby-talk mailing list asking for help with a programming problem presented in Chris Pine’s Learn to Program online tutorial. (Note that page also gives you somewhere to go to buy the book Pine wrote as an “improved, expanded” version of the same idea.)

I figured I should share some of what I’ve learned since then about how to do exactly that — how to start writing a simple program. I’ll use the same programming problem that came up on ruby-talk: something that prints out the lyrics for 99 Bottles of Beer. It probably won’t be the most elegant implementation possible, but it should make the point about how to start writing software, and it’ll stay away from concepts that might be considered “advanced” or are idiomatic of a particular programming language. It will, however, assume that you know some very basic programming syntax.

So, here it is, a step-by-step example of how to start writing a simple program, using Ruby as the example language.

  1. Create the framework of the file. It should look something like this:

      #!/usr/bin/env ruby
    

  2. Come up with your flow control structure. Idiomatic Ruby would probably involve an iterator like each or downto, but we’ll stick with something common to most languages used by beginners — the while loop. There’ll also probably have to be a variable involved:

      #!/usr/bin/env ruby
    
      bottles = 99
    
      while bottles > 0
      end
    

  3. Next, make sure you haven’t broken anything already. Of course, you need some way to indicate that things are working, if only very vaguely. As such, we’ll just make sure that the while loop terminates based on use of the variable, so you know you haven’t written an infinite loop. The following program should just run and end quickly without any output, indicating that your loop is behaving as expected:

      #!/usr/bin/env ruby
    
      bottles = 99
    
      while bottles > 0
        bottles -= 1
      end
    

  4. Now you need to make it actually do something useful. Stick a puts statement in there to print out the first line of each stanza of the song. It should print out “n bottles of beer on the wall,” over and over, where n is a number counting down from 99 to 1.

      #!/usr/bin/env ruby
    
      bottles = 99
    
      while bottles > 0
        puts "#{bottles} bottles of beer on the wall,"
        bottles -= 1
      end
    

  5. Of course, there’s something wrong with saying “1 bottles of beer on the wall,” since “1” doesn’t really conjure up an idea of plurality. We’ll solve the problem of how to generate the correct behavior later, but for now we can at least eliminate the incorrect behavior by having it stop at 2 instead of 1.

      #!/usr/bin/env ruby
    
      bottles = 99
    
      while bottles > 1
        puts "#{bottles} bottles of beer on the wall,"
        bottles -= 1
      end
    

  6. Let’s finish off that while loop so that it does everything we need it to do — print out the rest of each stanza of the song:

      #!/usr/bin/env ruby
    
      bottles = 99
    
      while bottles > 1
        puts "#{bottles} bottles of beer on the wall,"
        puts "#{bottles} bottles of beer,"
        puts "Take one down, pass it around,"
        bottles -= 1
        puts "#{bottles} bottles of beer on the wall!"
      end
    

  7. The last edit to the program reintroduced the singular/plural mismatch, because the last line generated says “1 bottles of beer on the wall!” Let’s just take that last stanza out of the mix, and deal with it separately. Increment your test value by one, again:

      #!/usr/bin/env ruby
    
      bottles = 99
    
      while bottles > 2
        puts "#{bottles} bottles of beer on the wall,"
        puts "#{bottles} bottles of beer,"
        puts "Take one down, pass it around,"
        bottles -= 1
        puts "#{bottles} bottles of beer on the wall!"
      end
    

  8. Unfortunately, the song isn’t quite done. We still need to deal with the special cases we cut out of the while loop. Write something to deal with the last two stanzas:

      #!/usr/bin/env ruby
    
      bottles = 99
    
      while bottles > 2
        puts "#{bottles} bottles of beer on the wall,"
        puts "#{bottles} bottles of beer,"
        puts "Take one down, pass it around,"
        bottles -= 1
        puts "#{bottles} bottles of beer on the wall!"
      end
    
      puts "2 bottles of beer on the wall,"
      puts "2 bottles of beer,"
      puts "Take one down, pass it around,"
      puts "1 more bottle of beer on the wall!"
    
      puts "1 bottle of beer on the awall,"
      puts "Only 1 bottle of beer,"
      puts "Take it down, pass it around,"
      puts "No more bottles of beer on the wall!"
    

  9. Looking at the output, it could be prettier. Add some empty puts statements in there to space out the stanzas:

      #!/usr/bin/env ruby
    
      bottles = 99
    
      while bottles > 2
        puts "#{bottles} bottles of beer on the wall,"
        puts "#{bottles} bottles of beer,"
        puts "Take one down, pass it around,"
        bottles -= 1
        puts "#{bottles} bottles of beer on the wall!"
        puts
      end
    
      puts "2 bottles of beer on the wall,"
      puts "2 bottles of beer,"
      puts "Take one down, pass it around,"
      puts "1 more bottle of beer on the wall!"
    
      puts
    
      puts "1 bottle of beer on the awall,"
      puts "Only 1 bottle of beer,"
      puts "Take it down, pass it around,"
      puts "No more bottles of beer on the wall!"
    

  10. Now that everything works, all we need to do is make a better program out of it. If you learn some programming techniques that can help make the program more easily understood and maintained, or somehow more efficient, they might be useful. Some idiomatic Ruby techniques such as the aforementioned downto iteration method, conditional handling of singularity vs. plurality, and other changes might make for a more elegant solution.
  11. Refactoring your program isn’t necessarily a big deal for a trivial programming problem like this, but this is a great time to practice those techniques so you’ll have a handle on them when you start needing them for more complex problems.

12 March 2008

BecomeAnXcoder — I can has Mac?

Filed under: Geek — Tags: , , , , , — apotheon @ 11:58

BecomeAnXcoder | CocoaLab

I want to learn Objective C. For this, I need something running MacOS X (preferably Leopard-era, or Tiger-era as a second place option). Does anyone care to donate?

Okay, so I’m mostly kidding. Still, it would be cool. . . .

I wonder if this would work with Renaissance, too.

11 March 2008

insomnia and productivity

My insomniac productivity a few days ago wasn’t just geared toward writing lengthy rambles about the differences between various forms of philosophical libertarianism. I also wrote code — in particular, I wrote an entire program from start to finish, inspired by code I found online for doing the same thing that (frankly speaking) sucked.

I wonder why it was such a productive night. As I think about it, I remember that my experience in years past mirrors the stereotype: geeks that stay up all night hacking away at something that totally consumes their attention at the time, producing far more in a couple nights’ work than your average professional does in a month.

The phenomenon has been termed hack mode:

a Zen-like state of total focus on The Problem that may be achieved when one is hacking (this is why every good hacker is part mystic)

More about it, from the same source:

Being yanked out of hack mode (see priority interrupt) may be experienced as a physical shock, and the sensation of being in hack mode is more than a little habituating. The intensity of this experience is probably by itself sufficient explanation for the existence of hackers, and explains why many resist being promoted out of positions where they can code.

Recently, Sterling “Chip” Camden (of Chip’s Quips and Chip’s Tips) recently wrote on the subject of geek productivity. It was cast as consultant productivity, of course, because that’s the sort of geek he is — but it gets into the same concepts as the Jargon File definition of “hack mode”.

Compare his words:

Focus. One reason why IT pros don’t always do so well in social situations is that they have the power to concentrate intently on one problem to the exclusion of everything else. (No, honey, I wasn’t ignoring you — I actually didn’t hear you, even though you were standing right beside me and speaking clearly. I might have even said “uh huh,” but that was just a 202 response.) We geeks need to maximize this ability in order to be effective. We can’t allow ourselves to be interrupted for “just a minute” to answer a question. The instant we break concentration, the entire problem that we were modeling in our head drops on the floor and shatters into a million pieces. This is why you shouldn’t answer the phone, e-mail, or chat during these periods.

. . . with these from the “hack mode” entry at the Jargon Wiki:

Some aspects of hacker etiquette will appear quite odd to an observer unaware of the high value placed on hack mode. For example, if someone appears at your door, it is perfectly okay to hold up a hand (without turning one’s eyes away from the screen) to avoid being interrupted. One may read, type, and interact with the computer for quite some time before further acknowledging the other’s presence (of course, he or she is reciprocally free to leave without a word). The understanding is that you might be in hack mode with a lot of delicate state (sense 2) in your head, and you dare not swap that context out until you have reached a good point to pause.

Crazy-late hours of intensive hacking lend themselves naturally to entering, and sustaining, a deep state of “hack mode”:

  • Other (saner) people aren’t around to interrupt. They’re all asleep. This provides additional safety when juggling eggs.
  • The requirement of keeping from disturbing others inhibits the tendency to engage in distracting entertainments (like TV). This almost forces one to focus entirely on one’s work. Only something like reddit stands in the way.
  • Subjectively speaking, it seems that the wee hours of the morning lend themselves to an almost surreal, abnormal perspective. Inspiration can be found in odd places under that sort of influence — which leads to new ideas coming to mind and being explored that, by the light of day, may have been dismissed immediately as “crazy talk”.

Discovery of these benefits to late nights coupled with the heady experience of “hack mode” itself (it’s like a powerful psychologically addictive drug — really and truly), along with other factors, surely contributes to the increasingly nocturnal and insomniac (sometimes to self destructive extremes) tendencies common in “larval stage“:

a period of monomaniacal concentration on coding apparently passed through by all fledgling hackers. Common symptoms include the perpetration of more than one 36-hour hacking run in a given week; neglect of all other activities including usual basics like food, sleep, and personal hygiene; and a chronic case of advanced bleary-eye. Can last from 6 months to 2 years, the apparent median being around 18 months. A few so afflicted never resume a more `normal’ life, but the ordeal seems to be necessary to produce really wizardly (as opposed to merely competent) programmers.

This makes a lot of sense, considering the fact it generally takes ten years to become a competent programmer. The same is essentially true of anything — it takes ten years’ worth of work to become truly proficient (what the unambitious might call a “master”) in any skill that embodies great technical challenges. It’s not the actual chronological period of ten years that matters, of course — it’s the amount of time and effort invested in learning and practicing the skill that matters. It just observably tends to take about ten years for most people who consistently pursue such skills to reach a level of significant proficiency.

I’m prone to insomnia — it comes and goes, sometimes afflicting me for a week at a time, occasionally longer, sometimes only one night here and there. I try more and more all the time to adopt a more “normal” sleep schedule, but I’m simply not nearly as effective at this as I’d like. The insomnia keeps coming — and the definition of larval stage holds a clue to one of the reasons for it:

A less protracted and intense version of larval stage (typically lasting about a month) may recur when one is learning a new OS or programming language.

This obviously isn’t the sole reason for my bouts with insomnia, or even the primary reason. It is, however, probably a contributing factor.

I don’t think I have a perfect handle on the forces at work, however — even those in my own head. The above-listed benefits can’t be the only reason that, when I allow it, insomnia can be so productive, for instance. It’ll bear more thought.

By the way, the program I wrote was a command-line utility that retrieves currency exchange rate data from the Internet and provides up-to-date translations between currencies. It was inspired by the train wreck of a currency exchange utility I found here. As of this writing, that program I found is hopelessly broken, in addition to being poorly written and essentially unmaintainable — thus my desire to write something better.

All original content Copyright Chad Perrin: Distributed under the terms of the Open Works License