Fun Little Threading Problem

August 26, 2011 at 04:06 PM | Play | View Comments

A fun little threading problem I ran into today: imagine a Thermometer which can issue notifications if the temperature reaches a certain threshold:

class Thermometer(object):
    def set_temperature(self, value):
        self.temperature = value

    def wait_for_temperature(self, target):
        # ... wait for `self.temperature` to be at least `target` ...
        return self.temperature

Using only AsyncResult, how can the set_temperature and wait_for_temperature methods be implemented to guarantee that multiple threads can wait_for_temperature without missing a temperature change (only one thread will be call set_temperature).

My solution:

class Thermometer(object):
    def __init__(self):
        self.temperature_changed = AsyncResult()

    def set_temperature(self, value):
        self.temperature = value
        next_change = AsyncResult()
        self.temperature_changed.set((next_change, value))
        self.temperature_changed = next_change

    def wait_for_temperature(self, target):
        changed = self.temperature_changed
        temperature = self.temperature
        while temperature < target:
            changed, temperature = changed.get()
        return temperature

I originally encountered this problem working on a component at work, but I enjoyed the solution so I thought I would adapt it and post it here.

Permalink + Comments

Making Settlers of Catan less painful with pity points

February 27, 2011 at 06:02 PM | Play | View Comments

If you've played Settlers, you know that missing a couple of early-game rolls can be the difference between a win and a painful, boring loss. Pity points[0] help fix that.

The rules are simple:

  • Any time a player doesn't get any resources from a normal (ie, start-of-the-turn) dice roll, they get one pity point.
  • At any time, a player may exchange pity points equal to their number of victory points for one resource.

For example: on Alice's turn, she rolls a 3. Neither Alice nor Bob have a settlement adjacent to a 3, so they both get one pity point. Also on Alice's turn, Bob trades three pity points (because Bob has three victory points) for one sheep, and trades that sheep to Alice.

[0]: introduced to me by Fraser Harris — thanks!

Permalink + Comments

Lightroom: Export a List of Pictures in a Catalog

September 12, 2010 at 12:52 PM | Play | View Comments

I recently had to export all the names of images in a Lightroom catalog. There was no obvious way of doing this through the Lightroom interface, so I threw together a little Python script that directly reads Lightroom's SQLite database. There are a few caveats, noted in the file (below)… But it worked pretty well for me, and hopefully other people will find it useful too.

Permalink + Comments

How to Beat SimTower

March 15, 2009 at 04:32 PM | Play | View Comments

SimTower -- we've all played it, many of us have loved it, none of us have beat it.

Until now.

So, here we go: the definitive guide to beating Sim Tower!

0: Get the Game

It's hard to beat a game you can't play, so getting a copy of the game is a good place to start. I got mine at Abandonia.

A note here: the game will run under Darwine on Intel-based Macs... Just don't try and save -- that doesn't work.

1: Starting your Tower: hitting two stars

After the game is installed and started, begin your tower by using the build-a-lobby-in-the-bottom-left-corner-of-the-screen trick to double your money, then build a lobby that is the entire width of the screen.

After you have built the mega-lobby, start building offices. Lots of offices. Three floors worth of offices. In addition to offices, build stairs. I build them approximately half a screens width from the right side of the screen, then every screens width after that. It doesn't really matter, though -- all that matters is that you've got three floors of solid offices and stairs going to all of them.

By the time this is done, you should have two stars (300 population).

2: Fast food: three stars

Great -- you've got two stars. Only three more to go. And how will we get there? Fast food.

Why fast food? Well, the hardest part of the star requirements is the population, and fast food restaurants have the highest population to space ratio. Also, no one seems to notice if the only thing in your tower is fast food and office space.

So, time to start building!

Your first order of business is to build two security offices. It doesn't really matter where you put them, all that matters is that you have them -- they are the only requirement for three stars. Stick them under ground, at the beginning of a floor -- where ever.

Now that that's out of the way, it's time to start building fast food.

Your goal is to build eleven (yes, 11) floors of fast food.

To do this, you will also need elevators. Lots of elevators. You will need about six, distributed across the length of your building. I like to build them in pairs:

Additionally, you will need to make sure that the lazy sims working in the offices don't use these elevators. Use the inspector tool to look at each elevator, then click the floor numbers to disable floors 2,3,4. Also, I've found it helpful to have one elevator which goes to odd-numbered floors and another which goes to even-numbered floors. Try that too.

Oh, yea, and make sure that all the elevators have eight cars in them.

At some point in the process of building this unholy pile of fast food, you'll get a population of 1000 and hit three stars. Cool! On to the next step.

3: Cinemas: A (brief) change from fast food (four stars)

Once you've hit three stars you'll get the option to build even more exciting things like restaurants, shops and party halls.

But just go ahead and ignore those.

The only things you should be concerned with are:

  1. Building more fast food.
  2. Add a liberal sprinkling of cinemas - I have no evidence for this, but I think they bring more people into your building.
  3. Build a few parking spots. Make sure you build enough that there are always a few empty. You will need them for the VIP and five stars.
  4. Build one hotel suite, along with housekeeping right beside an elevator. This is also for the VIP.
  5. Your sims will whine about wanting medical and recycling centers. Give them one medical center, and as many recycling centers as they need to be happy (2 or 3? Just don't over-do it -- recycling centers have a steep annual fee).

Alright, and once you've done that, just go back to building more fast food.

At some point here, you will hit a population of 5,000, the VIP will come and you will get four stars. Good job.

And if you get to 14 floors and still don't have four stars, just skip down to the next section anyway.

Oh, your building will catch on fire too. Just pay to have it put out.

4: Metro station, express elevators and more fast food (five stars)

Ah, four stars. You think you're almost there, don't you? Ha!

By now, you should be up to about 14 floors. You will finally get a break from the tedium of building fast food as you get to build a sky lobby and revamp your elevator system.

So here's what to do:

  1. Build a sky lobby on the 15th floor.
  2. Build express elevators from the 1st floor to the 15th. I have six, also in pairs.
  3. Extend two of the express elevators all the way down, as low as they will go, then build a metro station there.
  4. Move the existing elevators down so they go only to the 10th floor.
  5. Build escalators from the sky lobby down to the 11th floor.
  6. Build four more floors of fast food (from floor 16 to 20), and use escalators to connect all of those to the lobby.
  7. Build more elevators on the 15th floor, directly over top of the elevators which go from floor 1 to 10. These elevators will be used to get people to floor 21 and above, so make sure they don't stop at floors 16 through 20).
  8. As you build more floors of fast food, use these new elevators to connect them to the sky lobby.

And there you have it -- do this up to floor 23 or 24, and eventually you'll hit a population of 10,000 and five stars. Huzza!

5: One last thing...

Phew, you're at five stars and you've probably got a population of close to 15,000. Your first order of business is to get your population up and over 15,000 (the requirement for a "Tower" ranking). Keep building fast food until you've got that :-)

Once you're over 15,000 population, you've only got to do one more thing: build a cathedral. To do this, pick two express elevators which are at least the width of a cathedral apart, then extend them up all the way to the 100th floor. Build a small lobby on the 90th floor, place the cathedral on the 100th floor, then build an elevator to connect them.

Now you've just got to wait for someone to get married, and your tower will be awarded the rank of "Tower"! (just don't forget to turn off fast mode so you can enjoy the wedding).

And that's it! You're done :-)

Resources

A couple of useful resources:

Permalink + Comments

Python Brain-Teaser

May 29, 2008 at 11:14 AM | Python, Play | View Comments

I'm working on pulling some functionality out of one object and putting it in another, and I came across this interesting problem:

class Foo:
    me = "foo"
 
class Bar:
    me = "bar"
    def get_me(self):
        return self.me
 
Foo.get_me = Bar.get_me
x = Foo()
 
print x.get_me()


What does this print?

And, next question, why is that?

After lunch I'll post my thoughts :-)


Until now, I had assumed that the semi-magic self variable was set on method calls (ie, when x.get_me() is called)... But apparently it's set when the object is instantiated (which makes perfect sense, otherwise getattr(Bar(), 'get_me')() would not work).

So I can only presume that something equivalent to this happens when an object is instantiated:

from functools import partial
new_obj = Class()
for (key, val) in new_obj.__dict__.items():
    if not callable(val): continue
    setattr(new_obj, key, partial(val, new_obj))
Permalink + Comments