# Rebooting Ourselves

It was a fairly rough week. Thus, over this weekend I thought about re-examining and resetting various procedures and things I do, as opposed to actively filling my time with activities. This reminded me of a Humans of New York post I came across several years ago:

“I’m rebooting my life entirely, again. It’s time for Andrew 5.0.”

In computer science, semantic versioning is a system for identifying different versions of software products in a standardised way. Under this system, a product’s version is an ordered triple of nonnegative integers written $major.minor.patch$. This is typically used for software, though the definition does not seem to require it. The system discusses changes in terms of a public application programming interface (API), which specifies what functionality the product offers.

In terms of software, a SQL database’s API could include the types of queries that may be processed. For MCMAS-Dynamic, the public API would include the details of the modelling language it is able to verify properties for. A non-software example could include a simple kettle; the public API could include how one adds or removes liquid, how one turns it on or off, and possibly alarms or other feedback mechanisms for when the liquid has boiled.

When a new version of a product is released, the version number is increased (in lexicographic terms). How this increase is done depends on the types of changes since the previous version:

• If the public API is ‘broken’, meaning that previously valid ways of using the API are no longer valid or accomplish different things, then the change requires a major version bump. To do this, the major version is incremented, and the minor and patch versions are reset to 0 (e.g. $7.5.1 \leadsto 8.0.0$). For example, if the kettle used to play an alarm when it the liquid was boiled and this was a part of the public API, then the major version should be bumped if this functionality is removed. (In particular, if the API did not specify that the kettle had to play an alarm, this change might not warrant a major version bump.)
• If new features are added without ‘breaking’ the API or there are non-trivial internal improvements, the change leads to a minor version bump. The minor version is incremented and the patch version is reset to 0 (e.g. $7.5.1 \leadsto 7.6.0$). For example, if the new version of the kettle is substantially more energy-efficient, then that could be a minor version bump.
• If something was broken and has been fixed (without changing the public API), then the patch version should be incremented (e.g. $7.5.1 \leadsto 7.5.2$). For example, if the kettle previously rang an alarm twice when the liquid was boiled even though the kettle’s API specifies it should only ring once, then a change that makes the alarm only ring once could be part of a patch version bump.
• Multiple changes in aggregate should be evaluated in aggregate. In most cases, the largest magnitude of all constituent changes applies, though generally speaking this is not true (consider one bugfix plus two changes, one which breaks the API and another that reverts that change – that is a patch bump, not a major bump).

Generally, making a more aggressive version bump than would be required for one’s change is acceptable, though it can confuse users. In particular, I tend to expect backward-incompatible changes when facing a major version bump; not finding any can be surprising and confusing.

The sentiment of the quote sounded like it was a major version bump. Defining an API for one’s life is obviously very difficult; even if one tries to use a lot of abstraction, I find that there are just too many facets. Rather loosely, our API might be split into a bunch of micro-services. We can treat physical needs and bodily functions like breathing and digestion as infrastructural. These services might then focus on the range of activities we involve ourselves in, or range of activities we could involve ourselves in. For me personally, this could include software engineering, getting along with other people, finance and budgeting, computer science, writing, puzzle solving and so on.

Hopefully, I would imagine that we chew through a lot of patch versions as we continue to improve skills. Today’s release notes could include “Jeremy knows a little bit more about thread pools” (I read a chapter of Java Performance Tuning today over a post-lunch coffee). Minor versions would also be relatively common; this wouldn’t be from today specifically, but “Jeremy can vaguely attempt a Balance Loop puzzle” is probably pretty recent, extending the sudoku and other puzzle-solving features.

Depending on how we define the API, major version bumps could be very common. It is typically important to be relatively disciplined with breaking changes in an API in a software engineering context, as clients may often depend on one’s product in non-obvious ways. While others’ dependencies on us can indeed be non-obvious, I think one factor that changes things is that our systems seem to be ephemeral whilst program code is not. A codebase left as it is over years or centuries retains its capabilities (admittedly, finding suitable infrastructure to run the product might be an issue).

On the other hand, there is some evidence that we lose skills that are underutilised with time. I used to play Dance Dance Revolution quite a lot and could probably pass an arbitrary level 15 song as well as some 17s; I doubt I can do that today as I haven’t played in a few years. The ways we interact with others or manage our finances may change as our personal environments change as well; for example, if I moved away from the UK, I would not be able to allocate my investments the way I do now, because I would lose the ability to use ISAs (and probably most other forms of UK-specific tax-free savings). This may even happen without action (for example, if the UK government changes how ISAs or tax-free savings work) – though you could argue that declaring the use of specific vehicles in one’s API might be too specific and implementation-dependent (“I will use tax-advantaged accounts that are valid in my location appropriately” is maybe better).

In light of the above, I would be a bit laxer with what constituted a ‘breaking change’, which pulls things back toward subjectivity which I think semantic versioning was trying to avoid. I might regard myself as having major version 2 right now; I could consider everything up to and including my second year at Imperial as version 0, which is typically used in development to refer to a pre-release period of rapid iteration. Although National Service and/or moving to the UK for studies did bring about nontrivial changes, I really didn’t know what I wanted to do at that time (not that I know now, but there is at least a vague direction).

The Google internship was probably the turning point for version 1; that also coincided with several major changes with regard to finance, investment, philosophy and priorities. I’d call the second major change to be when graduating from Imperial and starting at Palantir; even then, I’d regard the first set of changes to be more fundamental. The re-examination I did over the weekend is actually probably a patch release (or maybe a minor that improves several non-functional characteristics); it certainly doesn’t warrant a major version bump.

# Algorithmic Modelling – Codenames

Codenames is a board game designed by Vlaada Chvatil which tests communication. The game is played with two teams; each team splits itself into clue-givers and guessers.

There is a board of 25 cards, each with one (or more) words on them. Of these cards, 9 are owned by the first team, 8 owned by the second team, 7 are neutral and one is the ‘assassin’.

