Older blog entries for Bram (starting at number 117)

Poker

It turns out that my simplified poker was a bit too simplified. Chris Chang pointed out that since all-in bluffs are guaranteed to fail half the time, raising one is strictly superior to going all in. He suggests adding more cards to get rid of that problem. With the way people play these days that game would be just about as interesting as no hold 'em. (See that link for a good explanation of why no limit isn't really 'the cadillac of poker' and pot limit is better.)

Here's an interesting question: if you have a positive expectation bet, how much should you bet each successive round to make your money grow as quickly as possible? If you bet nothing you obviously get nothing, but if you bet everything you wind up with zero and lose out on the ability to make any money in later rounds. It turns out this is known as the Kelly Criterion.

There's computer security snake oil even in poker. This 'audit' just about made my head explode. An audit is when you go over the internals of a system and analyze that it works correctly. Running statistical tests on the output isn't an audit, it's just bullshit.

While trying to grok the rules to Razz I came up with the following game, which I think has most of the strategic elements of Razz but has a lot of the weirdness removed. I say 'I think' because Razz has a whole lot of weirdness and not having played it I have a hard time figuring out what that weirdness causes in practice.

Each player gets two pocket cards to start and community cards are dealt out as in hold 'em. The difference is in how hands are scored. Unlike in other forms of poker, the hands really are seven-carded. The hand with the highest card wins, with a tie-break of the second-highest card, then third, etc. Duplicate cards are completely ignored. For example, if player X has AQ and player Y has K3 and on the board is A5538 then X's full hand is AQ853 and Y's full hand is AK853, so Y wins. If two hands are identical except that one has an extra low card, then the one with more cards wins. For example, if player X has AQ and Y has A2 and on the board is Q9884 then X's hand is AQ984 and Y's hand is AQ9842, and since Y has the extra 2 Y wins. Having two extra cards of course also wins, and having a triplicate of a card causes both duplicates to be thrown out. As in Razz, flushes and straights don't count for anything.

I think there are a few things which make this an interesting game. A hand which contains two lower cards than another one pre-flop has only a low chance, I think about 7%, of winning, so trying to intimidate people by playing every hand will rapidly get you soaked. Also, knowledge gained after each face-up cards are dealt is directly related to the previous knowledge gained, increasing chances for reasoning what cards a player has based on their behavior. The chances of any particular card turning up on the board are reasonably high, so even if you start with a pocket ace there's almost a one in three chance that you'll find yourself playing garbage and having to figure out whether to bluff or fold.

Alarm Clock Display

I have a digital alarm clock with a seven-pin display which I've long noticed 'warbles' in funny ways when I brush my teeth with an electric toothbrush, due to the vibration it imparts on my head. I always attributed to the weird way different pins warble to odd cognitive phenomena, but the other night I noticed that it's always the pins on the top and right edges which warble as one group and the others warble as another, so now I wonder if there's something funny about the timing of it, for example maybe those three pins are offset by 1/120 of a second from the other four as they cycle on and off.

Monitors also warble when you bite into crunchy potato chips. It's highly amusing.

Hex

Based on the hex board evaluation ideas I gave earlier, I've written a hex playing program. I found giving it a two-ply look-ahead got rid of the tendency to play new moves right next to old moves.

This program plays position surprisingly well, but still has some very obvious weaknesses. For example, it doesn't realize that bridges are fully connected.

Clearly some sort of hexy/six-style feedback from tactical calculations into positional evaluation is necessary to make this program play better. I think my approach is quite a bit more inherently flexible about ways of doing that than the circuit resistance approach which hexy and six use.

To use this code, create a hex board of the size you want, then use x() and o() to place pieces, and to have the computer place a piece use moveo(). The computer only plays O, which is trying to connect the top and bottom. Runs of length 1000 work reasonably well.

