Showing posts with label jokes. Show all posts
Showing posts with label jokes. Show all posts

Wednesday, September 23, 2009

A Professional Technical Conversation

Me: I need to determine if an executable is in my path. So I use which...
Old Sk00l Unix Guru #1: Right.
Old Sk00l Unix Guru #2: Right.
Me: But I need to do it from a script, so I'm checking the exit code....
OSUG #1: Right.
OSUG #2: Right.
Me: And that works great on Linux. But on Solaris, it's 0 on both success and failure.
OSUG #1: Can't you just put it in backticks and grep the output?
Me: Well sure, I can. But it seems like such an old utility should have a way to return 'yes' or 'no'. What's the Old Sk00l UNIX Way to do this?

*all three characters pore over Solaris man page, which was last updated in 1992*

Me: I guess I'll do that. I just wanted to be sure that if I did the backtick and grep thing, someone isn't going to look at that later and say "what a n00b".
OSUG #1: You can write a comment that says "let me know if you have a better way".
OSUG #2: Or "to overcome braindead Solaris return code values".
Me: I guess leaving a comment about someone being braindead IS the Old Sk00l UNIX Way.

Sunday, August 30, 2009

Invention Idea #6

My office kitchen fridge has an incredible profusion of soda cans. (As an aside, I don't understand why: If you want it cold, just buy it from the machine right before you drink it. If you brought it from home to save money, you should be buying it in 2L bottles, not cans.)

Many cans are unlabeled, but some have a name scrawled on them, or some tape, or a business card stuck under the tab. However, these solutions have a couple problems. First, they only provide identification, not security. Second, some of these are kind of time-consuming. The tape, for instance, can't take less than 60-90 precious seconds during which you could be reading some hilarious emails forwarded from the secretary.

Thus my invention, which I call "Club Soda". You slip it on, snap it shut and club it with a tiny key. It would be personalized with your name via a tag or engraving or something. Security and identification in under 10 seconds. MSRP $4.99.

Wednesday, September 10, 2008

New Control Structure Considered Useful

We have a large data processing problem at work. Basically, we get thousands of items every day and have to figure out which ones go together. The only way to know if they go together is to try them. Some items may not go with anything, some may fit with a hundred or more other items. The one nice thing is that once we've found 3-5 items that go together, we can zip through all the other members of the group.

The problem is finding those 3-5 items. Choosing every possible combination of 5 would take too long. Choosing every combination of 3 is fast enough, but leaves a lot of extras. The simple solution is to first try all the combos of 3, then try all the combos of 4 on the remainder, then try all the combos of 5 on the remainder of that. The smaller and smaller pile makes the larger and larger choices feasible.

My boss, who is a competent practical programmer, suggests we have 3 procedures: One that does a 3 nested loop, one that does a 4, and one that does a 5. Like this (in Tcl):

set items {apple orange banana grape strawberry}
set count 5

for {set i 0} {$i < $count} {incr i} {
    for {set j [expr $i + 1]} {$j < $count} {incr j} {
       for {set k [expr $j + 1]} {$k < $count} {incr k} {
         set string [lindex $items $i]
         lappend string [lindex $items $j]
         lappend string [lindex $items $k]
         puts $string
       }
    }
}

That's just the 3 level loop because the other two look almost the same. The 4 and 5 level loops are identical except for having additional levels. As a programmer who values elegance over readability, the phrase "identical except for" is a red flag. Why have 3 separate procedures when all you are adjusting is a single parameter? What I need is a new control structure that is basically a for loop but lets me control how many nested fors there are.

Tcl makes it easy to create new control structures. Here's the control structure definition:

# Usage:
#  indexcount - how many items are being chosen
#  itemcount  - how many items are being chosen from
#  indexvar   - variable to hold current combination of indexes
#  body       - code to execute for each combination
proc chooseloop {indexcount itemcount indexvar body} {

    if {$indexcount > $itemcount} { 
      error "More indexes than items"
    }

    if {$indexcount == 0} { return }

    set indexes {}
    for {set i 0} {$i < $indexcount} {incr i} {
       lappend indexes $i
    }

    set maxindexval [expr $itemcount - 1]

    while {1} {
 
       # make new body that sets indexvar first
       set newbody "set $indexvar {$indexes}\n$body"

       # do this iteration
       uplevel 1 [list eval $newbody]

       # find incrementable index
       set found no
       for {set i 0} {$i < $indexcount} {incr i} {
          set index [lindex $indexes end-$i]
          set thismax [expr $maxindexval - $i]
          if {$index < $thismax} {
             set found yes
             break
          }
       }

       if {!$found} { break }

       # increment this index and set all following ones
       set incrindex [expr ($indexcount - 1) - $i]
       set precedingval [lindex $indexes $incrindex]
       for {set j $incrindex} {$j < $indexcount} {incr j} {
          lset indexes $j [expr $precedingval + 1]
          set precedingval [lindex $indexes $j]
       }
    }
}

Now to get my 3 level loop, I can call like this:

chooseloop 3 5 indexes {
    set str ""
    foreach index $indexes {
       append str "[lindex $items $index] "
    }
    puts $str
}

In order to do 3, then 4, then 5, I can call like this:

for {set i 3} {$i < 6} {incr i} {
    chooseloop $i 5 indexes {
       set str ""
       foreach index $indexes {
          append str "[lindex $items $index] "
       }
       puts $str
    }
    puts "--"
}

The output of that last one is:

apple orange banana 
apple orange grape 
apple orange strawberry 
apple banana grape 
apple banana strawberry 
apple grape strawberry 
orange banana grape 
orange banana strawberry 
orange grape strawberry 
banana grape strawberry 
--
apple orange banana grape 
apple orange banana strawberry 
apple orange grape strawberry 
apple banana grape strawberry 
orange banana grape strawberry 
--
apple orange banana grape strawberry 
--