The clue-givers attempt to communicate to the guessers which cards are owned by their team. This is done by giving a one-word clue followed by the number of cards N corresponding to the clue. The rules establish some bounds on allowed associations (for example, ‘sounds like’ clues are not allowed).

I don’t know how much time went into selecting the words to appear on individual cards, but there are certainly many words in the deck that can be interpreted in many ways, which makes the game fun. For example, I can think of quite a number of ways to clue BOND (COVALENT for unambiguity; DURATION, ASSET or DEBT for the debt; JAMES, AGENT or SEVEN or even at a stretch something like CASINO for the character; FRIEND or FRIENDSHIP; STREET or TUBE; CONTRACT, PROMISE or WORD for the idea of a promise; ADHERE or CONNECT, among others). Which one I might pick would depend on the other words on the board.

Guessers then identify up to N+1 cards they think their team owns. This can be based on the entire history of clues given, not just the previous clue. These cards are guessed one at a time; a team is only allowed to make further guesses if they guess ‘correctly’ one of their team’s cards. Teams may refrain from making all guesses.

The game ends either when all cards owned by a team are revealed (that team wins), or if a team reveals the assassin (that team loses).

In practice, clue-givers will need to consider all cards, not just the ones their team owns. The penalty for ‘failure’ varies; the assassin is an instant loss, and revealing a card owned by the other team is also bad. For example, with the cards APPLE, BANANA and GRAPE it would be very tempting to declare (FRUIT, 3) as a clue; yet, if KIWI is owned by the other team (or worse, is the assassin) it might be dangerous.

However, if the other team has already revealed that KIWI is theirs (e.g. with another clue, maybe SOUTH or BIRD) then the FRUIT clue becomes safe. Thus, pre-computing a strategy at the beginning of the game (e.g. by partitioning the eight or nine clues owned into several logical groups while avoiding other words) may not be optimal.

I tend to consider making an effort to win to be a key part of games, and thus what moves may be considered good also often depends on the state of the game. For example, if the opposing team has just one card left, I will give a broader clue that may have more tenuous links in a ‘do or die’ effort to finish on this turn. A less extreme example would be attempting weaker links if behind, or perhaps playing slightly more conservatively if ahead.

Mathematically modelling Codenames can be tough. We can try modelling the game state as a tuple $(O, E, N, x, h, f_O, f_E)$ where $O, E, N$ are sets of the remaining clue words our own team has, words the enemy team has, and the neutral words, $x$ is the assassin, $h = (t,w,n)^+$ is the history of the game, and $f_O$ and $f_E$ are preference functions of the form $h, w, n, O, E, N, x \rightarrow P$, returning an ordered list $O \cup E \cup N \cup \lbrace x \rbrace$. $(t, w, n)$ is a clue meaning that a given team gave a clue word and hinted that some number of cards was relevant. This already abstracts two difficult parts away – ordering the clues, and determining how many of the top preferences to pick.

I think the preference functions need to take into account previous clues from both teams; if a previous clue could clearly have corresponded to two words and I picked the wrong one, it might be fairly high on the list even if unrelated. Similarly if this scenario happens to the opposing team, I would probably avoid the word that would blatantly be theirs.

The notion of degree of confidence also isn’t captured as well in our ordering; going back to the fruit example, having a clear ordering would imply that clues for less than 4 items could reliably result in correct guesses (if we knew that APPLE was by a small margin the best pick, we could safely and confidently give (FRUIT, 1) to clue it, which seems wrong). One could imagine modelling these with selection probabilities, though things would be even more complex.

The above representation still seems computationally difficult to work with. The evolution of the preference function as one moves from one state to another is unclear (so in that representation it is fully general), making lookahead difficult. It doesn’t seem like a greedy choice is always best; for example, given eight clues that are reasonably divisible into four pairs, a clue for 4 words taking one element from each pair might be a bad idea if the other words can’t easily be linked.

We can proceed by simplifying the preference functions; a simple approach could be that for each $w, n$ each team has a persistent preference function that returns an ordered list of $O_0 \cup E_0 \cup N_0 \cup \lbrace x \rbrace$. The preference functions during the game then return the subsequence of that list that contains strictly the words still left in the game. This of course doesn’t take into account past information or clues from the other team.

With this, we can attempt to solve the game using standard techniques; assuming that the vocabulary of clues is bounded (let’s say it must be from the Linux dictionary), a game state is winning for the current team if there exists some word for which the preference function returns everything in $O$ as a prefix. A state is losing if all moves in that state produce a state which is winning for the opposing team.

We can generalise this to a simple probabilistic model as well; the preference ‘functions’ instead return a discrete random variable that indicates either guessing some word or passing. A simplified model could then, at the start of the game, assign weights to each candidate indicating the relative probability that candidate would be selected. These can be normalized to account for a pass probability. As words are removed from the board, the probability of the remaining words being selected scales (we can imagine a simple rejection-sampling where we discard words that aren’t actually on the board any more).

The algorithm for the probability that we get a win from a given state is then slightly more complex (though I think still reasonably covered by standard techniques).

# Likelihood Estimation

One of my team-mates introduced another interesting question over lunch. Working through it reminded me of some of the statistics problems I struggled with at Imperial, specifically during Intelligent Data and Probabilistic Inference. It reinforced that in spite of scoring 90 for that course I’m still not confident I knew what I was doing then (or now).

Suppose you have a symmetric triangular distribution of unknown width and mean. Given that the distribution has yielded three independent samples of 2, 4 and 5, what is the expectation of the mean?

The triangular distribution can be used as an estimate for something which is known to be bounded both above and below, that also takes into account a value known to be the most probable. Some argue that it is the simplest distribution satisfying these (though one could argue that a cosine or some kind of truncated normal might be more applicable).

The instinctive answer I have is simply the mean of the samples, or $\frac{11}{3}$, though I was suspicious as probability and statistics often yield non-intuitive results.

