Skip to content

The Marriage Problem

Another one from the vaults. I wrote this in the late 1990′s:

A society consists of equal numbers of males and females. Each female knows all the males and vice versa. Each female has a priority list of the males she would like to marry, and vice versa. The task is to marry them all off with the least shortfall in expectations, that is, with maximum of priorities being satisfied.

Let’s say that there are X males in a village, and, as luck would have it, there are also X females. Assuming monogamy, each and every bloke is guaranteed a partner, although she may turn out to be more of a ball-and-chain (and vice-versa—let’s not be sexist).

Being of a well-organised race, the villagers carry around with them, at all times, a stone tablet, onto which they carve the names of their favourite members of the opposite sex. In fact, they’re so fastidious about this that they keep the names of *every* member of the opposite sex, ranked from most desirable (assigned a ranking of 1), to the least desirable (assigned a ranking of X).

Whenever two villagers of the opposite sex meet, they compare notes (so to speak). Each quotes the rank they’ve assigned the other, so that both parties know their Mutual Attractiveness Factor, which is defined as the sum of the two separate ranks.

Hundreds of years ago, a rather forward-thinking village chief built a chess-board in the centre of the village, containing X*X squares in total. Each row of this board is inscribed with the name of a male villager, while the columns are reserved for the females. Whenever a couple meet, they make a pilgrimage to the board, and place upon the square at the intersection of their names a number of pebbles. The number they choose is always exactly the same as their M.A.F. (due to some ancient tradition, no doubt).

Each spring, when a man’s fancy turns to… chess, the village idiot stops playing with his dead rats, and instead sweeps the chess board free of pebbles. He does this with a straw broom, babbling all the while, about such things as “en-pee-’ard” and “low-cal-mini-mah”. The village idiot who, fortunately, is hermaphrodite, sweeps the board free of pebbles in a very strange way (using a process which he refers to as a “seaweed-with-musical-timing”).

What he does is this: he first looks for a pile of pebbles which, if it were to be swept away, would cause either the row or column which intersects it to become pebble-free. If such a pile is found, it is carefully gathered up and transferred to a leather sack, and the names associated with the row and column are recorded on a list. The row and column are then rather haphazardly swept clear. On the other hand, if no such pile is found, then the largest pile of stones on the board is swept into the forest. In the case when more than one such pile exists, the village idiot selects between them at random (there isn’t space here to describe how he makes the selection; suffice it to say that the process involves a chicken, several lengths of twine, and boundless patience).

This process, or “algae-rhythm”, is repeated until the board is free of rocks. When this happens, the village idiot hands his list to the local clergyman, who promptly marries all of the couples on it. The idiot then divides his bag of pebbles into 2X evenly-sized groups (which, more often than not, involves smashing the pebbles into bits). The number of pebbles in each group represents the average rank assigned to a person by their partner in marriage (which explains the low divorce rate, perhaps).

Once the weddings have taken place, the village idiot is given a bag of gold by the grateful couples, which he promptly spends on beer and rats.

Solving Puzzles, circa 199*

I had absolutely no sleep at all last night, which is why I spent today in a stupor, content with reading news and pottering about rather than Doing Something Challenging.

This explains why I started doing some vanity searches this afternoon, digging up an old web-page of mine from the mid-1990′s. Yes, it used TABLEs for formatting (back then, it was common to UPPERCASE your HTML). Yes, it included a count of page views at the bottom of each and every page. And, yes, it even included a link to my “hotlinks” which I could access when using “Netscape” from home, over my swanky 14.4 dialup connection (presumably when I could drag myself away from playing with my PlayStation).

One of my old web pages was about number problems. I used to have fun writing programs to solve puzzles such as these by brute force:

Which numbers satisfy the following property… the sum of the individual digits of the number raised to the power of that digit is equal to the number itself? For the purpose of this problem, we define 0^0=0.

