October 2007 Archives

My dad made up a bunch of dulce de leche a while back; if you're going to boil one can, you might as well fill the pot. For those who don't know, the easiest way to make dulce de leche, a caramelized milk product popular in South and Central America, is to boil a can of sweetened condensed milk for two to three hours. At the shorter end of that range, you'll end up with viscosity similar to a caramel syrup; longer and it turns into a thick, spreadable paste, not unlike Nutella.

I have seen numerous references on the internet of people not wanting to boil a can for fear of it exploding, but this trepidation is unfounded - boiling is a normal part of the canning process. The contents of the can are put in, the can is sealed and then it is brought to 100°C or even hotter to sterilize the elements within. Leaving a can in boiling water on the stove is perfectly safe, assuming the pan doesn't run dry, the water will keep the system, can included, from breaking the boiling point. That's just basic thermodynamics. As mentioned previously, it's worthwhile to boil a few cans at once, since the energy expenditure of keeping a pot simmering on the stove is nearly identical.

To make the ice cream, combine these ingredients and toss it into your ice cream maker:

1 can sweetened condensed milk
1 can dulce de leche
1 cup heavy cream
2 cups milk
Vanilla to taste (1-3 teaspoons)

I used thick (3 hour) dulce de leche, which lends a very strong flavor and skim milk, because it was in the fridge. To get everything to combine, I had to stir it on the stove for about 10 minutes. Don't just let milk sit on the stove unstirred, however; it grows a nasty skin quite quickly. If you don't have another can of sweetened condensed milk, it can be replaced by another cup of cream, a half cup of milk and a cup of sugar.

Code Golf

| 1 Comment | No TrackBacks

I stumbled across a code golf earlier this week that offers numerous problems. The specific challenge I came across was the fizz buzz problem that I had been introduced to a few weeks ago.

My initial attempt in Perl was this:

for (1..100) {
    $a = "";
    $a = "Fizz" if !($_ % 3);

    if (!($_ % 5)) {
        $a .= "Buzz"
    } elsif ($_ % 3) {
        $a = $_
    }

    print "$a\n"
}

Nothing special at all, just some fairly tight, clean code. Aside from the broken apart if block and the use of bad variable names ($a, $_) it wouldn't look out of place in a normal program. After exhausting my knowledge of esoteric Perl, I whittled it down to this:

for (1..100) {
    $a = ($_ % 3) ? "" : "Fizz";
    $a .= "Buzz" if !($_ % 5);

    $a ||= $_;

    print "$a\n"
}

With a bit of digging, I found that I could use the + and , operators as part of print to get rid of that $a assignment:

for (1..100) {
    $a = ($_ % 3) ? "" : "Fizz";
    $a .= "Buzz" if !($_ % 5);

    print + $a || $_, "\n"
}

But you certainly don't need most of the parenthesis, and Perl deals with barewords just fine:

for (1..100) {
    $a = $_ % 3 ? "" : Fizz;
    $a .= Buzz if !($_ % 5);

    print + $a || $_, "\n"
}

Finally, after reading through perlvar I found that the input record separator, which defaults to "\n", can take the place of that four-character newline:

for (1..100) {
    $a = $_ % 3 ? "" : Fizz;
    $a .= Buzz if !($_ % 5);

    print + $a || $_, $/
}

101 characters, but you can go a step further, drop the $a assignment and condense those statements down below:

for (1..100) {
    print + ($_ % 3 ? "" : Fizz) . ($_ % 5 ? "" : Buzz) || $_, $/
}

Finally, since this is now a single Perl statement, the curly braces can be eliminated by placing the loop control at the end (thanks to Fotios for that tip). After you beat the whitespace out, you end up with 56 characters:

print+($_%3?"":Fizz).($_%5?"":Buzz)||$_,$/for(1..100)

Q.E.D.

It was widely reported yesterday that Microsoft bought a 1.6% stake in Facebook for $240 million, thereby valuing the company at $15 billion. Sure getting in on such a huge cache of advertising-ready eyeballs and consumer data is worth a lot, but the bid puts a price of $357 on each of Facebook's 42 million accounts. Marketplace's coverage put that number at $300 dollars, which takes into account Facebook's projection of 50 million accounts by the end of the year. Beyond that, however, is the fact that an account doesn't necessarily mean a user; nothing stopped me from creating a Facebook page for the Pope and I know that Jesus isn't actually my friend. Furthermore, not all registered users regularly use the site. I would bet that more than a quarter of my friends use facebook less than once a month, and even then only for a handful of page views (no, I don't want to be your super-best-buddy). If we take my brash generalization at face value, leaving 30 million active users, they are each worth $500. Do you really think you see $500 worth of ads on Facebook?

Data::Dumper

| No Comments | No TrackBacks

Data::Dumper is one of the most useful Perl modules when developing code, providing quick and easy access to the contents of data structures. Are you unsure whether you're setting the values of a hash correctly? Don't understand how someone has organized an object that you're 'use'ing? Data::Dumper to the rescue.