The distribution is named as such because it has a triangular probability density function; because of the laws of probability (area under the function must be 1), specifying the minimum, maximum and mean is enough to uniquely identify it. Supposing we have a minimum $a$, a maximum $b$ and a mean $c$, this yields a pdf of:

$f(x) =\begin{cases} \dfrac{2(x-a)}{(b-a)(c-a)} & a \leq x \leq c \\ \dfrac{2(b-x)}{(b-a)(b-c)} & c \leq x \leq b \\ 0 & \text{otherwise} \end{cases}$

We are only dealing with a symmetric case, so we can set $c = \frac{a+b}{2}$ which cleans things up a little:

$f(x) =\begin{cases} \dfrac{4(x-a)}{(b-a)^2} & a \leq x \leq c \\ \dfrac{4(b-x)}{(b-a)^2} & c \leq x \leq b \\ 0 & \text{otherwise} \end{cases}$

Based on our observations that we have three samples of 2, 4 and 5, we can construct the likelihood that a given triangular distribution gave rise to a certain result. While the probability sampling a given distribution resolves to a precise value is infinitesimally small, we can still compare them in relative terms using the density functions. We can write this as

$P(2,4,5;a,b) = f(2)f(4)f(5)$

Expanding this term will depend on where exactly 2, 4 and 5 fall in our triangle. Let’s work out the most promising case (where 2 falls on the left of $c$ while 4 and 5 fall on its right); the rest are left as an exercise to the reader. In this case, we have

$P(2,4,5;a,b) = \dfrac{4(2-a)}{(b-a)^2} \times \dfrac{4(b-4)}{(b-a)^2} \times \dfrac{4(b-5)}{(b-a)^2} = \dfrac{64(2-a)(b-4)(b-5)}{(b-a)^6}$

At this point, we notice the original question needs a bit more specification. We aren’t given what the distribution of possible values of $a$ and $b$ is. One way of getting around this is just to pick a uniform distribution; however, that isn’t quite defined over the real line. We can for now simply find the maximum likelihood estimate for $a$ and $b$.

Alternatively, if we give prior probability distributions for $a$ and $b$, we could also use the samples as information to get a posterior distribution. Usually we would pick a conjugate prior distribution that wouldn’t fundamentally change even when accounting for the sample; I didn’t find one for the triangular distribution, though.

If we want to find the most likely distribution, we seek to find an extreme point; this can be done by taking partial derivatives (and this expression actually lines up quite well with the quotient rule). There is a fairly standard ‘trick’ for handling these, though; since the logarithm is a strictly increasing function, we compute the log-likelihood instead. The maximum of the logarithm will also be the maximum of the original function. Using the laws of logarithms, we get something a lot more tractable:

$\log P(2,4,5;a,b) = \log 64 - 6 \log(b-a) + \log(2-a) + \log(b-4) + \log(b-5)$

Computing the partial derivatives is then straightforward. We then set them to zero, and solve the resulting equations simultaneously; this yields

$a, b = \left( \dfrac{1}{3} \left( 4 + \sqrt{\frac{2}{5}} \right), \dfrac{1}{3} \left( 16 - \sqrt{10} \right) \right), \left( \dfrac{1}{3} \left( 4 - \sqrt{\frac{2}{5}} \right), \dfrac{1}{3} \left( 16 + \sqrt{10} \right) \right)$

We’ll want the second pair of solutions; the first actually has $b \approx 4.279$ which is no good (we need $b > 5$). Interestingly, the mean of that triangular distribution is then $\dfrac{2}{15} \left(25 + \sqrt{10} \right) \approx 3.75497$ which is not quite $11/3$.

Indeed, though, the log-likelihood we get with these values of $a$ and $b$ is about $-4.74053$. Indeed, if we look at the family of distributions with $a = \frac{11}{3} - \alpha$ and $b = \frac{11}{3} + \alpha$, the best we get is about $-4.7473$.

# On Deckbuilding Games and Slay the Spire

Deckbuilding is a genre of games where players start with a (usually) standard deck of cards and then improve it over the course of the game. This can involve acquiring new cards that are usually more powerful than the initial set of cards and/or synergise in better ways, upgrading existing cards, or even removing cards that are weaker or less relevant so that one is more likely to draw the (better) remaining cards.

These games typically offer some replayability because the sequence of decisions one may have on how one can improve one’s deck differs from game to game; what it means for a deck to be successful can also vary depending on what the other players are doing.

Slay the Spire is a player-versus-environment RPG where combat is driven by a deckbuilding mechanic; players start with simple offensive (Strike) and defensive (Defend) moves plus possibly a few class-specific cards. The combat is turn-based. On a player’s turn, the player draws 5 cards. Cards have an energy cost, and players initially have three energy per turn to play as many cards from their hand as they want. Of course, there are cards and other mechanics that can be leveraged to obtain additional card draws or energy. Players are also shown their opponents’ next moves, which allows for some degree of planning; a simple example of this could be deciding to eliminate a specific monster in a group, because it is about to attack.

In terms of gameplay, the start of the game does feel relatively rudimentary as the player always has the same or a similar deck. However, each time a player defeats a group of monsters, he is given the option (but not the obligation) to add one of three cards to his deck.

The options that come up in the first few rounds will typically shape how the deck develops. For example, while most cards can be upgraded once only, there is a specific card called Searing Blow that may be upgraded multiple times; eventually, it can develop into a card that costs 2 energy but yet deals far more damage than Bludgeon, a 3 cost card that deals pure single-target damage. It is a viable strategy to build a deck around this, eliminating other cards from the deck so that one draws it on every turn; there are cards like Double Tap (which, for 1 cost, doubles another attack) that can further enhance this type of deck.

Conversely, I frequently play in a style which relies on combining cards that give a constant strength bonus to all attacks along with cards that attack multiple times for small amounts of energy. That said, some degree of flexibility is important, as the choices given to the player will be different on different plays; being wedded to a single strategy can be dangerous, as specific key cards may not be available.

