Archive for April, 2006

Find new music: a song a day calendar

Tuesday, April 18th, 2006

So, here we are 108 days into the year and if you haven’t found some new music this year, it is time you check out CC365. It is a song a day calendar featuring exclusively Creative Commons music. Grant Robertson is doing a great job picking a wide selection of tunes: Jazz, electronica, j-pop, hip-hop, country, you name it. And since the artists encourage you to share their music, they don’t find themselves in the awkward position of suing their fans, grandmothers, and 12-year-old girls or installing hacker’s tools on your computer.

Free Music Daily - Indieish.com

Perplex City

Monday, April 17th, 2006

Last month, TR bought a Perplex City starter kit for my wife and I. What a cool game! There are so many levels you can play at. You can solve puzzle cards by yourself. You can join up with others online and solve cards together (including some really hard cards requiring group efforts). The city itself has a lot of depth, with record companies, pharmaceutical companies, schools, blogs, and newspapers. Some of these “companies” run ads in London newspapers, and puzzles from the game have shown up in newspapers and magazines. Finally, you can hunt for the stolen cube and try to get the $200K reward.

Many of the puzzles make fun programming challenges. I’ve been doing them in python, since that is such a great language for rapid programming. Sweet Dreams (#85) makes an obvious candidate:

#!/usr/bin/env python

a = 1
b = 1
while a < 400000:
    c = a + b
    a = b
    b = c
    print c

My wife solved Rickety Old Bridge (#106) much faster than I was able to write the program (although the program found that there are two similar solutions, not just one). This was a good one to learn generators with:

#!/usr/bin/env python

class bridge:
    people = { "kurt":2, "scarlett":5, "violet":1, "sente":10 }
    states = [ {"near":people.keys(), "far":[], "moves":[]} ]

    def move(self, source, dest):
        """ yield all new states formed by moving
            a person from source -> dest """
        for state in self.states:
            for person in state[source]:
                yield {source:  [s for s in state[source] if s != person],
                       dest:    state[dest] + [person],
                       "moves": state["moves"] + [person] }

    def to_far(self):
        self.states = [s for s in self.move("near", "far")]

    def to_near(self):
        self.states = [s for s in self.move("far", "near")]

    def score(self, state):
        times = [self.people[name] for name in state["moves"]]
        total_time = max(times[0], times[1]) + times[2] + \
                     max(times[3], times[4]) + times[5] + \
                     max(times[6], times[7])
        return total_time, state["moves"]

    def print_scores(self):
        scores = [self.score(s) for s in self.states]
        scores.sort()
        scores.reverse()
        for s in scores:
            print s[0], s[1]

    def run(self):
        self.to_far()
        self.to_far()
        self.to_near()

        self.to_far()
        self.to_far()
        self.to_near()

        self.to_far()
        self.to_far()

        self.print_scores()

if __name__ == "__main__":
    b = bridge()
    b.run()

The program I came up with for solving Magic Square (98) takes a long time to run but eventually starts finding candidate solutions about 2.2 million squares into its search:

#!/usr/bin/env python

def comb(nums, n):
    if n == 0: yield [], nums
    else:
        for i in range(len(nums)):
            for tail, remaining in comb( nums[:i] + nums[i+1:], n-1):
                yield [nums[i]] + tail, remaining

def rows(nums):
    if not nums: yield []
    else:
        for row, remaining in comb(nums, 4):
            if sum(row) == 34:
                for other_rows in rows(remaining):
                    yield [row] + other_rows

def check(grid):
    magic = True
    for i in range(4):
        if sum([row[i] for row in grid]) != 34:
            magic = False
    if sum([grid[i][i] for i in range(4)]) != 34 or \
       sum([grid[i][3-i] for i in range(4)]) != 34:
        magic = False
    return magic

count = 0
for grid in rows(range(1, 17)):
    count += 1
    if count % 100000 == 0:
        print count / 1000, "K"
    if check(grid):
        print grid

Throwing tops

Saturday, April 1st, 2006

18th century toys? Help me, Internet

Several years ago I got an old-fashioned wooden throwing top for Christmas. Unfortunately no one in my family knew what do with it. We couldn’t figure out how to get it to spin, so it went into the back of the closet. TR’s post about yo-yo videos finally made the light go on: The Internet knows…

Sure enough, there are sites with video tutorials showing how to throw tops.

I never would have figured it out on my own…you wrap the string around a different part of the top than I was trying, and you throw it upside down (it flips over in the air). This is the kind of thing that makes the Internet more valuable than a library to me. Sure, I probably could have researched these tops at a library and gotten an instructional video through interlibrary loan. But not in 15 minutes.

Effort Threshold

Saturday, April 1st, 2006

I’ve noticed something: If frequent tasks take too much effort they don’t get done. Unless it is dirt simple, people procrastinate. It’s as if there is an effort threshold. Easy tasks slip under the threshold and get done. Involved tasks…well…maybe we can start on them tomorrow.

I’ve seen this happen with all sorts of things:

  • Running unit tests: If it takes more than a single command or button-press to run tests, developers will only run them once a project. If you’re lucky.
  • Committing code: if your check-in process has too much red-tape, developers avoid checking in. Result? You might as well not be using version control.
  • Paying bills with checks instead of online: Putting checks in envelopes? Maybe tomorrow.
  • Editing digital photos before posting them to Flickr: I still don’t have a smooth enough workflow so photos sit on my computer unprocessed for way too long.
  • Writing blog posts: And now we get to the real point of this post…

Posting to Blosxom took just a little too much effort. TR posted some articles back in November and December I wanted to respond to, but I haven’t gotten around to. Admittedly, this was partly my fault because my CoolURI scheme added a few extra steps to posting. I like Blosxom and it was great software for starting out but it was time for something with more features. So, I switched to WordPress. The out-of-box experience is great:

  • simple installation
  • web-based interface for posting
  • web-based configuration interface
  • Larger user base so plugins and themes are plentiful
  • comments
  • pages load a lot faster than before (again, my fault because my CoolURI plugins slowed Blosxom down)
  • tags (well, categories but you can use them like tags if you like)

So, let’s see if this allows blogging to slip under the effort threshold again…