For example, the number 3435 is known to have this property, since 3^3 + 4^4 + 3^3 + 5^5 = 3435.

This problem proved rather easy to solve. We know that no numbers above 10*9^9 (about 4e9) can have this property, simply because the sum will always be less than the original number. Therefore we can solve the problem by brute force, using unsigned 32-bit integers.

I wrote such a program, and it took a few hours to execute on our SGI Onyx computer. The solution set is { 0, 1, 3435, 438579088 }.

And here’s my program:

#include <stdio.h>

typedef unsigned long INT;

int main(int argc, char **argv)
{
	INT number;
	INT sum;
	INT num;
	INT power[]={0,1,4,27,256,3125,46656,823543,16777216,387420489};

	for(number=0; number<4e9; ++number)
    {
		sum=0;
		num=number;

		do {
			if((sum+=power[num%10])>number) break;
		} while(num/=10);

		if(number==sum) printf("%d\n", number);
	}

	return(0);
}

It’s almost unbelievable that such a program used to take “a few hours” to run on a machine that was, at the time, a veritable power horse. Today I compiled and ran it on my grungy lappy. It burned one core for a few minutes to find the same solution. All the while, my computer remained snappy, and I actually became impatient waiting for the answer. What have we become? Why aren’t we doing more, now that we all carry around supercomputers with us?

Funny thing is, my website was averaging 1800 hits per day back in the mid-90′s. This blog, by comparison, barely manages 10. Well, phooey.

Update: Optimisations

On my desktop at work, this same program ran in 150 seconds, using a quarter of the total processing power of the machine. That’s something like 26 million numbers checked every second. That would have seemed like magic 13 years ago, when the Onyx was checking half a million numbers each second.

Beetlefeet asked about the optimisations mentioned in my comment below. Each optimisation sped up processing by a factor of 10 or so. I’ve re-run them on my desktop. The first completes in 45 seconds, and the second completes in around 5 seconds, so they still count for something!

The first optimisation, by David Conrad, worked by keeping a running total of the current value, modifying it each time around the loop based on how the digits in the number changed. It printed the result whenever the number equalled this running total. Here’s the code:

#include <stdio.h>

int digit[10] = {0,0,0,0,0,0,0,0,0,0};
long diff[10] = {-387420489,1,3,23,229,2869,43531,776887,15953673,370643273};

int main(void)
{
    unsigned long x = 0, val = 0;
    int i;
    while (x < 4e9) {
        if (x == val) printf("%lu\n", x);
        i = 0;
        digit[i] = digit[i] == 9? 0 : digit[i]+1;
        val += diff[digit[i]];
        while (digit[i] == 0) {
            i++;
            digit[i] = digit[i] == 9? 0 : digit[i]+1;
            val += diff[digit[i]];
        }
        x++;
    }
    return 0;
}

The second optimisation, by Geoff Bailey (AKA Fred the Wonder Worm), was really clever; it maintained a running total too, but worked by looping over 10 variables, one that represented each digit. Here’s the code:

#include <stdio.h>

typedef unsigned long   ulong;

long diffs[] = {
    1, 3, 23, 229, 2869, 43531, 776887, 15953673, 370643273, -387420489
};

main()
{
    ulong       sum, n;
    int         i0,i1,i2,i3,i4,i5,i6,i7,i8,i9;

    sum = 0;
    n = 0;

#define LOOP(var, lim, code)	\
    for (var = 0; var < lim; sum += diffs[var++])	code

    LOOP(i9, 4,
    LOOP(i8, 10,
    LOOP(i7, 10,
    LOOP(i6, 10,
    LOOP(i5, 10,
    LOOP(i4, 10,
    LOOP(i3, 10,
    LOOP(i2, 10,
    LOOP(i1, 10,
    LOOP(i0, 10,
    {
        if (n == sum)
            printf("%lu\n", n);
        n++;
    }
    ))))))))))
    return 0;
}