Players can also acquire relics which further influence game mechanics; these can simply provide boosts (such as “every 10th attack does double damage”), make certain styles of gameplay more attractive (“the third Attack card you play each turn boosts your Dexterity by 1 for the rest of the combat”) or even significantly change game mechanics (“retain your hand rather than discarding it” or “if you empty your hand, draw 1 card”). These are random (and apart from at the shop / rewards from winning boss battles, players aren’t really given options here) so, as before, planning on specific relics becoming available is also typically not a good solution.

Winning the game unlocks a new-game-plus mode called ascension; players start at Ascension 1, which increases the rate at which elite enemies spawn. Winning the game on Ascension 1 unlocks Ascension 2, which applies the restrictions of Ascension 1 and makes normal enemies do more damage. This increases incrementally up to Ascension 20. I’ve got up to 16 on one of the characters. At high levels there’s not very much room for error; I have had a 10 win-streak without Ascensions, but struggle with high Ascensions quite a bit. I think I tend to force my deck to fit a certain mold perhaps too early on; this can get scuppered if I subsequently am unlucky.

Another challenge a player can take on, as with many other games, is speed-running, or attempting to win quickly. Playing fast (as shown in the screenshot above) limits one’s time for decision making. For example, I normally plan my entire route through the map for each level at the beginning of the level, but that of course takes a bit of time. A normal, more relaxed game can easily take 30-40 minutes, especially if I’m playing with a relatively less aggressive build.

I’ve played the game for about thirty hours or so. It has been enjoyable, and the Defect character (an automaton that manipulates a queue of orbs) is particularly fun, if difficult to use. In terms of educational value I think the game demands a decent intuition of probability, as well as understanding how cards may work together. There are some synergies that are explicit or clear, but others are often less obvious and require some thought/experimentation.

# Travelling Songs

For a recent Palantir event, I was asked to state a song that I enjoy listening to whilst travelling. I had a few candidates in mind, but went with This Town by Niall Horan. I didn’t have to justify my choice – but I had several reasons in mind.

Most of my travel for work is done solo. This makes sense for going on-site, but even for larger company events and conventions I find that I end up travelling on my own fairly often. Also, quite a lot of my travel requires flying; even when it is not long-haul, the overhead of going through airports and ensuring that I am on time already adds quite a bit of travel time. I thus find that I have a fair chunk of time where I spend time thinking and reflecting on how things have been going. I thus picked a quieter, more downbeat song which gives me enough space to maintain a thread of reflective thought. That said, interestingly the other songs I had in mind were unlikely to be as conducive to that!

I should count myself fortunate to have travelled quite a fair amount for work (that said I’m sure there must be people who are sick of excessive travel). One “class” of songs that might be relevant for some would be a sense of adventure and anticipation; for me personally on work trips that is a bit less relevant. Many trips are to places I’ve already been to (I guess the company only has a few major offices) – in the past three years I think I have visited Palo Alto about eight times. Of course, that may change with university on-site recruiting picking up; I first visited both Denmark and Croatia on these trips, and I did enjoy those travels a fair bit.

I think of myself as fairly ambitious. There are often more things I like to do than have the time to execute on (and hence metaphorically “words I never got to say the first time around”). In some ways, this is especially true of my travels to Singapore, as I’m there only about three to four weeks a year out of 52. Separately, work trips often involve very intense iteration (that tends to be what motivates the trip in the first place), leaving little time to explore the place I’m in.

Thinking about it, the song does also mention the act of travelling (“drive highways and byways to be there with you”). I didn’t pick the song for that reason, though – identifying work as the thing one is always chasing is dangerous.

The other songs I had in mind included Fury of the Storm by DragonForce; that follows the “sense of adventure” theme. That song also brings back memories of my first internship at Palantir, which involved a decent amount of travel. I’m not sure I could imagine listening to metal for ten straight hours or so, though. I also considered James Arthur’s Back from the Edge which I featured in a review about a year and a half ago; travel certainly doesn’t provide a clean or blank slate, but it does provide a temporal boundary for how I categorise things, I think.

During the event, nine other engineers volunteered their choices. There was a fairly broad range of picks, ranging from rather bubbly dance pop (Elastic Heart by Sia) to harder rock picks, and a couple of alternative choices I was completely unfamiliar with. It was nice to see this variety, though.

# Algorithmic Problem-Solving: On Pigs and Poison

A teammate asked me a computer science / algorithm question over lunch. It took me somewhere between 30 to 40 minutes of thought and discussion with teammates to solve the problem, inclusive of writing about 20 lines of Java; I can see it being a kind of ‘brain teaser’ interview question (and thus generally best avoided). That said, genuinely not having heard this problem before, I think it was interesting to see the thought process I went through to get to the final answer.

You have 1,000 buckets of water, 1 of which is poisoned. It is known that the poison if ingested will kill a pig within 15 minutes. You have one hour to determine which bucket contains the poison. What is the minimum number of pigs that you need, and how would you do it? (Eventually, of course, you want to generalise your answer.)

After some initial “lateral thinking”-style questions (does the poison only kill pigs? is the death timing exact?), I determined that it was intended to be a genuine algorithms problem. As a computer scientist, I then thought of binary encodings. This gives a quick solution to the case where you have just 15 minutes to determine which bucket is poisoned – if you convert each number to a 10-bit binary number (so the first bucket is 0000000000, the second is 0000000001, and so on) and give the first bucket to no pigs, the second to pig number 10, the third to pig number 9, the fourth to pig numbers 9 and 10 and so on, the final state of the pigs 15 minutes later allows you to determine the poisoned bucket. If we used this method and only pigs 5 and 7 died, then the poisoned bucket has binary representation 0000101000, which corresponds to bucket number 40. In any case, we know the answer is bounded above by 10.

I then considered ways of extending this solution given that we can run four trials instead of one. I did consider partial experiments, but didn’t see a way this would be helpful. One quick possibility we came up with was to linearly split the buckets among a number of pigs to cut down the search space – though this risks losing one pig at each iteration. Still, we determined that 6 pigs would work:

• On trial 1, you have 1000 buckets and 6 pigs – divide into 7 groups of at most 143.
• On trial 2, you have 143 buckets and possibly 5 pigs – divide into 6 groups of at most 24.
• On trial 3, you have 24 buckets and possibly 4 pigs – divide into 5 groups of at most 5.
• On trial 4, you have 5 buckets and possibly 3 pigs – the binary method can distinguish 8 buckets.

Yet, this same method wouldn’t work with 5 pigs. We were ready to settle on 6 as the answer, but the question asker revealed that it was possible to do better than 6. The idea of imbalanced groups then came up – the ‘no risk’ group of buckets should be larger, because in that case we could guarantee that we would still have all our pigs if we needed to investigate that group.

I guess I haven’t done algorithm interviews for a good while, and it thus took me to this point before I thought of setting up a recurrence relation. Define $W(n, p)$ as the maximum number of buckets distinguishable with $n$ trials and $p$ pigs remaining. I then set up this relation:

$W(n, p) = \begin{cases} 2^p & n = 1 \\ 1 & p = 0 \\ W(n-1, p) + pW(n-1,p-1) & \text{otherwise} \end{cases}$

The last case comes about because we can safely allocate a group of $W(n-1, p)$ buckets to be given to no pigs, since with one fewer trial we can distinguish between them. For each of the pigs present, we need to prepare to continue the investigation with one fewer trial and one fewer pig, hence $pW(n-1,p-1)$.

This is more efficient, but doesn’t quite get us there yet. I noted that $p(4, 5)$ was somewhere in the 800s, which established that strategies based on risking one pig in every round apart from the last would be insufficient. Thinking a little more about it, I realised that in the extreme case, you could always have a special bucket each round that you gave to all pigs – if they all died that round, we would know that bucket was poisoned. However, you couldn’t have more than one of these per round – if they all died, you wouldn’t know which bucket was the cause.

More generally, you could split the groups of buckets into groups that are given to zero, one, two… up to $p$ pigs, where $p$ is the number of pigs still left. The groups given to smaller numbers of pigs could likely be larger, to account for the additional resources available in later rounds. The following recurrence relation then drops out:

$W(n, p) = \begin{cases} 2^p & n = 1 \\ 1 & p = 0 \\ \sum_{i=0}^p \binom{p}{i} W(n-1, p-i) & \text{otherwise} \end{cases}$

This actually has a closed form solution. I didn’t notice it when looking at the recurrence, though it became apparent when I coded up a program to calculate the required $W(4, 5) = 3125$. I was surprised to see how much additional discriminatory power five pigs had, though four wouldn’t be sufficient. Interestingly, five pigs and three periods were sufficient. The general closed form solution is simply $W(n, p) = (n + 1)^p$ and our argument provides a method for actually identifying the relevant bucket.

Finally, an interesting challenge here was to establish that it wasn’t possible to achieve this with four pigs (so that 5 would be the minimum). One way to do this was to reason in terms of information theory – a pig either survives all the way or dies after a given round, and then it stays dead. This is $n + 1$ many possibilities, and there are $p$ pigs, so it seems that we can’t do better than $(n+1)^p$. Clearly $5^4 = 625 < 1000$ so four pigs isn’t enough; also, this expression matches the value obtained by our recurrence-based method, suggesting that that is indeed optimal.

# Tactics and Strategy (2018 Q2 Review)

I generally interpret strategy to refer to thinking about broader goals and general approaches for achieving these goals; conversely I think of tactics as finer-grained methods for effectively completing smaller tasks (that hopefully contribute to fulfilling one’s strategic goals). As a software engineer who works with databases, strategic concerns could be “the database should be able to serve requests quickly”, or “you shouldn’t be able to shoot yourself in the foot too easily”; tactics could involve using B-trees or clever data structures, or being careful about what APIs one exposes respectively.

For individual endeavours and also at work, I often need to play both a strategist and a tactician. I’m responsible both for determining what to seek at a high level and for implementing the required steps. There’s some tension in devoting resources towards getting better at either of these; I’d say the skills are certainly distinct (though not independent; good strategic thinking requires knowledge of what may be tactically plausible, and one should implement suitable tactics to optimise for outcomes that one strategically favours).

Strategically things have been a bit foggy this quarter. To some end there has been progress in terms of general quality as a developer, at least by some metrics. Getting better technically is good, though it seems to have been more of a focus than I remember prioritising it to be.

I have to some extent been struggling to find satisfaction in things, as well (there was a very relevant series of sermons on contentment in church – but practical application is often much harder than theory). I think some of this was a change from working with a preponderance of ‘shiny’ features leading to patent applications or other forms of explicit external recognition. I even forgot about some features that were clearly valued by other teams or people until they reminded me that I wrote them when discussing what I’d been working on in general!

Outside of work, also, I need to find strategic direction (there hasn’t been very much). With regard to computer science, I need to think where I go from here. AAMAS’18 in Stockholm is coming up and I’ll be presenting there about model checking LDLK on finite traces. This paper was very challenging to write; differently from the first two, I actually had to develop a substantial amount of novel content. I found myself guilty of excessive handwaving in the original proof presented in the thesis – there was a detail which I claimed to be trivial that turned out to require a full column of argument! I also have one more paper to write. I’ve also not been doing as much independent study of both computer science and software engineering as I would like.

In terms of finance, one of the good things about index investing is that there isn’t that much to do once the system is set up. There’s even less if you’ve automated some of the workflows (as I have)! After that, much return is subject to the random walk of the markets – with the (I’d say justified) belief, of course, that that walk trends upwards. The main ‘action’ required then is to stay the course, which requires patience and persistence.

Markets have been a bit of a mixed bag. Equities have gone up a lot apart from emerging markets, but a good chunk of this is likely to be currency effects as the pound fell hard. The usual table follows:

(Disclaimer: I hold the Fidelity World Index Acc, Vanguard LS80, iShares EM index, iShares property index, BTC, GBP and USD in various quantities, among other things.)

Spending has exploded (well, relatively) this quarter. Some of this is due to periodic expenses with a period greater than three months coming in in this quarter – renewing the servers and domain name for this website and brokerage fees. There is also some (I’d say permissible) lifestyle inflation too – frugality or cheapness to the detriment of daily happiness is usually not something worth doing unless one is forced into that position.

My budget also has a category called ‘Learning and Development’, which includes books for reading and fees for various educational activities (such as conferences, lessons, exams and the like). This swelled in Q2. I haven’t been reading substantially more. Most of this was the fees for AAMAS’18, FLoC’18 (more logic!) and music lessons.

I’ve made a conscious decision to spend more time outside of work on various recreational pursuits (even if the precise details of these aren’t clearly directed). I’ve gotten faster and better at solving logic puzzles and Sudoku; it’s difficult to come up with clear performance metrics, but I’m usually able to score in the 70th percentile or so in online contests, and can occasionally squeak into the 80s in broader contests (where the average skill level is slightly lower). I know that I was in the 20s or 30s when I first started trying these. I ranked 42 of 157 in the UK Sudoku Championship 2018, and less impressively 50 of 141 in the UK Puzzle Championship 2018.

I’ve continued writing here – a bit less frequently than I would like, admittedly. I also had my first vocal lesson in about three years or so – it’s good to be back. To some extent I strive for quality in what I do, even in recreation (I told my teacher “I enjoy sounding good” – I didn’t go as far as “I only enjoy it if I’m sounding good”, though that’s probably more true than I like to admit…)

I traditionally feature a song I’ve listened to a lot over the quarter in these reviews; I’ve done this for about five years now, and it can be interesting to see what I was listening to several years ago. In many cases I liked most of the songs then and I still do now; I tend to select quite heavily for a meaningful message or idea, and I like to think I’m quite resistant to faddish qualities in songs.

I first heard this song on a plane (like many others!) when flying from London to Singapore for a one-week vacation in May. I have listened to a couple of songs by the British boyband The Wanted before. One of their heavier pieces, Warzone (about leaving an abusive relationship) featured in my 2014 Q2 review, where I decided the 90- and 100-hour weeks I worked then were a bit too much of a cost. I also quite like Chasing the Sun, and a couple of their album-only tracks as well.

Unfortunately, the band dissolved a few years ago. They weren’t quite as successful as One Direction, so as far as I know only one member, Nathan Sykes, has continued with a solo career. I didn’t actually know this until I came across his new album Unfinished Business (yes, quite apt). The opening track is titled Good Things Come To Those Who Wait. It reminded me a fair bit of James Arthur’s Back From The Edge both aurally and thematically.

Some people run and fall
They don’t even walk at all
There’s nothing to prove, just to feel you exist

It’s important to balance aggressive implementation (“running”) with careful evaluation of whether what one’s implementing is relevant to what one wants to do – especially if the path ahead is unclear. In some cases, it can be better to move more slowly and carefully.

The last line sounds weird, but in context is a reason why the speaker takes his time with things. The converse of feeling a need to prove oneself to others is understandable. I do fall into that trap sometimes, though I know it can be a dangerous thing to do.

More generally, the idea that good things come to those who wait can be contentious. I think it depends on what kind of waiting is involved – waiting to strike when opportunity arises is great (which I think is the point of the song – “I prefer to stick when the others would twist”), but idle, muddled waiting might not work so well.

As far as the album is concerned, I also found I Can’t Be Mad to be excellent. There were also a number of other good songs; I think it was a reasonably strong offering.

# Scoring Points

I think it would be reasonable for me to describe myself as competitive. Through my years at university I had a goal of scoring a GPA of 90 percent (where a first-class degree is awarded at 70 percent); I added a clause of working a part-time job later on. I’ve enjoyed participating in a variety of contests from young, both in terms of work (Singapore Math Olympiad, ICPC) and play (Sims 4, music exams, puzzles).

Speaking of puzzle contests, I participated in the UK Sudoku Championship 2018 at the beginning of this week. Participants were given 2 hours to solve 16 puzzles of varying difficulty. To keep things interesting, the puzzles aren’t just standard or “classic” sudoku, but also feature additional constraints – for example, the highest-scoring puzzle had an additional constraint where both major diagonals had to have the digits 1 to 9 once each as well. I solved 13 puzzles, which led to a placement of 42 out of 136 (or 157, depending on whether one considers zero scores). I finished the remaining puzzles after the time ran out and would have needed about 2:20 overall; the fastest solver cleared everything in 1:09, just under half that!

I think one of my weaknesses can be a tendency to over-index on pursuing things that I think are worth doing. This may not work out so well if my thoughts turn out to be incorrect or misguided, or if the pursuit causes unpleasant side-effects. Writing this reminds me of the 90 to 100-hour weeks I used to pull in second year when studying for the exams then.

Anyway, one of the things I’ve been looking at recently has been building up a healthy portfolio. I had a conversation with my parents today, and one of the things that came up as part of the discussion was something I used to do in high school.

In Singapore, most food courts and hawker centers have an economy rice stall. The stalls offer steamed white rice accompanied by various cooked dishes. These include meat-based dishes like fried chicken or Chinese char siu, vegetable dishes and tofu, among others. Ordering from an economy rice stall is typically cheap (as the name suggests); thinking about it, it also bears similarity to the low-cost model for airlines in that one chooses and pays specifically for what one wants, and has flexibility in choosing what is included.

My high-school canteen had an economy rice stall, and I remember budgeting S$1 (now 56p; then probably more like 45p or so) for lunch every day. This would typically result in fairly unhealthy meals, admittedly, with rice plus one hot-dog and a small portion of nuts and anchovies. For comparison, many meals in the canteen ranged from S$2 to S\$3. Note that cooked food in Singapore is generally much cheaper than in London, and food in school canteens is typically subsidised.