Note that although a two-ply look-ahead is substantially better than a one-ply look-ahead, a chess-style three-ply look-ahead would be of dubious value. A better approach would be to make the results of the move/counter-move pairs influence which positions are generated in the fill-in process.

from random import randrange
from copy import deepcopy
def hexprint(myarray):
    for i in xrange(len(myarray)):
        print (' ' * (len(myarray) - 1 - i)) + ' '.join([str(myarray[x][i]) for x in xrange(len(myarray))])
    print
class hexplayer:
    def __init__(self, size):
        self.size = size
        self.states = [['.' for i in xrange(self.size)] for j in xrange(self.size)]
    def o(self, x, y):
        assert self.states[x-1][y-1] == '.'
        self.states[x-1][y-1] = 'O'
        hexprint(self.states)
    def x(self, x, y):
        assert self.states[x-1][y-1] == '.'
        self.states[x-1][y-1] = 'X'
        hexprint(self.states)
    def findbest(self, values):
        best = -1
        bestx = None
        besty = None
        for i in xrange(self.size):
            for j in xrange(self.size):
                if values[i][j] > best and (self.states[i][j] == '.'):
                    best = values[i][j]
                    bestx = i
                    besty = j
        return (bestx, besty)
    def moveo(self, runs):
        values2 = [[-1 for i in xrange(self.size)] for j in xrange(self.size)]
        responses = [[None for i in xrange(self.size)] for j in xrange(self.size)]
        for i in xrange(self.size):
            for j in xrange(self.size):
                if self.states[i][j] == '.':
                    self.states[i][j] = 'O'
                    values, wonx = self.evaluate(runs)
                    bestx, besty = self.findbest(values)
                    assert self.states[bestx][besty] == '.'
                    responses[i][j] = (bestx, besty)
                    values2[i][j] = runs - wonx - values[bestx][besty]
                    self.states[i][j] = '.'
        bestx, besty = self.findbest(values2)
        self.states[bestx][besty] = 'O'
        hexprint(values2)
        print float(values2[bestx][besty]) / runs
        r1, r2 = responses[bestx][besty]
        print r1+1, r2+1
        hexprint(self.states)
    def evaluate(self, runs):
        wonx = 0
        top = self.size - 1
        values = [[0 for i in xrange(self.size)] for j in xrange(self.size)]
        for run in xrange(runs):
            myvalues = deepcopy(self.states)
            for i in xrange(self.size):
                for j in xrange(self.size):
                    if myvalues[i][j] == '.':
                        myvalues[i][j] = ('X', 'O')[randrange(2)]
            visited = [[0 for i in xrange(self.size)] for j in xrange(self.size)]
            def neigbors(x, y):
                r = []
                if y > 0:
                    r.append((x, y-1))
                    if x > 0:
                        r.append((x-1,y-1))
                if x > 0:
                    r.append((x-1, y))
                if x < top:
                    r.append((x+1, y))
                if y < top:
                    r.append((x, y+1))
                    if x < top:
                        r.append((x+1, y+1))
                return r
            remaining = [(0, i) for i in xrange(self.size)]
            while remaining:
                x, y = remaining.pop()
                if visited[x][y] != 0:
                    continue
                if myvalues[x][y] != 'X':
                    continue
                if x == top:
                    wonx += 1
                    break
                visited[x][y] = 1
                remaining.extend(neigbors(x, y))
            else:
                remaining = [(top, i) for i in xrange(self.size)]
                while remaining:
                    x, y = remaining.pop()
                    if visited[x][y] != 0:
                        continue
                    if myvalues[x][y] != 'X':
                        continue
                    visited[x][y] = 2
                    remaining.extend(neigbors(x, y))
                for i in xrange(self.size):
                    for j in xrange(self.size):
                        m = neigbors(i, j)
                        n = [visited[x][y] for (x, y) in m]
                        if (1 in n or i == 0) and (2 in n or i == top) and self.states[i][j] == '.':
                            values[i][j] += 1
        return values, wonx