I guess that optimisation and obfuscation are closely related (although you don’t always get faster code by making it harder to understand).

Amazing First Week

I sent out an email to a bunch of friends and family on Monday morning announcing the fact that I’ve resigned my job to focus on personal projects for the remainer of 2010. The response was overwhelming; I received many emails and phone calls, all very supportive, and some offering help.

I’ve achieved the following things in my first sabbatical week:

  1. Found an office in Leederville that I’ll be moving into next Wednesday.
  2. Completed a prototype of one of my projects, the d-board (get it here).
  3. Pitched three of my other ideas to a handful of people who are interested in funding them with Real Money ™.
  4. Met with an accountant to set things up for if and when I actually do make any money.
  5. Started planning the implementation of MegaHAL10, another of my projects.

Thanks all so much for the overwhelming support. It’s been great. And don’t forget to subscribe to “The Occasional Jason” if you want more detailed updates; the subscription form is over there on the right (if you’re viewing this on my blog).

The Great Productivity Experiment

2010 was to be my year of “no unfinished project”. I tried really hard to work 10 hours a week on “Postal Worker”, but slotting in two hours of development time between 9am and 1am each weeknight resulted in burnout (we have a new baby in the house, and I just couldn’t continue to burn the candle at both ends). Rather than fail, I’ve decided to quit my job and spend the rest of 2010 working on personal projects, including Postal Worker, so expect to see a whole lot more bloggage going on around here. And, if you’d like details, here’s the first group email I sent out to friends and family (you can subscribe to the list from this blog; there should be a signup over there on the right).

Postal Worker 13

Right, so I’m back in the thick of it. I spent tonight working on the InputManager, which is fairly rudimentary at the moment, but the overall plan is for each game context to be able to process input from a controller that abstracts away the specific hardware being used (which, for an iPhone, is keyboard, pointer, location, compass, socket and accelerometer). It should be trivial, for example, to switch between controlling a game character with touch or tilt, without having to change any code in the game character entity itself (this makes prototyping much more fun; I wouldn’t expect you to offer that switch to the user in production however).

The other goal of the InputManager is to give game contexts and game systems controlled access to input controllers. For example, when a particular game context is active, it may require exclusive access to touch. In other circumstances, several game systems and contexts may use touch simultaneously (as would be the case when implementing game entity control with touch and overlaying a HUD that contains buttons that may be pressed). I want to avoid the usual technique of having entities, contexts and systems query the input devices directly, so that’s taking a bit of thought and hacking to figure out.

I expect I’ll be a day or two on this, and then will move onto entities.

Pop, Pop

Right, time to get back into it. I’ve just returned from a sensational family holiday down at Eagle Bay, and, before the Easter Break, I finally finished Bogus Quest to my satisfaction (it’s now pretty much the game I envisioned during Global Game Jam). And the Interzone Controversy seems to have died down a bit, although the pot is still simmering on the back-burner. Which means, in the spirit of my New Year’s Resolution of “leave no project unfinished”, that it’s now time to return to Postal Worker. Yay!

It can be a struggle getting back to an old project when the code has been left dormant for so long (well, it’s been weeks and weeks and weeks, you know). Code rot is real, you know. But I am keen as anything to get back into making a componentised entity system, so we’ll see how things go. Tonight it’s just preparatory work – I’ve been upgrading to the latest release of Airplay SDK (which now supports iPhone app signing on the PC without having to run a klunky signing server on a Mac), actually getting the PC app signing working, fixing a few memory bugs and basically making sure I actually know what I’ll be doing tomorrow night when I dive back into things.

It’s good to be back :)

Push-Down Stack

At the start of the year I began working on Postal Worker, a game for the iPhone based on an idea that I came up with at GCAP in Melbourne at the end of 2009, while talking with a couple of mates over coffees in the hotel bar. I was totally psyched, and gave myself a 100-hour deadline to get the game done and dusted. I started by building a game engine on top of AirPlay SDK. It was fun, and I was making good progress.