use Data::Dumper;

my %foo;
$foo{'bar'} = 'This is bar';
$foo{'baz'}{'foo'} = 'This is foo, stored under baz in %foo';
$foo{'qux'} = 'This is qux';

print "The hash '%foo' looks like this:\n";
print Dumper(\%foo);

When executed:

The hash '%foo' looks like this:
$VAR1 = {
          'bar' => 'This is bar',
          'baz' => {
                     'foo' => 'This is foo, stored under baz in %foo'
                   },
          'qux' => 'This is qux'
        };

Note that I passed Dumper() a reference to the 'foo' hash by using a backslash, which is what you will want most of the time with anything other than a scalar. Passing a reference causes Dumper() to print the entire variable's contents in the same scope. If you pass 'foo' directly, instead of its reference, you end up with this:

The hash '%foo' looks like this:
$VAR1 = 'bar';
$VAR2 = 'This is bar';
$VAR3 = 'baz';
$VAR4 = {
          'foo' => 'This is foo, stored under baz in %foo'
        };
$VAR5 = 'qux';
$VAR6 = 'This is qux';

Which doesn't make it clear that 'foo' is a hash.

Homemade Carbonator

| No Comments | No TrackBacks

Carbonator thumbnail After reading this instructable I was very excited because I've recently started drinking a lot of seltzer water and I felt silly paying for something so simple. I collected parts from eBay and some online distributors as follows:

  • 15lbs. CO2 tank (eBay, $80 shipped)
  • Regulator (BeverageFactory.com, $45)
  • Carbonator cap (MoreBeer.com, $15)
  • Tubing and adapters (hardware store, $5)
  • Filled CO2 tank (Robert's Oxygen, $25)

It's a pretty simple arrangement, in the end. Just hook the regulator up to the tank along with the tubing to the carbonator cap, adjust the pressure to 50PSI and then fizzy up a bottle of cold water.

I watched some music videos on YouTube today and found that Ska-P do not look at all as I imagined them. Yum!Yum!ORANGE, however, look exactly like my mind pictured.

This is a hack of the script rsnaptar included with the rsnapshot distribution. In short, it takes a few rsnapshot directories, runs them through tar, gzip and gpg finally depositing the results on another machine. I wrote this so that I could grab the backups from a server at work and routinely toss them onto a DVD that I take home with me. It's a bad idea to be walking around with all of the company's source code, hence the GPG. The magic all happens on one line which runs tar, piping the output to ssh which runs gzip reading from stdin on the remote machine then on to gpg dumping its output wherever you want.

#!/bin/sh
SNAPSHOT_DIR="/data/backups/tarback"
DEST_LOCATION="/home/stephensdg/Desktop/backups"

USER=stephensdg
HOST=10.32.193.100
ID_FILE=/home/stephensdg/.ssh/id_dsa
GPG_HOME=/home/stephensdg/.gnupg

LS="/bin/ls"
TAR="/bin/tar"
CAT="/bin/cat"
CHMOD="/bin/chmod"
CHOWN="/bin/chown"
MKDIR="/bin/mkdir"
SSH="/usr/bin/ssh"

cd ${SNAPSHOT_DIR}
for BACKUP_POINT in `${LS} ${SNAPSHOT_DIR}`; do
        ${TAR} -chf - ${BACKUP_POINT}/ | ${SSH} -i ${ID_FILE} ${USER}@${HOST} \
        "gzip - | gpg --homedir ${GPG_HOME} -e -r Drew > \
        ${DEST_LOCATION}/${BACKUP_POINT}.tar.gz.gpg"
done

NetBank Failure

| No Comments | No TrackBacks

NetBank logo It's not every day that you hear about a bank failure. Prior to NetBank's failure on Friday, the last was in February and that was the first in two and a half years. Thanks to the Federal Deposit Insurance Corporation (not to be confused with The Fed), the impact of a bank's dissolution doesn't have much effect on its customers. As detailed in the above-linked FDIC page on the NetBank failure, ING Direct will take over the accounts of NetBank and anyone with deposits less than the FDIC insurance limit won't suffer any loss at all. Those with uninsured deposits (the amount exceeding $100,000) can only expect to see half of that amount:

Due to the projected sale of assets of the former bank, the FDIC is in the position to provide each uninsured depositor with an dividend equal to 50% of your uninsured amount. These funds will be deposited directly into your account net of your uninsured portion.

The lesson? This isn't the depression, but bank failures still happen. If you keep your deposits under the FDIC limit then it's very much a non-issue; if you exceed those limits, you could sustain significant losses. When Metrobank failed last February those with more than $100k at the bank got lucky because the FDIC was able to cover the relatively small amount of exceeding assets fully. In the case of NetBank, the amount of uninsured assets are great enough that the FDIC isn't doing that again.

Pages

About this Archive

This page is an archive of entries from October 2007 listed from newest to oldest.

September 2007 is the previous archive.

November 2007 is the next archive.

Find recent content on the main index or look in the archives to find all content.