Some of this frugality continued when I entered university. I had similar ‘adventures’ in my first year at Imperial, where I somehow maintained a grocery budget of £7 per week (£1 per day) for a full academic term. Things relaxed over time, especially as I convinced myself that I did have reasonable earning power. To be fair, there was increasing evidence of that as I did several internships and part-time jobs while I was at Imperial.

Clearly, if one is trying to build a portfolio quickly, one factor that can be optimised on would be maximising fresh inflows to the portfolio. Minimising one’s expenses and thus increasing one’s savings rate helps with that, of course.

However, aggressive expense minimisation often leads to other appreciable costs in terms of health, happiness and stress. Apart from direct opportunity costs (for example, from foregoing higher quality or safer food), there are secondary effects as well (affecting socialisation, for instance). The mental overhead of needing to evaluate many small financial decisions every day can be significant as well; I’ve found it to be the case in my personal experience.

Having a sizable portfolio can be useful; I don’t think I have to be convinced of the value of financial independence even though I don’t necessarily have early retirement plans at this stage. However, as an end in and of itself it is not particularly satisfying. I’m fortunate in that I haven’t taken on large debt obligations, and right now (though I may regret saying this later) bumping the numbers in some brokerage account or on my spreadsheets is nice, but brings very little marginal happiness.

It may well be obvious that, to quote a blog post I read this week, life is more than compounding money. In general, reducing it to an arbitrary single end is difficult. Nonetheless, when pursuing a goal I sometimes lose some sight of broader things, and it’s thus important to remind myself of this.

It has been said that “what gets measured gets managed”, and for me at least most goals tend to be fairly quantitiative and measurable in nature. I often place these in some kind of OKR framework which often isn’t as friendly to softer, more qualitative tasks. That probably explains to some extent “losing sight of broader things”. Some may have a very clear and specific view of what they want to do, but I’m not there yet.

# On Challenges that Build

On my return flight from Singapore to London, I listened to quite a few hours of music. Two of the songs I listened to and enjoyed at least partially for similar reasons were It’s Gonna Be Me (by NSync), and I Can’t Be Mad (by Nathan Sykes). It’s a bit of a strange pairing as the former seems to be an upbeat, relaxed pop song while the latter is a fairly moody piano ballad. However, the common element I latched on to here was that both songs feature sections that are repeated multiple times, with the vocals developing additional complexity on each iteration (thinking about it this is fairly common in songs that are critically reviewed well, and also in songs I like). For example, in It’s Gonna Be Me there is a line in the chorus which is sung four times over the course of the song, and its complexity develops:

The challenges in I Can’t Be Mad have a couple of changed notes, but also (if trying to reproduce the original) demand different productions of the notes (falsetto vs not, belts, etc). There’s always a risk of adding too many embellishments, though I find expanding upon base melodies can be quite interesting. Singing these, and considering what would be reasonable for my voice (adding a closing run to the last syllable above, for instance) and what would not be (adding a +1 semitone key change after the second chorus in I Can’t Be Mad – original is already awfully hard), can be enjoyable too.

Generalising this, I quite like the idea of “increasingly complex variations on the same theme” when learning concepts and when teaching them. This already seems to happen for many concepts in mathematics. Over the course of an A-level student’s mathematics education, he/she might understand how to write a quadratic expression as a product of linear factors (e.g. converting $6x^2 - 19x - 7$ into $(2x-7)(3x+1)$). This could first begin with expressions where inspection works feasibly. However, students should also be presented with some examples where inspection is extremely difficult or even impossible (though probably only after gaining some confidence with the cases where inspection is plausible). For general expressions, one could try to use both the quadratic formula and factor theorem to factorise something like $6x^2 - 19x - 8$ into $-\frac{1}{24}(-12x + \sqrt{553} + 19)(12x + \sqrt{553} - 19)$. However, there will be some expressions like $6x^2 - 19x + 16$ where the solutions to the quadratic are not real; later, with some understanding of complex numbers, these would make sense. Students will also learn about problems which may not obviously be quadratics but can be written as such (like $x^4 + 2x^2 + 1$); the ability to synthesise the various techniques can then be tested with something like $7x^8 - 10x^4$.

To some extent my Masters project also had this theme – linear time logic, adding knowledge, adding dynamic modalities, generalising that to full branching time logic, and then switching out the infinite traces for finite traces. I haven’t written a course or a book on a computer science topic yet, but I can imagine that there might at least be sections that follow this kind of sequence.

This pattern also occurs a fair bit in many technical interviews I’ve seen as well, where problems start easy, but additional and progressively more challenging constraints are repeatedly introduced. The purposes here could include testing for a breaking point, seeing how candidates react to problems without an obvious solution, or whether they are able to synthesise additional information to come to a solution.

I find that I often learn best by practicing on smaller examples at first, and then (attempting to) generalise their conclusions to larger models, considering when these conclusions may fail or not. Having multiple variations of progressive difficulty can be useful as they can give a sense of achievement as partial progress towards an overall goal is made. Furthermore, I find understanding how changes in the problem scenario leads to the base solution method being applicable or inapplicable to be a key part of understanding as well; there is a clear need to reason about this when considering incremental variations. Going back to It’s Gonna Be Me, for example, aiming downwards at the word ‘love’ and not conserving sufficient air or energy for it might work for the first three passes, but it’s unlikely to on the last round.

There is a risk that the method can be frustrating in that it seems like it is consistently ‘moving the goalposts’, especially if one forgets that the partial goals are partial goals (and starts to think of them as complete ends in and of themselves). The standard I’m using for understanding (ability to critically evaluate applicability in novel contexts) may be seen as a little high. I also haven’t covered how to bootstrap the method (that is, how to develop an understanding of how to attack the base problem before any variations are introduced). Nonetheless I think there are some contexts where this works well. I’ve found it to be useful in singing, mathematics and interviewing at least!

# Colour Rush (Board Game: FUSE, Kane Klenko)