I still have my domains

Thanks to everybody who mailed me translating the mail about my domains. A whole bunch of people translated it for me, and David Turner went so far as to call ovh and tell them about the apparent hijack attempt. And Joey DeVilla got in contact with James Woods at Tucows.

All the help turned out to be way more than needed. I probably could have ignored the original mail and not gotten my domains taken, since it required affirmative action on the part of one of the contacts listed, and for those two I was the only contact.

Right before posting here about my domains I mailed tech support at my registrar, domainmonger. A few minutes later I noticed the domain locking feature, and turned it on. Somewhere about that time I got mail from tech support at domainmonger saying that they'd locked all of my domains. I'm not sure whether they or I did it first.

Thanks everybody for your help, that was confidence-inspiring.

In answer to the obvious question 'Why didn't you just hit the site and say no?' First of all, the site was in french, which I only speak a few words of, and second of all, when I went to it it said that I needed to enter some code taken from my registrar. While that message was probably legit and there for security purposes, it set of an alarm bell in my head that the attempted transfer mail I got might have been a fake sent by a spammer in an attempt to get me to give them a confirmation code to steal my domain. So I didn't do it.

Cool Mechanical Stuff

Here , here and here you can find lots of explanations of cool mechanical things.

My own crackpot engine ideas

I've designed a piston replacement I call a 'steel lung'. It basically acts like a piston in that it contains a chamber which expands and contracts, but unlike a piston the shape of the chamber remains mostly spherical for the entire stroke, for much better surface area to volume ratio than found in conventional pistons. Of course this creates extra friction, although not an insane amount - the amount of 'seam' is only two or three times what you have in a piston. It also increases sealing problems, but again not as much as you'd expect. It can be configured so that the expansive forces push the moving pieces into each other rather than away from each other, and the sealed edges move outwards during combustion, so there isn't all that much force on them.

The big question, of course, is whether heat loss during combustion is significant enough to be worth reducing. I'd appreciate it if anyone has any knowledgeable opinion about this.

Another idea of mine is based on how the heat of the piston head is frequently a problem in car engines. How about if, rather than a conventional piston, we have a piston which is composed of several sliding pieces in such a way that the piston head is actually a sliding pieces whose exposed part is different with each ignition? That would cause the effective surface area of the piston head to be a lot larger, thus making it easier to keep cool. Again, I'd be interested in any knowledgeable opinions about whether this is a worthwile goal even in principle. I have a design for this, but it lacks elegance.

Finally, I have a question about the way in which motion is translated from reciprocating to rotational. It seems a little odd that real engines do this with a simple camshaft, since that has a very particular rate of movement at each point, and I have a hard time believing that it's optimal. There are plenty of only slightly more complicated mechanisms, many given in the links above, which can modify this with a lot of precision. Does the relative rate of movement of the piston at each point in the cycle not matter all that much, or is it simply not worth the extra complexity?

Buckminster Fuller was a crackpot

Buckminster Fuller's intended great invention was the dymaxion car, which was basically a stretch limo with one front wheel which always ran backwards. Its funding was pulled after a fatal crash.