Then Global Game Jam suddenly loomed, and I decided to put the Postal Worker project in pause mode so I could hack out a game in 48 hours. I took the opportunity to learn ActionScript, and made a dinky little flip-screen arcade adventure called Bogus Quest. I spent the week following GGJ adding new features to the game and fixing some bugs. I still have a list of things that I want to do, including adding a proper loading screen and adding sound effects.

Then Mike Turner came and raided the Interzone offices, and I became involved with spreading the word about what happened in an attempt to get the Australian government to actually do something about it.  A lot of people have been seriously disadvantaged by all of this, but, at the same time, there was a great sense of camaraderie, and it was quite a lot of fun analysing documents, editing video and basically getting the word out to journalists.

Tonight I realised that I’ve got three hobby projects on the go. I’m a self-proclaimed procrastinating perfectionist, by which I mean that I have a bunch of crazy ideas but never actually get around to completing any of them, out of fear of failure. Ask me about Magnate, my web scraper cum news aggregator, or my procedurally generated text adventure, or MegaHAL10 (the next version of the chatterbot I wrote 15 years ago), or Thrust Harder, or dBoard, or SpeedReader, or Fanglr. All projects that I’ve been incredibly excited about, and all terribly incomplete.

Well, no more. I’m going to manage my push-down stack, and make sure that I always go back to and complete projects that were interrupted. I won’t stop the interruptions. They’re fun. But I will make my default activity finishing the current project, whatever that might be.

So look out for a blog post about Bogus Quest soon. And, after that, keep your eyes peeled for Postal Worker 13. I promise!

Interzone: The Downward Spiral

This article has moved to www.interzowned.com/the-downward-spiral.

Postal Worker Pause!

I plan to take a bit of time off to (a) recover from the fantastic Global Game Jam that was held over the weekend and (b) check out some of the other Global Game Jam games. Big props to Simon Wittber for organising such a great event, and well done to all who took part!

I went into GGJ with the intention of developing a Flash game, even though I’d never done that before, and didn’t know my ActionScript from my Objective C. It was a long haul; I worked around 40 hours in a single weekend (the equivalent of a normal working week), and I did all of the design and implementation myself (although Pazu and Sizzle helped with graphics, and I used some other freely available assets).

So, without further ado, I humbly request that you check out and vote for Bogus Quest.

Postal Worker 12

Tomorrow marks the beginning of Global Game Jam 2010, which means I’ll take a brief respite from Postal Worker development. Expect the 13th installation to be late in the week next week.

Tonight I started by implementing a pause mode in KranzkyEngine. You can now pause, resume and stop it. Pause is pretty straightforward to implement; the engine sets or clears a boolean flag, and passes a time delta of 0 to all update methods if it is paused. It worked without issues in the HelloKranzky sample game.

Of course, once the pause mode was in, I wanted to tap to pause and tap again to unpause. Sure, this could be hacked in quickly, but the whole point of this exercise is to build a neat, re-usable game engine, so I took the lengthier route. I realised that I want at least four “managers” in the game engine:

  • The ContextManager, which you’ve met before
  • An InputManager, to take player input (keyboard, multitouch), appropriately transformed
  • An EntityManager, to handle all of the game objects, and
  • A SystemsManager, to handle various systems (like Physics), where each System is responsible for all of the Components that may be attached to Entities

So I began by refactoring the ContextManager to derive from a KranzkyManager ABC, and then I added addManager and getManager calls to the Engine. Internally, the Engine iterates over the list of managers, calling update() and render() on each one.

The cool thing about this is that a game could, conceivably, add a new manager to the engine without touching any engine code. Which is awesome.

Anyway, by the end of the night I had the sample game running, identically to before, using the new system. And I didn’t have any time to implement the InputManager that started this whole thing off. That’ll be for next week :)