While I’m not sure I would go the full length to say that efficiency is the highest form of beauty, I’d certainly say that I can find efficiency to indeed be beautiful. In controlled environments, I enjoy testing my own efficiency (typing tests, programming and Sudoku competitions, competitive Sims). Many of these environments feature elements of uncertainty, meaning that managing probabilistic outcomes is key to being efficient (in Sudoku bifurcation can sometimes be faster than reasoning through complex logical chains; in a programming contest, you might luck out on some buggy or sub-optimal algorithm actually passing all test cases anyway). I’ve recently enjoyed a challenging game which has probability management at its core.

FUSE is a real-time dice game from designer Kane Klenko. Players play bomb defusal experts who are trying to defuse bombs; this is represented by rolling dice and placing them on ‘bomb’ cards to match constraints. The team rolls some number of dice, and then allocates them to the cards, incurring penalties if some of the dice cannot be allocated. The game itself has a hard time limit of 10 minutes, so quick thinking is encouraged as players get more turns (and thus more rolls of the dice).

The dice are almost standard six-sided dice; interestingly, I noticed that it was not the case that opposite faces of each die added up to seven (2 was opposite 4 and 3 opposite 5, for some reason). The dice come in five colours (red, blue, black, yellow and green), and there are five dice of each colour. Card constraints may involve numbers, colours or both, and vary widely in the difficulty; easy cards have requirements like “two dice matching in either colour or number” or “A – B = 2”, while more difficult ones can involve building a six-die pyramid where each die is a specific colour. The bombs are rated in difficulty from 1 to 6, skipping 5.

Some bombs also introduce ordering constraints, requiring players to build a tower or pyramid (and players are not allowed to build unsupported structures). There is also a dexterity element here, as the penalty for knocking over a tower or pyramid is losing all progress on that card.

I’ve only played solo or in a team of two. Playing solo, a player draws and rolls three dice at the beginning of his/her turn, and then allocates them to a pool of four active cards, possibly placing multiple dice on a single card. At any time (except towards the end of the game), there are four active cards and five cards in a ‘market’ ready to become active when an active card is completed.

I’ve been able to complete the single-player “Elite” difficulty (getting through 23 cards in 10 minutes) about half of the time if playing with a random mix of 27 cards, and have done it (once in ten attempts or so) if playing with cards drawn from the most difficult sets (i.e. all the level 6s and 4s, with all remaining cards being level 3s).

I made some simple tactical observations regarding card constraints. For example, there is a level 2 card requiring three numbers that sum to 11. If I have a free choice of a number to play there, I would play as close to 4 as possible (considering that two dice most likely sum to 7).

I think the main strategy in solo play involves ensuring that one’s cards don’t end up having conflicting demands, as far as possible. For example, consider the following set of cards.

This is an awful situation to be in, because apart from one space for a 1, all of the cards here demand high numbers to start. Four decreasing numbers only admits a 4 or higher (and even then, I find starting that card with a 4 very restrictive as it forces 3-2-1); the 15 sum only admits a 3 or higher (and then forces 6-6; I usually play one six and then on a later turn find a pair adding to 9). Misaligned numerical constraints can be painful; misaligned colour constraints might be even worse because colours are sampled without replacement (well, until card(s) are cleared or penalties are incurred). There is a level 4 card that demands four dice of the same colour, which I try not to pick up.

There are many cards that have rather specific requirements (e.g. a specific colour and number); I tend to try to carry one or maybe two of these at a time, while trying to ensure the rest of the cards cycle regularly. The penalty for a unused die involves re-rolling it, and then removing a die that matches in terms of colour or number (if possible).

Although the game only lasts ten minutes (or less, if the deck is cleared in time), I’ve found it to be highly addictive, especially difficult runs on the elite difficulty. I’d expect times to vary quite widely as it’s a dice game, though I’ve noticed that I run out of time with between one and three cards from the end most of the time. I’ve never counted, but it wouldn’t be unreasonable to average fifteen seconds for a turn, and to some extent things average out over 120 selections and rolls. As mentioned above, I think a key part of solo FUSE strategy involves managing interactions between the requirements of active cards.

Minor criticisms would include some disconnect in the difficulty of the cards. I find that most of the level 6s are less luck-dependent than some of the lower level cards, like the level 3 “any 5, a yellow die, and a green 2”. More bizarrely, the ‘6-5-4 pyramid’ card in the photo above is only level 2, though it’s considerably more restrictive than the ‘sum to 15’ card also in the photo (level 3). There might be a case for a more permissive card being rated higher if the cost of verifying correctness is higher (e.g. ‘three digit prime number’), but I don’t think adding three numbers introduces much overhead.

The ceiling for individual card difficulty also isn’t very high. The highest stacks are of height 5 (with very loose constraints) and pyramids of height 3 (using six dice). I’d imagine there would be scope to define some level 8 cards that might use seven or more dice and/or require combinations that are stricter or more complex, like a six-die pyramid where each die not placed on the ground level must equal the sum of the two dice directly underneath it, or even something like this:

I’ve played this with a friend from Imperial as well. With two players, each player has two active cards, four dice are rolled and each player must take two dice. We only played up to the standard difficulty. I’d like to play this with a bigger group, though; communication gets much trickier, and also with two I am able to maintain sufficient context in my head to compute a good allocation of four dice across two sets of two cards. With five, there are 10 active cards, which would probably be unreasonable to keep track of.

In summary, I’d highly recommend this game based on my solo/pair experiences. I’ve probably had about twenty to twenty-five playthroughs in total, and have enjoyed it thoroughly even though I generally don’t enjoy real-time games. Each run is short, but can generate an adrenaline rush, and the difficulty level is highly configurable so it should be possible to find a level that works well. I might even extend the game with some custom “hard mode” cards (this can be done by getting opaque sleeves so the backs are indistinguishable). I haven’t yet had the opportunity to play with a larger group, which should bring new and interesting challenges too.