You can read Fuller's excuse-making about the crash here. For those of you unfamiliar with the physics involved, I'll explain. The car turned left and, as is inevitable with a 20 foot long vehicle with real-wheel steering, its butt stuck out into the right lane. There happened to be a car there (Fuller claims it was 'rubbernecking', which is completely besides the point - this is a very common kind of accident which shouldn't cause a fatality). When the rear side of the dymaxion hit the other car, its single rear wheel got shoved hard into the ground, making it precess and forcing the turn to be even greater, quickly causing the car to get to such an angle that it rolled over.

The investors wisely decided to pull out after this, presumably because they wanted nothing to do with a company with such callous disregard for passenger safety, and that was the end of that. Fuller did spend a huge amount of his own money attempting to build more cars, but they never went anywhere, probably because the quality of his engineering ideas was about what you'd expect, which is to say, very poor.

When you look at Fuller's accomplishments, philosophy, and claims, they bear a notable resemblance to many internet pundits today.

Moller Skycar

Speaking of which, those of you who have heard of the Moller Skycar may wish to read this.

If you're interested in flying recreationally, I recommend powered paragliding.

Simplified Poker

When musing about poker, I came up with simplified version, which is close to as simple as you can get. Two players, three cards. Each player is dealt a single card. The higher card wins. After anteing up, each player can either fold, call, raise one, or go all-in. I suspect that this variant would actually be fairly interesting to play, since it involves going all-in (which I think makes complete mathematical analysis completely beyond the capabilities of current techniques) and the small number of cards make the contents of the other player's hand strongly related to the contents of your own.

An improved trust metric

I think I've figured out how to improve on the last batch of trust metric ideas I posted. In those, I had problems with everything certified by the 'root' looking like spam, and suggested some very kludgy ways of dealing with that problem.

A much better approach is to view spam guilt as 'leaking' out of the system, an extremely small amount from everywhere. I'll present a technique as an interative process, in which spam guilt gets back propogated with each round. After many rounds have been done, it will be clear that some nodes have their guilt score increasing without bound, while the rest will have their guilt scores stabilized. All nodes whose guilt surpasses some threshold are then removed (the number of rounds and threshold are obviously a judgement call, but generally more is better). The distinctions between directly vs. indirectly attacking nodes I posted about before are then made, and the decision of which nodes can mail is based on the result.

(At some point I'm going to post a consolidated form of my best trust metric to date, so people don't have to read a long series of posts and cull the non-obsolete snippets out of them to figure out what's going on. In the mean time, I apologize for the vague references to stuff I've posted about before, and please bear with me.)

First, we have some value for how much spam each node is allowed to send before getting cut off, which we set by judgment call. A hundred pieces sounds reasonable, so I'll use that for the sake of argument. Next, we calculate how much 'leak' each node is, which we can reasonably set to 3 * (total amount of spam ever sent) / (total number of nodes). The number 3 can obviously be varied, but that's a good value.

On each round, we add spam score to direct infringers, back-propogate spam scores and then leak spam scores. We add spam scores for each direct infringer simply by adding the amount they've spammed to their score. To back-propogate, we iterate over each node, and for each of them we find the minimum spam score of it and any of the nodes which certified it, and transfer 100 to that node. If the node in question's spam score is less than 100, we transfer that amount. To leak, we reduce the spam score of each node by the leakage amount, and round up to zero.

I'm quite happy with this algorithm. It's essentially linear time, and I can straightfaced say that it's both secure and practical.

Chess

bgeiger: If one were to select a game to be the single canonical abstract strategy game which people the world over knew how to play, having draws would be a complete disqualification. Go has no draws if you use a super-ko rule and non-integer komi, but there are many modern board games which meet that criterion as well, for example Amazons.

Phew

Enough blogging for one sitting. More later.

Somebody trying to steal my domains

I just got the following mail. It looks like somebody's trying to steal some of my domains. Anyone got any suggestions for what I should do? From the rough translation babelfish does, it looks like it's saying that if I do nothing then the transfer will go through by default, which sounds too fucked up to be true, but hey, this is the domain name system we're talking about. This is also right after I told a couple jackasses who made offers for bittorrent.com to take a hike.

From: support@ovh.com
To: bram[at]bitconjurer.org
Subject: [TRANSFERT] bittorrent.com

SARL OVH
140, quai du Sartel
59100 ROUBAIX
Tel : 0 899 701 761
Fax : 03 20 20 09 58
Email : support@ovh.com

Objet : Demande d'acception ou refus de transfert
Vos Ref : bittorrent.com

Roubaix, 2004-07-19 16:29:42

Madame, Monsieur,

Nous avons reçu une demande de changement de registrar pour le nom
de domaine bittorrent.com et vous êtes l'un des contacts actuels de ce
domaine:

*-----------------------------------------------------
| DOMAINE: bittorrent.com
| REGISTRAR: TUCOWS INC.
| CONTACT: bram[at]bitconjurer.org
| CONTACT: bram[at]bitconjurer.org
*-----------------------------------------------------

Si vous acceptez le transfert du domaine, l'enregistrement
sera suivant:

*-----------------------------------------------------
| DOMAINE: bittorrent.com
| REGISTRAR: OVH
| CONTACT: LT795-OVH (tlsx@wanadoo.fr)
| CONTACT: LT795-OVH (tlsx@wanadoo.fr)
| CONTACT: LT795-OVH (tlsx@wanadoo.fr)
*-----------------------------------------------------

Pour accepter ou refuser ce transfert, merci de cliquer sur
ce lien:

http://www.ovh.com/cgi-bin/[stuff]

Si vous NE repondez PAS dans les 5 jours ET si AU MOINS un autre contact
ACCEPTE le transfert, le transfert sera effectué.

Si aucun contact ne répond, le transfert échouera.

ATTENTION :
si vous n'êtes pas indiqué ci-dessus comme contact pour ce domaine, vous
pouvez perdre tout privilège sur ce domaine. N'acceptez ce transfert que
si vous êtes sûr d'en avoir compris les implications.

Ce transfert a déjà été payé.

Pour toute information complementaire, contactez-nous :
support@ovh.com
Merci de votre confiance.

Le Service Client OVH

I got another one for bittorrent.org as well.

Chess

Computer chess programs have gotten very good. Not only in terms of raw computational power, but the very best have improved their play a lot. Deep Junior in particular has a very aggressive attacking style. Consider for example this game, played as black, which involves seemingly almost accidentally sacrificing two pawns so that a knight can take a liesurely stroll across the board to the opponent's king. Unlike many of the celebrated human attacks, this is done against Diep, a no-slouch computer competitor which placed third in the tournament. Many famous chess games turn out to have had extremely bad play by the losing side, with the celebrated attack being unfortunately unsound. With Diep as the opponent, it's doubtful that any simple or even not so simple tactics were overlooked.

Hopefully this newfound attacking ability will make there be not so many goddamn draws in high-level chess. The long-feared draw death has been essentially happening at the highest levels of human competition, and the way computers were able to defend much better than they could attack probably exacerbated the problem a lot.

Board evaluation in hex

I came up with an interesting heuristic for playing hex the other day. We will compute a score for all remaining cells, and move on the cell with the highest score. To compute scores, we will conduct several million independant random trial runs, each of which increase the scores of some cells. On each trial run, randomly place the remaining pieces in unoccupied cells. If you win, throw the run out. If the opponent wins, find each cell owned by the opponent for which the winner would be changed if that single cell were converted to your side, and increase the score of each of those cells by one.

One bad aspect of this algorithm is that it will play randomly when one side or the other has a near lock, since all scores will be zero. That could be fixed by changing the number of remaining cells owned by the opponent, to produce 'optimistic' or 'pessimistic' play. Comparisons of optimistic vs. pessimistic evaluations of about equal positions would be interesting.

The stochastic nature of this algorithm might superficially seem quite ludicrous and computationally wasteful. Ironically, all that CPU-eating is quite refreshing. We have unbelievable quantities of CPU, but when one tries to throw it at hex the same way one throws it at chess, the cycles simply disappear down a black hole.

I'm optimistic that this heuristic will do well. Clearly experimentation is needed.

Interestingly, this algorithm bears a strong resemblance to some trust metric ones I've suggested before. I think that's because hex sort of is like a trust metric - one side is trying to get two sides of the board to trust each other, and the other side is trying to keep that from happening.

60 cycle per second trailers

I noticed an interesting phenomenon in my bathroom the other night. The light on my toothbrush is very small, and cycle at 60 cycles per second (or maybe 120, I'm not sure), and, due to the way human eyes work, when the room is a completely dark leaves a very brief afterglow. As a result, when your eye scans over it a distinct trail appears for a split second. The distribution of the dots is interesting. Some acceleration is visible with the dots at the beginning being closer together, but the eye movement appears to stop pretty much instantaneously.

Financial Hijinx

For a while after I started work on BitTorrent I had no job and lived off savings. Eventually the savings ran out and I started living off of credit cards (don't worry, they're all paid off now).

Living off credit cards is an interesting experience. To do it for a while, you have to keep getting ever larger amounts of credit while keeping your interest rate low. Fortunately credit cards offer low introductory rates, frequently 0%, especially when you take out money on them as a balance transfer from another card. They particularly like doing this for people who have a history of paying off credit cards. For example, people who have been paying off cards completely by transferring to other cards when they get an introductory rate. Yes, this is completely gameable and insane, but it's also standard practice.

When undertaking to get credit cards, it's important to have as few inquiries in your credit as possible. Credit granting formulas are quite arbitrary and erratic, so to keep people from simply applying for credit until they get it, the credit agencies keep records of when you apply for credit and count that heavily against you later on. The types of inquiries aren't differentiated, so for example getting a cell phone counts against for getting a mortgage. Yes, this is also completely insane. To avoid having dings against your credit, it's a good idea to do as little applying for credit as possible. You can keep credit cards from seeing each others's applications by letting 'pre-approved' applications pile up for a while, then sending them all out on the same day.

If you have a very old collections for a very small amount of money and pay it off the payoff counts as 'recent collections activity', so if you need to get some credit in the near future you should hold off on paying it. This policy goes beyond insane into completely nuts, but it continues to be the case.

Once a very low rate on one card is about to run out you should, of course, transfer the balance completely over to another card. It's a good idea to do this later rather than sooner because there's frequently a fee for doing a balance transfer. It's always a good idea when given a new offer of a low rate to call and ask what they can offer you, because the people on the phone can frequently offer you a lower rate and waive balance transfer fees.

Some financial institutions let you transfer money into and out of your credit line via online banking without getting a cash advance charge. You should of course use this if you have it. Making a minimum payment this way is fairly amusing - you transfer money out of the credit card, transfer it back in, and presto, your minimum payment has been made.

Interviewing

Studies of interviews yield a very discouraging result. Interviews are practically worthless for screening candidates. In an interview you can tell if a person is a pleasant conversationalist, and you can give some technical questions to rule out the truly inept, but beyond that you might as well be rolling dice. This is counterintuitive in the extreme. Of all the different things you can say about a person, you'd expect there to be at least some correspondence with one of them. There's a whole long list of criteria, most of them completely illegal - pick candidates who are male, female, black, white, young, old, married, single, thin, fat, tall, short, blond haired, brown haired, etc. None of these have ever been shown to have any correlation with job performance, although I'd like to note that in an all-male work environment hiring an attractive female is probably good for morale.

If I ever have to hire someone from a few candidates, the first thing I'm going to do is call up their schools and employers listed to find out if they lied about degrees or dates of employment. Even though work history doesn't correlate with job performance, being a lying sack of shit almost certainly does. A surprising number of people lie on resumes, mostly because nobody ever checks them. One thing I most definitely will not do is ask former employers what they thought of the person. I've seen those calls get answered, and the quality of responses is dubious, to say the least.

Next I'm going to pick the person, if any, who I've already heard of, since they're likely to have done something worthwile. By 'heard of' I mean in a professional context. Being someone's cousin or loose acquantance doesn't count.

If I'm stuck in the end with several candidates none of whom I've heard of I'm going to pick based on the only criterion I've come up with which seems likely to have some correlation with job performance. I'm going to pick the one with the shortest commute time. Employees who can get to work quickly are going to have less incentive to switch to another job.

Bohemia Redux

For a while now I've been attempting to find an interesting two-player game of no chance which is based on the very special square board topology of viewing sets of four spots which form the vertices of an orthogonal square as being somehow connected. I think I've figured out how to do that now.

Players alternate placing pieces of their color in unoccupied squares. Every time a player places pieces of their color in all four corners of an orthogonal square they get a point. In the end, the player with the most points wins. The game can be made fair with a swap rule, and draws can be eliminated by giving either the first or second player to move the win in case of tie score.

This is essentially a territorial game at core, sort of similar to go in that you have to evaluate which parts of the board are most in dispute. The topology of the board is quite mind-bending, even calculating the score is a chore without a computer. But that mind-bendingness might be quite interesting.

27 May 2004 (updated 27 May 2004 at 01:55 UTC) »

I accidentally hit 'post' instead of 'preview'. Move along, nothing to see here.

Cayley Graphs, Permutation Puzzles, and Archimedean Solids

For many years I had an idea for an approach to solving rubik's cube. Just recently I found a trivial expository example of my approach. Jaap of course took my idea and ran with it and now has a gallery of quite remarkable correspondences between simple permutation puzzles and archimedean solids. (My contribution was the cuboctahedron.)

Gambling pools with odds

Racetrack betting has a very curious feature: When placing your bet, you don't know what the actual odds are. The current odds are readily available, but those in principle could completely change before the close of betting. An interesting variant would be to allow people to place bets on a horse which were contingent on the odds on that horse being at least a certain value. I haven't worked out whether it would always be possible to set canonical odds for a given set of bets, but I suspect it is. This would be an interesting (and, of interest to casinos, potentially quite popular) variant on normal betting pools.

Memory Allocation

graydon has some commentary on memory allocation. Specifically, he's in favor of explicit 'might be null' status for variable, and strictly tree-structured memory allocation. These are good ideas, but there are many thorny edge cases. For example, with non-nullable variables there's the case of an object's constructor passing 'this' to something which reads a variable which hasn't been set yet, even though it's guaranteed to be set once the constructor finishes. For memory allocation, usually that approach works fine, but there are occasional data structures which require making an exception to work properly, such as a circularly linked list. No single allocation scheme can capture the full generality of practical behavior, so the options are to either make a system which handles the vast majority of cases well (which strict tree-based doesn't quite) or have a system for violating the general rule in special cases.

I've spent quite a bit of time thinking about how to make a type-safe language with the declarative power of C++ (and more) but with the transparency of C. A friend of mine told me that one of my ideas amounts to 'jump tables but no vtables' - If you subclass an object, rather than making the class data structure point to a superclass object, it simply inlines a copy of references to all the methods it inherits from the parent, with overriden methods substituted. This vastly reduces the complexity of method lookups at runtime, both in terms of cycles taken and difficulty of proving correctness. The tradeoff is that in theory there could be an exponential blowup in the size of class objects in memory, but in practice that won't happen. (Well, maybe it will happen for those truly obsessed with OO wankery, but they get what they deserve.)

Advogato Feedback

I get very little feedback from this weblog. I know people read it because every once in a while I post an entry which generates lots of response (for example, the first one on solar thermal energy). Maybe this is because my entries are so obtuse that people aren't sure what to make of them. Or perhaps it's because I've made my email address so difficult to find. I had to do that, unfortunately, due to a deluge of not only spam but non-spam BitTorrent tech support requests. I simply couldn't keep up with them, and now make the assumption that anyone who I really want to hear from will make the effort to find my email address. I hope I don't lose too much important mail this way.

Spam Filtering

Speaking of spam filtering, I've now basically gotten my problem under control with the following filters - anything with 'dsl' or 'cable' in a Received: line but not in the From: goes to /dev/null. Anything with 'unknown' in the Received: line gets chucked. Anything with a locally tacked-on Message-Id: which isn't From: a locally hosted domain goes to /dev/null. And finally, anything which matches any of a very long list of bounce formats or bounce subject lines gets chucked.

I've taken this aggressive approach to spam filtering because even small amounts of spam were making me delete real mail thinking they were spam. Unfortunately people with even slightly dubious mail setups are likely to have their mail to me /dev/nulled now. And of course I never get bounces any more. I hope I don't lose too much important mail this way, but I undoubtedly lose some.

Gambling on Wall Street

The Springfield daily newspaper, the Daily Star, reported that their local baseball team was slumping, and had missed the spread five games in a row (which was true). Richard Smallbrain, CEO of the Company of America, wrote a scathing op-ed piece criticizing the paper for tainting its sports coverage with gambling. Smallbrain then also mentioned that his company is a a growing part of Springfield's economy and has beat wall street expectations three quarters in a row.

How to make money off of terrorism

The traditional spy novel scenario for terrorists profiting from their work is quite dubious. Usually the scenario is that the terrorist shorts the stock of a public company before attacking it. This is a bad strategy on a number of fronts. To begin with, shorting requires that you place stock or cash in reserve, thus limiting the amount you could possibly make to a small fraction of the amount you can front. Further, the potential upside of a short is capped at the amount you get up front, thus limiting how much you can make that way even more.

Those problems can be mitigated by using puts instead of shorts, but a much more fundamental problem remains. Attacks frequently fail, and even if they do succeed they often do a lot less damage than you expected. The rebound of a stock after it shoots down can leave it higher than it started. Plus, to reliably reduce the value of a public company requires doing a whole lot of damage, and some people have moral objections to doing that.

There is a much more reliable market-neutral way to make money off of terrorist attacks. First, go long and get puts on a company's stock, with strike price at the current value and maturation times for both on the same day as far in the future as possible. Now you will be out some money and have an interesting bet going where the more the company's stock moves, in either direction, the more money you make. (A nice benefit to this approach is that options with a strike price of the current value tend to be much more liquid than the more extreme ones). If you were to hold onto these options until maturity, this would be a very risky bet, but you aren't going to do that - if you unload them in just a day or two, the bulk of change in the value of your options is going to be in the volatility level of the stock, so even if the stock price is back where it started, if the volatility has gone up you'll make a substantial profit.

Next, set off a smoke bomb in the company's main plant. If that isn't your style you can just give a few ben franklins to your friend who's about to appear on CNBC to get him to say that there are rumors that the company is about to be acquired. In a day or two everyone will probably have figured out that whatever mischief you started was no big deal, so the stock will likely go back to where it started, but in the interim volatility will have gone through the roof, so you can unload the stock with a fat profit.

If you can't be bothered setting off smoke bombs, or happen to not want to do anything illegal, there's a perfectly legal technique based on this approach which makes money due to an artifact in the way that volatility is calculated. In general volatility is calculated by averaging it over the last N days. You can search for stocks which just so happen to have had a lot more volatility over the last N/2 days than the preceding N/2 days, then long and put them, wait N/2 days, and unload your positions. Since the first half of the range will now have passed, and the volatility level in the just passed N/2 days is likely to have been between the two values, the volatility measurement will now be higher, and you can probably unload your position at a profit.

The Recursive Universe

ANKOS follows a remarkably similar format to The Recursive Universe, a much older, and much better book. The Recursive Universe is much more rigorous, uses Conway's life, and doesn't have all that pompous bullshit which ANKOS is notable for.

A funny tangent - another book by the same author, William Poundstone, gives the formula for KFC's secret spices: salt, pepper, and MSG.

The automata I mentioned in my last entry is rule 54, described on pages 696 and 697 of ANKOS. The simple-looking diagrams on page 697 are deceptive - that apparent simlicity only happens on a large scale, there's a whole lot of complicated churning which goes on before things settle down.

Codeville

Codeville has been progressing rapidly, and is self-hosting and able to talk to remote repositories.

108 older entries...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!