Learning German 8: Ein Jahrestag (An Anniversary)

Ich lerne jetzt seit einem ganzen Jahr Deutsch. Ich erinnere mich, dass ich mit Duolingo und Linguee fing an. Zuerst lernte ich ein paar Wörter mit diesen Apps (obwohl es ist nicht so, dass ich von Null fing an. Früher hatte ich drei Monaten in Zürich gewohnt, und obwohl ich dann kein Deutsch gelernt hatte, erinnere ich mich natürlich ein bisschen Sachen.)

Als ich die Unterrichten bei Palantir begann, kannte ich ungefähr zwischen 600 und 1000 Wörter. Aber ich wusste kein Grammatik, und hatte nie auf Deutsch gesprochen. Wir hatten ein paar Deutschstunden, und dann unsere Lehrerin machte ihren jährlichen Urlaub. Ich hatte eine Fünf-Wochen-Pause, aber ich lernte weiter. Sie empfahl mir eine Serie von Büchern, die heißt “Dino lernt Deutsch”. Ich las diese Büchern gern, weil ich die Charaktere lustig und (wichtiger) die Sprache verständlich fand. Ich mochte auch die Fragen nach jedem Kapitel, weil ich mein Verständnis des Textes überprüfen konnte.

Ich glaube, dass ich vielleicht im September oder Oktober das A1-Niveau erreichte. Aber wegen meines Arbeits und meiner Faulheit machte ich die Prüfung im Januar. Damals war meine deutsche Sprachkentnisse sicherlich über A1; deshalb mochte ich “sehr gut” (mehr als 90 Prozent) Note. Ich übte andere Prüfungen, z. B. die englische GCSE (zu dieser Zeit bekam ich Siebener, die vielleicht Niveau A2 sind), und die telc A2 Deutschprüfungen. Endlich bekam ich 100 Prozent – das war noch ein bisschen überraschend. Ich vermute, dass sogar ins Sprechen und Schreiben man alle Punkte bekommen kann, wenn man die Aufgabe komplett erfüllt.

Wegen des Coronavirus muss ich die Unterrichten selbst bezahlen. Natürlich bevorzuge ich, wenn die Firma bezahlen, aber das ist für mich kein Problem. Ich finde die Deutschstunden effektiv und interessant. Am wichtigsten ist, dass ich mich durch diese Unterrichten mein Sprechen und Schreiben verbessern können. Eine Person, die meine Arbeit präzise korrigieren kann, ist sehr wertvoll.

Und dies ist mein erster Artikel, den ich komplett auf Deutsch geschrieben habe (am meistens…). Es ist klar, dass dies immer noch sehr schwierig ist. Aber es ist gut zu sehen, dass ich jetzt über komplizierter Ideen und Sachen schreiben kann. Ich will, und werde, weiter lernen.

I’ve been learning German for a full year now. I remember that I began with Duolingo and Linguee. I first learned a few words with these apps, though it isn’t the case that I started from zero. I had previously lived for three months in Zurich, and although I didn’t learn German at the time, I naturally remember some of it, by absorption.

When the lessons at Palantir started, I knew somewhere between 600 and 1000 words or so, although I knew zero grammar, and had never spoken a word of German. We had a few lessons, and then our teacher went on her annual holiday. I had a five week break, but I continued to learn. My teacher recommended a series of books called “Dino learns German”. I enjoyed reading these books, because the characters were funny, and more importantly the language was understandable. I also liked that there were questions after each chapter, as they allowed me to validate my comprehension of the text.

I believe I probably reached an A1 level in September or October, but because of my work and laziness I only did the exam in January. At that time, my German skills were surely above A1, therefore I wanted to get a “very good” (90% or higher) grade. I practiced other exams, for example the English GCSE (at that time I was scoring around grade 7s overall, which are about A2 level) and the A2 telc exams. In the end I scored 100%, which was still surprising. I guess that even in speaking and writing, one can get full marks if one fulfills the task completely.

Because of the coronavirus, I now have to pay for lessons myself – of course I prefer if the company pays, but that is not a problem. I find the lessons effective and interesting. Most importantly, I can improve my speaking and writing through these lessons – having a trusted person who can precisely correct my work is very valuable.

And this is also my first blogpost that I’ve written completely in German (well, kind of). It’s clear that this is still really difficult, but it’s good to see that I can now write about more complex ideas and things. I do want to, and will, continue to learn.

Beyond the Storm

Image by Dieter_G from Pixabay

The 5th of June 2020 bore similarities, for me, to the 29th of June 2016, the 6th of October 2015 and the 4th of January 2012. What is common between these dates is that they are the days just after a large – or as is the case with the most recent instance – intense project or series of projects were completed (the first and third were work related; the second was MCMAS-Dynamic, and the fourth was my full-time national service in Singapore). The final stages of these projects usually involve blatantly unsustainable working practices in the pursuit of excellence, quality, and/or tying up all loose ends. Interestingly, all but the most recent instance were tied to hard timelines of some kind.

It might seem like finishing a large or intense project would be a cause for celebration. That’s certainly true, both because of the extrinsic value of a project (performance improvements, new features, research contributions, or even some peace of mind) as well as the intrinsic sense of accomplishment from having completed (or at least survived) it. However, I find that there’s also a degree of emptiness that tends to grow in the few days after. The projects were inherently challenging and would have taken a large amount of my time, especially when considered in terms of the fraction of my hours they’d take up in their final weeks. There is also often a more significant amount of mental bandwidth and fortitude required for these projects to be successfully completed. Thus, when they’re finished, there’s going to invariably be a large disruption to the routine I’d have had in the days leading up to completion. While my attitude towards downtime and rest periods has grown into a more defensive and I think healthier position over time (so that I’m not immediately thinking “what’s the next productive thing to focus on?”), they can still only last for so long before a fear of laziness and indolence creeps back in, and I need to determine what I should look at next.

This would lead us to one possible strategy for dealing with these down periods: always having something lined up. This was serendipitously true in the 2015 instance; that day, a Friday, was my final day as a Palantir intern, and I began my final year of university on the Monday, with a fresh set of difficult modules and the beginning of MCMAS-Dynamic. We were required to take seven modules across the two terms, and I decided to front-load my modules. There was definitely a drop in intensity from the first week of October to the second, but it was relatively small. I’d say of the four instances here, this was the one that affected me the least. This is on a much smaller scale, but I didn’t feel any downtime after taking or passing the A1 Goethe-Institut exam because I knew I wanted to learn German to at least a B2 standard. I can often get overly focused on the task at hand to the exclusion of this. Pre-planning may not always be possible or optimal, as well: especially at work project selection is more often driven by business requirements and telemetry with a dose of intuition, which can change rapidly. Nonetheless, I think this is a good strategy especially for personal projects.

There is a natural extension of the above: if one maintains a portfolio of parallel projects, then finishing a large project would have less of an impact. This sounds good in theory, but I am slightly skeptical, mainly because in my experience these projects demand so much attention and time especially in their tail that there is often little productive capacity left to look at others. Furthermore, these “surges” in demand at the end often result in an elevated level of work that needs to be paused to maintain one’s sanity. In a sense, although I don’t particularly like the down periods, they are important and necessary (incidentally I’m strongly reminded of a phrase I’ve learnt in German class: wichtig und notwendig). Also, if one prioritises some (possibly one) of these projects substantially more highly than the others, it can be difficult to find the motivation to work on the lower-priority projects while there is still productive work that can be done on the important ones. I do do this for personal projects (maintaining friendships, learning German, competitive puzzles, writing and personal finance all run in parallel), but these are rarely the ones which call for massive, aggressive surges. (I won’t say that there weren’t any, though: the end of uni was where I focused on the first, and around the change of the tax year I do sometimes need to look at the fifth.)

An alternative approach is to avoid these last-minute pushes to reduce the delta between an intense final surge and not having the project at all. This is plausible, though I’m not certain the last-minute pushes are always avoidable, or for that matter a bad thing. A large amount of the stress in the 2016 instance was because with two weeks left, my supervisor Prof. Alessio Lomuscio and I decided to begin formally attacking LDLK on finite traces; the end would have been fairly relaxed if we didn’t do that, I’m happy I did it, though: this was an interesting (and publishable!) part of the investigation. In the 2020 instance, the deadlines were synthetic but getting those projects done quickly was important to reduce the amount of concurrent context I needed to track.

In summary, I’ve become more used to down periods after intense stretches of work and/or large projects are delivered; I think these are to some extent necessary even though I don’t find them particularly enjoyable. Making an effort to have something else planned, and/or working on multiple projects in parallel, where possible is usually helpful. Though these aren’t always possible, and in some cases if rigidly adhered to might limit the complexity of projects that one can successfully undertake. These down periods can be unpleasant, but I don’t think changing one’s projects is necessarily worth that tradeoff.

Remote Routines

It’s been about two and a half months since I started working from home, and I think I’d describe it as better than I expected, but still less than ideal. A tip I’ve suggested to my teammates to help maintain productivity while working from home is to establish a daily routine.

I’m aware of this in theory, but haven’t been as good at adhering to this in practice. The availability of meals in the office resulted in a natural routine: I would eat breakfast in the office before the workday started, and would normally finish most development work before dinner. I’d sometimes write documentation or polish up a test after dinner, but usually the post-dinner work would be less intense. This wasn’t true for everyone, of course (one could elect to skip breakfast and/or have dinner at home), but it was for me. I also set up my laptop to remind me at 8 pm to ask myself if I should stop for the day, and in any case an empty office was useful as a reminder that it was late, and that I perhaps should no longer be around.

Initially, I did follow this: I marked the start of the day with a short walk to the local M&S before breakfast. However, things started degrading over time. I think much of this was in relation to wanting to get as much sleep as possible before meetings or work started. I’m not sure what precipitated that; I imagine that would probably be a late night, perhaps caused by some combination of working late and getting distracted with reading, computer games or something else. I’ve been reading Puzzlecraft: How to Make Every Kind of Puzzle, and I do remember a recent evening where I started trying to craft a triple of linked Sudoku variants that weren’t independently solvable, but had a unique solution taken together at 9.30 pm or so, and finished at 1.30 am.

It’s probably related, but I noticed that I’ve recently been working longer hours – with reduced time outside of work it’s invariably tempting to push one’s sleep backwards, even if doing so may have undesirable consequences. I normally have a 2.5-3 km walking commute to the office (and interestingly this is what is currently recommended by the government), which takes me about 30 minutes at a reasonably quick pace. This is between 45 minutes and 1 hour each day (I almost always walk in the morning, but sometimes take the Tube in the evening) of time that seems to be mostly converted into development time. I guess this is a benefit of working from home if one holds one’s hours constant (that said, my commute also has exercise benefits for me).

Some of this might also be because I’ve started doing more independent development work again (there was a time where I spent <20% time on this, while it’s probably between 30 and 40 percent now). It’s now actually possible and directly relevant to my goals to make larger independent pushes. This is intellectually welcome though I do need to be careful about how far I take this.

I’ve also been getting more sleep for some reason. This may be a product of increased mental fatigue. In addition to development work, the hobbies I’ve been spending time on recently – reading, logic puzzles, learning German and some computer games – are generally quite taxing.

I normally get about 7.5 hours of sleep during the week, and maybe 8.5-9 or so on weekends. I think the amount of sleep I’ve been getting from Sunday to Thursday hasn’t really changed, but I don’t seem to feel as well-rested as normal. In terms of weekend schedules, I do remember an abnormally high frequency of 10- or 11-hour sleeps as of late.

There are definitely advantages to working from home – it can be better for focusing on specific difficult problems, and not having to do a 30 minute commute is a big win (and is possibly a bigger win for others). I’m not sure I would want to, though, given the choice, perhaps not for fault of the concept in general, but instead because I haven’t had the willpower, knowledge, or some other factor needed to thrive on it. There are also other frustrations: video-conferencing while passable still seems frictionful, and while I’m an introvert even I find the lack of human contact unsustainable.

Learning German 7: Fremdsprachen und Computer (Foreign Languages and Computers)

In der A1 “Start Deutsch 1” Prüfung muss man in das Schreiben-Teil ein Formular ausfüllen, z. B. ein Anmeldeformular für eine Sprachschule, oder eine Reisebuchungformular. Obwohl ich darin eine sehr gute Note bekam, bin ich noch nicht sicher, Formulare auf Deutsch auszufüllen. Ich würde immer noch Englisch benutzen, weil ich Missverständnisse vermeiden möchten. Auf der anderen Seite, das Spielen von Computerspielen hat am meistens weniger Konsequenzen, wenn man Fehler machen. Ich spielte ein paar Spiele auf Deutsch mit meinen Freunde, darunter “Keep Talking and Nobody Explodes” und “Tick Tock: A Tale for Two”. In diesen Spiele ist gute und klare Kommunikation sehr wichtig. Wir machte viel Spaß, obwohl wir waren viel langsamer als wenn wir Englisch benutzte.

One has to fill in a form in the writing part of the German A1 (“Start Deutsch 1”) exam, for example a registration form for a language school or a travel booking form. Although I got a very good mark there, I’m still not confident filling in forms in German. I would still prefer to use English, because I would want to avoid any misunderstandings. On the other hand, playing computer games mostly has fewer consequences when one makes mistakes. I played a few games with my friends in German, including “Keep Talking and Nobody Explodes” and “Tick Tock: A Tale for Two”. Good and clear communication is very important in these games. We had a lot of fun, even though we were much slower than if we used English.


A suggestion I’ve come across fairly often as part of language learning is to set one’s computer’s language to the target language. The aim here is likely to achieve immersion: one will see the language as part of one’s daily activities. Admittedly, the vocabulary one comes across is likely to be fairly domain specific (one will probably very quickly learn what the word for close or delete are – in German schließen and löschen respectively), but it does still likely cover a fair few common phrases and expressions that might be useful. For example, I have to think a bit to translate how to play (Spielanleitung or Wie man spielt, probably not the direct Wie zu spielen), while that would probably come very quickly to someone who did this.

As the previous sentence implied, I did not do this. I did try it briefly, but ran into enough frustrating issues that I switched my laptop back to English. I think the main issue wasn’t that I found the system unusable, but it did considerably slow things down. Many websites presented content, forms and questions to me in German (it’s possible this is my failure and/or I went for even more immersion when I changed the language settings), and I needed to read them really closely to be sure of precisely what I was doing. For example, I remember being asked, when booking a flight to Switzerland, Brauchen Sie aufgegebenes Gepäck? (Do you need checked baggage?) I knew Gepäck meant baggage – the problem was that I wanted hand (but not checked) baggage, and while I knew that hand luggage is normally written Handgepäck I didn’t know if aufgegebenes was another word for hand baggage or if it referred to checked baggage. While these kinds of disruptions could certainly be viewed as learning opportunities (and that is how I learned those words), they happened at a higher frequency than I would like, and were often disruptive.

There were also more technical issues relating to internationalisation (or “i18n” as is frequently written in tech). For example, my copy of The Sims 4 couldn’t find its old data directories because it decided to search in Die Sims 4. Most of my documents are still written in English, and Office also seemed to think that it should follow the default language for spell-checking (a reasonable assumption, and it’s probably too much to ask to have it infer the input language and then run spell check based on that, but frustrating for me).

On the other hand, I find computer games, especially ones that are relatively simpler, suitable for playing in a target foreign language because, as discussed above, there are generally fewer consequences for mistakes. If one is playing competitively, of course, then this would be an unnecessary handicap. The Sims series would probably be very good games for playing in German (or when learning a foreign language) because many of the words encountered would be similar to ones used often in real life – compared to Keep Talking, where numbers, colours and orientation were much more prevalent. Tick Tock was interesting and communication felt more difficult (we’ve only finished chapter 1): it’s basically kind of like an escape room with puzzles and instructions in German. I was able to figure out at least the gist of what was being said, so that wasn’t too much of a problem – the bigger challenge there was because my friend and I communicated entirely in German. Relaying instructions was tricky; there is a richer range of things that needed to be communicated (as compared to saying Vier Kabeln, rot-gelb-schwarz-weiß; thinking back the part of Keep Talking made trickiest by using German was the symbols module).

Torrential Storm (Q1+ 2020 Review)

I’m somewhat behind schedule on this one. To some extent, working from home has confused my weekend workflows, in that there isn’t as clear of a separation between work and non-work days. I’ve also been finding writing more taxing than normal, perhaps because I’ve had to do more of that at work for various reasons, both in a professional capacity and auf Deutsch, fur meine Hausaufgabe (in German, for my homework).

I’m still working on AtlasDB and at Palantir. For various reasons Q1 (and I’m extending this review to cover the first two weeks of April) has been tricky in terms of events at work. I think there’s one core paradigm that I used to have as a lead that I had some doubts about at the end of last year, and I’d say has been shaken even more since.

My normal approach to being a lead is to aggressively apply the golden rule – to push policies that I would like or find useful or helpful as a developer, and to reject those that would be unhelpful (allowing for some measure of unpleasantness, but not too much). The problems here come if there are considerable differences in relevant preferences or inclinations: what I find useful as I started out may not be useful for others.

Normally I’d write a section detailing my travels, though of course this was considerably less in Q1 because of COVID-19. I did travel a little bit in the early part of the year (I was in Singapore for the holidays, and made a short trip to Zurich to visit Stan in early March – back when there were just eight reported cases in Switzerland). I was originally slated to go back to Singapore for Easter, though of course that didn’t actually materialise.

We’re entering week 5 of the UK lockdown, and week 8 of working from home for me. Initially, the changes to my routine weren’t particularly serious (I was fortunate in that I had just come back from Switzerland – I normally travel once every 1-2 months, even if it’s just for a short weekend break).

The markets have also been pretty exciting, though I haven’t been thinking of them as much because of coronavirus (and perhaps that’s for the better, given the scale of the drops). I remember the first time I lost a month’s worth of investment contributions, but this was the first time I lost a year’s worth of them (on paper, at least). With increasingly stark economic data prints and forecasts, it’s a healthy reminder that movements in the market are often not about whether business/the economy are doing well or badly, but rather whether they are doing better or worse than expected (so if the consensus estimate is for a grade D and the actual performance is a C-, stocks could do well!).

In terms of logic contests, four Sudoku GPs have occurred, and my performance is probably not too different from last year. I’ve performed worse in terms of absolute number of points scored (I finished last year with 2502, four contests at 1565 would suggest 2347.5 as an overall score), but better in terms of ranking (61-50-74-71, overall 51; I finished 66th last year). I’m not sure if I’ve gotten any faster, really; in terms of strategies I wouldn’t say I could concretely identify a way I’m better now than I was last year. It’s possible the contests themselves have gotten harder, or the test solver pool has gotten faster (points are generally allocated based on how long test solvers take).

Similarly, four Puzzle GPs have been completed. I have been considerably less stable at puzzles; this hasn’t changed from last year, and has probably gotten worse in fact. I did worse in terms of absolute numbers of points scored (I finished last year at 1921, and four contests at 1205 implies 1807.5) and worse in ranking (139-154-71-141, overall 100; I finished 91st last year). I think my bad habits here involve being overly fearful of bifurcation. Puzzle choice is a bigger issue in these rounds than in Sudoku, since there are more options (even the best solvers frequently don’t actually solve everything). I tend to gravitate to number-heavy types like KenKen, Arithmetic Squares, Skyscrapers or Futoshiki because they feel comfortable, even though I’d say I’m fast at the first two but pretty bad at the last two.

Another hobby I’ve been pursuing is learning German. I took my A1 exam in Q1, and got a sehr gut (very good) grade with 100 percent. Perfekte Noten (perfect grades), as one might say. Lessons at Palantir continue and have been useful in ensuring that I have a more proper, structured framework for learning, as well as providing quality feedback on pronunciation and writing.

I started learning about Nebensätze (subordinate clauses) at the very end of last year to beginning of this year, and they’ve substantially broadened the range of things I can talk or write about. Wennals and ob (if/when – though not specifically previously, previously when, whether respectively) are very useful; weil (because) a bit less so since I already knew denn (because), but for some reason I find sentences with weil tend to roll off the tongue better. The practice of ending these clauses with the main verb (e.g. Ich weiß nicht, ob das gute Idee ist, weil ich vielleicht nicht genug Geld habe – I don’t know whether that is a good idea because I might not have enough money) currently requires me to build most of the sentence upfront, but the catharsis of unleashing the verb at the end feels great.

Social distancing has made me look at video games more, both in terms of games to play on my own as well as with friends. Interestingly, the concept of a rogue-like seems to be a common thread in three of the games which I’ve been playing a lot in Q1: Slay the SpireDicey Dungeons and Dead Cells. Games generally consist of individual runs that take from 15 to 60 or so minutes (Dicey Dungeons is probably on the faster end, Dead Cells can be much slower); there is some, but generally limited, progression across runs.

The first two are actually fairly similar in that combat is turn-based; the former involves deckbuilding, while the latter involves arranging equipment to maximise effectiveness of die rolls. The latter is very different and is much more focused on action and reflexes, which can be more appropriate if I don’t want to think as much. Slay the Spire, especially on super-hard modes, is quite a brain-burner.

These games are also similar in that they are reasonably easy at their base difficulty level – I think I had my first win of Slay the Spire on the third run, Dicey Dungeons on the very first run, and Dead Cells on the second run. I think I’d be able to win >95% of games on the easiest mode (Ironclad Ascension 0, Warrior level 1 and 0 Boss Cells, respectively). However, difficulty modifiers can make things very challenging: I’m pretty sure my win rate on Slay the Spire‘s Ascension 20 (max difficulty) is under 10%, and I’ve not completed Dead Cells with 4 Boss Cells (difficulty ranges from 0 to 5, increasing with each additional cell). There’s some evidence that I’ve gotten better at surviving what the game throws at me though, in that when I first started Ascension 20 and 3 Boss Cell mode looked completely impossible. Furthermore, I’d find the base modes mostly boring now, as even clear lapses in my play would be largely inconsequential – I think I enjoy a challenge.

The relative lack of travel also means that I haven’t listened to very much music recently. There are the fast-paced instrumentals that I listen to sometimes when implementing features (as opposed to design) – Destination Relapse is pretty good, even if the 200+ BPM track was written to be a really difficult rhythm game boss. To some extent similar would probably be Chopin’s Etude Op. 10 No. 4 (here performed by Rousseau), which would probably make a good boss song if playing the piano in general was treated as a rhythm game. There’s a kind of unrelenting fury and incessant urgency in the closing streams of Relapse and throughout the Etude that appeals to me, and perhaps reflects a torrent of potentially creative destruction (incidentally, the Etude is sometimes given that moniker as well). For me, that does make sense considering what I’ve been looking at in terms of work.

Learning German 6: Einhundert! (100)

Ich habe meine A1 Deutschprüfung bestanden. Ich habe nicht nur bestanden, sondern 100 von 100 Punkte erreichen. Man muss in jedem Teil mindestens 60 Prozent erzielen, wenn man die Prüfung bestanden. Es gibt fünf mögliche Bewertungen. Am höchsten ist “sehr gut” (90-100). Aber ich weiß nicht, ob ich eine sehr gute Entscheidung über das Sprachniveau machte – vielleicht konnte ich die A2 Prüfung auch bestanden? Vor sechs Monaten wusste ich nicht, wie meine Deutschsprachkentnisse entwicklen würden.

I passed my A1 German exam. I didn’t just pass, but got 100 of 100 points. One must score at least 60 percent in each part of the exam to pass. There are five possible grades. The highest is “very good” (90-100). However, I don’t know if I made a “very good” decision about which level of the exam to take – maybe I could have passed the A2 exam. Six months ago, I didn’t know how my German skills would develop.


This is in general an issue with exams where candidates must decide what level to enter themselves at: I’ve run into this before for music, and also with German. It’s a shame that the Goethe-Institut (and as far as I know, other alternatives like the telc) exams aren’t generally equipped to provide assessment at other grades for very strong, or alternatively, just-unsatisfactory performances. This is less of an issue with the Cambridge English qualifications – in general, candidates can also obtain a grade N + 1 or N – 1 result when taking the exam for grade if they, respectively, score close to full marks or just miss the passing mark.

I made the decision on which exam to take about 6 months ago – the decision was between A1 and A2. I started by looking at the model papers available from the Goethe-Institut. I think my opinion at the time was that at that point, I could mostly smoothly navigate the A1; A2 would be a struggle, though there were still four months to the exam. The speaking section of A2 would, in particular, have been a struggle then; I think it would still be difficult if I had to do it now. I think I tried out the reading and listening sections of both papers in September last year, and scored 83% on A1 and 57% on A2. I’ve tried out the B1 level papers more recently for reading (and the telc grammar/sentence construction ones as well) and have been able to fumble my way through with about 80 percent, though of course it has been six months since then!

The European Council does publish a self-assessment rubric to help distinguish these levels, but I find the “can-do” descriptors a little vague and, more importantly, difficult for me to confidently assess. I’d generally be confident with most of the A2 descriptors now, and five months ago I think understanding would be at A2 while production (speaking and writing) would be somewhere in between A1 and A2. However, there still exist interpretations where I wouldn’t necessarily be confident of my ability at the A2 level. Consider the descriptor for spoken interaction, which includes “I can handle very short social exchanges, even though I can’t usually understand enough to keep the conversation going myself”. Many of my social interactions with friends involve puns, humour and sarcasm which I might completely miss if delivered in German. I don’t think this is part of the expectation at A2, but it isn’t explicitly stated.

I was somewhat risk-averse and picked A1, figuring that I would get this out of the way and I could still take A2 subsequently, or alternatively jump straight to B1. As mentioned, I think my German skills developed more than I expected over the next few months, perhaps because I spent more time doing self-study. This isn’t a bad result at all, but something like this instead of say an 85 or 91 really did make me think if A2 would have been the better decision. In any case, I can’t take it back, and the improvements to my skill level remain. (It is possible that I might have developed my skills further if I did the A2 exam in January, as I would need to push myself through catch-up classes or work, but it would also have been considerably more stressful.)

Different World (Thoughts on COVID-19)

I remember a recent trip where my mum came up to London to visit. It was bright, and we had a relaxed lunch in a Chinese restaurant with a glass ceiling. I thought of how my routine had significantly changed – I would naturally prioritise spending time with her, instead of working an extra hour, studying another hour of German, practicing another set of logic puzzles or just scrolling through eBay.

Similarly, the recent COVID-19 situation has changed things quite a fair bit for me, and I imagine the changes I’m exposed to are still relatively small compared to what many other people face.

The obvious change is working from home, which I’m not particularly a fan of (human contact is important, and pair programming remotely turns out to be really hard – especially for me if I’m doing this more in an instructional capacity, as I like to have newer team members code while I jump in as needed), but I understand it’s necessary given the circumstances. Being able to work from home is certainly a privilege of software engineering, among other jobs. In hindsight, having the ability to work at all is also a privilege, in light of the widespread shop closures that came into effect. The UK government’s proposals should help, but it’s still a 20 percent pay cut (more, if one is earning more than 30,000 a year) – and I don’t know how exactly things are going to work for people on zero-hours contracts or the self-employed.

There is then social distancing: I’d lump the aforementioned shop closures into it, as if it is decided that civil liberties should not be restricted, one can still give strong pushes by decreasing the desirability of engaging in the behaviours that one doesn’t want. I do have a few groups of friends that I meet outside of work, but so far at least the impact hasn’t been too bad – we’ve found alternatives such as doing it digitally which are to me inferior but are still better than nothing. The shop closures are annoying, but in any case I do most of my shopping, apart from groceries and food, online. It hasn’t massively changed a majority of my weekend programmes, because of what activities are involved (usually reading, puzzles, computer games or walks – note that the last of these can still go ahead subject to social distancing). The relative absence of people (which is good!) is highly noticeable.

Travel restrictions are another factor. I had to cancel my Singapore trip over Easter, because the government requires returning Singapore citizens to spend 14 days at home. This is reasonable, but is of course problematic if one’s intended stay is less than 14 days. I didn’t have any other immediate plans to travel, though would likely have drafted some for the bank holidays, perhaps to Germany or Zurich again. In a sense the timing of my Zurich trip was good: I returned just before the number of cases spiked. That’s probably going to be on the backburner – and I wonder if (assuming the airlines survive) prices will be reasonable as we get past the peak.

Grocery shopping has changed as well: a year ago hand soap would have been a mundane entry on a list while I now actively look out for it. I also tried to execute a Sainsbury’s delivery order earlier this week, and saw no availability for three weeks. It’s unclear if the worst has already passed – I’m seeing slightly more stock, maybe because most of the stockpiling has already happened, and supermarkets are actively ramping up the capacity of their food-stocking chains.

Incidentally this makes me think of some variant of the Prisoner’s Dilemma from game theory, where cooperating is not stockpiling and defecting is stockpiling. It’s best if no one stockpiles (since stockpiling has costs: the cost of carry – organising one’s supplies, finding space for them, making sure use-by dates are observed safely – and the opportunity cost of the money going into the supplies, assuming that investment performance outpaces inflation). Normally, this is the case. However, as more people stockpile, seeking to stockpile suddenly becomes rational: not stockpiling may mean that one is unable to obtain important provisions. The game is iterated, as well: one presumably visits supermarkets multiple times, and can see the state of supermarket shelves and derive an estimate of what people are buying.

There is also the recent fall of and heightened volatility on the stock market. I use a broker called De Giro that has a feature to send an email every time a position goes down by 10% (I think additively). I’ve seen a couple of cheerful 40% depreciation emails for some of the riskier assets there. It could be worse: IAG (owning BA, among others) stock is down 72 percent, and Lufthansa is down 65 percent. Interestingly Singapore Airlines is “only” down 40 percent. The numerical magnitude and speed of the damage here, especially if considered in US dollars (which strengthened aggressively) is probably a factor of 10 larger than what I’ve dealt with in the past. In a sense, the speed highlights the perception of loss, because a more drawn-out fall tends to be partially insulated by fresh contributions and pound-cost averaging. However, despite the scale of the numbers involved, they seem a bit further removed (an image of a bonfire of notes equal to the five figure sum would be more concerning).

We’ll see how things go. I guess I was too young to remember and/or make any significant decisions when dealing with SARS in 2002-2003: I was in Primary 6 then, and remember schools being closed briefly. Even when schools reopened there was twice-daily temperature taking and values had to be documented. The numbers of cases were much smaller (I think four-figures globally), though I remember it being somewhat more dangerous (contrast with UK government advice – and this is indeed true – that for most people COVID-19 will be mild).

One risk of FIRE pursuits and/or aggressive savings strategies is for some reason not being able to spend the money one has saved up later on. I’d say the financial strategy I’ve been using from 2016 to early 2020, though not at popular FIRE blogger levels, involves an aggressive savings strategy, and to some extent that risk has manifested. I certainly wouldn’t say it has caused a significant shift in my thinking, but it’s a good reminder that stockpiling of wealth as an end to itself tends to be unhelpful.

Limitations of the Bus Factor

Over lunch today, a friend and I discussed what we were doing in response to COVID-19. I mentioned I was working from home, and that the purpose of working from home was presumably to avoid the offices becoming a coronavirus cluster. This isn’t the same as quarantine or self-isolation in that I can and do still leave the house, attend smaller-scale social events and meet friends. The probability seems not too high, but even if I become sick the idea is that we don’t want this to spread to others on the team or at the company.

The bus factor is a simple measurement of how concentrated key personnel are in a team. It is defined as the minimum number of people that can be removed from a team before the project stalls. For example, if a shop has five employees, where everyone can restock shelves but only two people are authorised to operate the cash register, then the shop team has a bus factor of 2, since if those two people are removed the shop will not function.

Generally, a higher number is better, as it means the team can tolerate more people being unavailable. This is often used to inform risk planning, such as by prioritising context-sharing, developer documentation or other means of spreading knowledge.

However, there is quite a lot of variance within a single measurement. For example, suppose we have a team A which has two leads, and we say that the team will stall if both of them are unavailable (but only them – any other group of people becoming unavailable, including everyone but one of the leads, is okay). Also consider team B, where the absence of any two people will cause the team to stall (though no individual would). Both teams have a bus factor of 2. However, A is strictly safer than B, and it seems to be quite a large margin. I’m not sure that B is safer than a team C, where there is one absolutely critical lead (bus factor 1), for that matter.

This could get us to a concrete problem. Suppose there is a 1 percent probability that each person on a team becomes unavailable for some reason. What is the smallest number of people such that it is possible that a team with a bus factor of 2 is actually riskier than a team with a bus factor of 1?


Finding the Extremes

To answer this question, we want to find the extremes of a given Bus Factor BF in terms of risk, because we want to compare the riskiest Bus Factor 2 team against the safest Bus Factor 1 team. This drops out quite naturally: the safest team is the one where there exists one specific set of BF people which will cause operations to stall, and no other combination that is not a superset of that set is essential. Conversely, the riskiest team is one where every combination of BF people is critical. As defined above, team B is the riskiest possible Bus Factor 2 team, and team C is the safest possible Bus Factor 1 team.

Without loss of generality, let the people in the team be numbered 1, 2, \ldots, n and the lead have number 1 (or 1 and 2 in the case of team A). Let the probability that an entity E becomes unavailable be P(E_\times). Then, the probability that each team’s work stalls is as follows:

\displaystyle P(A_\times) = P(1_\times \wedge 2_\times)

\displaystyle P(B_\times) = P \left( \bigvee_{i=1}^{n} \bigvee_{j=i+1}^{n} i_\times \wedge j_\times \right)

\displaystyle P(C_\times) = P(1_\times)

These terms as written aren’t very comparable – depending on the underlying probability distributions.

Attempting to Compare Terms

I’ve used logical formulas above to avoid making claims about the underlying probability distributions. However, if we assume that the probabilities are independently and identically distributed, and we say that over some fixed period of time the probability that an individual becomes unavailable is p, then we have

\displaystyle P(A_\times) = p^2

\displaystyle P(C_\times) = p

P(B_\times) is marginally trickier. This is the probability there are at least two people who become unavailable. It is probably easier to work out the complement P(B_\times'): that is the probability zero people or one person is unavailable. If we define X as the number of people (out of n) who become unavailable, then P(B_\times') = P(X=0) + P(X=1). It’s clear that P(X=0) = (1-p)^n. P(X=1) = np(1-p)^{n-1}: the probability a specific person is unavailable and no others are is p(1-p)^{n-1}, but there are n valid versions of this. More generally, X follows what’s called a binomial distribution. Thus,

\displaystyle P(B_\times') = (1-p)^n + np(1-p)^{n-1} = (1-p)^{n-1} \left( 1 - p + np \right)

and thus

P(B_\times) = 1 - (1-p)^{n-1} \left( 1 - p + np \right)

Notice that, as expected, this is dependent on n, while the other teams A and C have probabilities that don’t depend on n. Furthermore, as n increases, P(B_\times) increases – intuitively, as you consider more people, every way in which the team was already broken ignoring the new people remains broken, but some previously unbroken states can also break. (A more mathematical argument could look at the ratios of successive terms.)

Synthesis

The combination of exponential and polynomial (well, linear) terms in P(B_\times) would make direct comparison with P(C_\times) difficult. We can however fix some risk probability p and find out at which value of n team B (no one is individually critical, but every pair of people is critical) has a greater probability of stalling than team C (there is a single critical lead). To answer our initial question, we choose p=0.01. Since we have a closed form for the probability of team B having issues, we can plot a graph:

It turns out the answer here, n=16 is actually relatively small in computational terms, even if it is large as far as teams are concerned. That said, the conditions for a team being the safest possible for a given bus factor are extremely strict – the sheer under-resourcing from removing people, even if they aren’t information silos or have unique knowledge, would still severely impair team function.

Learning German 5: Do Not Give The Children Cigarettes

I had my Goethe-Zertifikat A1: Start Deutsch 1 exam about 3 weeks ago. The exam has four parts: listening, reading, writing and speaking. I was most nervous about the oral exam, but once it started, I felt more comfortable. The third part of the oral exam is about making and responding to requests. One of the other candidates took a card with a “no smoking” sign on it, but I think he forgot the word “smoking”. He was smart, though, and said, “Please do not give the children cigarettes”. I think my speaking skills were good enough, though unfortunately not as humorous.

Vor drei Woche habe ich meine Goethe-Zertifikat A1 Prüfung gemacht. Die Prüfung hat vier Teilen, nämlich Lesen, Hören, Schreiben und Sprechen. Ich war am nervösesten über die mundliche Prüfung, aber als sie angefangen hat, fühle ich mich besser. Das dritte Teil der mundlichen Prüfung ist über Bitten formulieren und reagieren. Ein anderer Kandidat hat eine Karte mit einem “Rauchen verboten” Schild genommen. Ich habe gedacht, dass er hat das Wort “rauchen” vergessen. Er war intelligent, und hat gesagt “Bitte geben Sie meinen Kindern keine Zigaretten”. Ich denke, dass ich habe gut genug gesprochen, aber ich war leider nicht so lustig.


Taboo is a game where one needs to communicate a word to one’s partner, without saying a list of “taboo” words. For example, for the word “Twister” one might have Tornado, Game, Colours, Legs and Arms as taboo words. If I still wanted to go for the party game approach (which I think is easier than the tornado approach as it’s very precise if done correctly), I might say something like “Something played at a party where a wheel is spun and players contort their limbs to place them on red, green, blue or yellow circles”.

I’ve found some similarities between playing Taboo and speaking in German (and even in Mandarin), in that I can’t always use the most direct approach of communicating something. The reason for this is different: in Taboo, it is the rules of the game, while with second and third languages it is typically because I lack vocabulary required to use the most direct approach. For example, if I wanted to communicate “I want a pair of chopsticks”, I could do this easily in English or Chinese (我要筷子), but I don’t know the word for that in German (Essstäbchen, it turns out). I might thus need to work around it via description, with something like “Könnten Sie mir chinesisches Besteck geben?”. There are a number of English words that have been adopted into German, so I could just take a shot in the dark with “Geben Sie mir ein Paar Chopsticks, bitte.” which would probably get the point across especially to a German speaker, though it’s wrong.

I’ve also tried playing Taboo myself in German. Even sticking to simple sentences (to avoid struggling with stringing together subclauses or neighbouring-sentences on the fly) not having a broad vocabulary makes it tricky. For example, I saw a card with goal word Biene or bee (banned: gelb or yellow, Stachel or sting, Summen or sum, Honig or honey, Blütenstaub or pollen). In English, this isn’t very hard: “there’s a queen, they make hexagonal structures, produce golden liquid good for coughs… you can say you have this in your bonnet, or if you’re in a rush you’re making a this-line for something”. I found this tricky in German. Even trying to translate what I’d say in English, I might begin “Es hat Königin”, but it goes downhill from there (turns out hexagon is just das Hexagon, and I could improvise liquid by just saying Wasser). I wouldn’t be able to give the idioms and I’m not sure they still work in German. Effectively, all of the missing vocabulary items are permanent Taboo words.

I think one of my strengths in English communication is being able to make statements fairly precisely (for example, “I don’t have a particularly strong opinion; while I agree with (specific parts of X), I’m not confident X is correct because I am not in a position to assess (other part of X)”, or “X is correct in principle but I’m not sure it’s appropriate to implement”). I’m not there in Chinese, and definitely not in German. This can be an issue with using possibly circumlocutory descriptions – if they accidentally indicate a preference that isn’t really there. For example, for the “chinesisches Besteck” example above, one can’t fault a server that brings a soup spoon (and depending on one’s point of view, the server could be justifiably annoyed if one rejects the soup spoon and continues to make this request without qualifying it further).

Is It Someone’s Birthday Everyday? Solving the Inverse Birthday Problem

The birthday paradox is a fairly well-known but unintuitive observation that although there are normally 365 days in a year (for simplicity, ignoring leap years and assuming a uniform distribution for birthdays), with as few as 23 people it is more likely than not that two of them will share a birthday. One of my teammates proposed an inverse of this problem: what is the minimum number of people are needed so that it is more likely than not that it is someone’s birthday every day?

Modelling A Specific Instance

There’s a lot to take in here, so let’s try to solve a simpler problem first. We could attempt to solve: given a specific number of people, how would we calculate the probability that it is someone’s birthday every day? If we have this method, we can reconstruct the answer to the original problem via a search algorithm.

The more general problem here would be: suppose we have N \geq 1 people. Each person draws one of K \geq 1 events with replacement – these are equally probable and independent. What is the probability that all events occur at least once? The more general introductory problem has K = 365, but of course that’s tricky to work with right off the bat, so let’s examine a couple of the smaller cases.

Algorithmic Ideation

Base Case Analysis

If K = 1, since we said that we always have at least one person, the one possible event will happen and the probability is 1. Moving on to K = 2, here N = 1 is a special case with probability of 0. For larger N, there are two specific situations we want to avoid, where every person draws the same event (remember that there were two events). Each of these happens with probability 2^{-N} so the probability of everything occurring once would be 1 - 2 \times 2^{-N} = 1 - 2^{-N + 1}.

We can now analyze K = 3 – if N \leq 2 we definitively have probability 0. For N = 3, the first person will receive a novel outcome with certainty, but the second and third person also need novel outcomes, and this happens with probability \frac{2}{3} \times \frac{1}{3} = \frac{2}{9}. It gets a little trickier with N = 4:

  • The first person to draw an event will get a novel event. This leaves 3 people to draw events, and 2 out of 3 events undrawn. We can call this state (3, 2, 3).
  • The second person to draw an event will get a novel event with probability 2/3, putting us in the state (2, 1, 3). Alternatively, he/she will draw the same event as the first person with probability 1/3, getting us in the state (2, 2, 3).
  • If we’re in (2, 1, 3), there’s a 1/3 probability that the third person draws the last event (in which case we are done), and a 2/3 probability he doesn’t, putting us in (1, 1, 3).
  • If we’re in (1, 1, 3) we have one person who needs to draw the last event with probability 1/3.
  • If we’re in (2, 2, 3), the third person will get a novel event with probability 2/3, putting us in (1, 1, 3). He might draw the same event as the first two people, in which case we definitely failed.

More generally, we can model the problem using a state machine (a technique which I discussed two and a half years ago). The states of this machine can be written as 3-tuples (p, q, r) which means we have p people to draw events, there are r events of which q still need to be drawn. Notice that q \leq r, and that for our problem, we have r = K and we generally want to find the probability of success for the state (N, K, K).

For K = 3, N = 4 we can draw this as follows.

Recurrence Relations

We can define V(p, q, r) as the probability that transitions from the state (p, q, r) will eventually end up in a SUCCESS state, defined as (p, 0, r) for all values of p and r (as that means all events were drawn). We make some observations on simple cases:

  • V(p, 0, r) = 1. We are already in a success state by definition.
  • V(0, q \geq 1, r) = 0. If everyone has drawn an event and there are still events that haven’t occurred, there is no chance for us to draw those events.

That’s all we need, and we can look at the recursive case. In the state (p, q, r), there is a \frac{q}{r} probability that we draw a new outcome, putting us in the state (p-1, q-1, r). There is also a 1 - \frac{q}{r} probability that that doesn’t happen – in that case we’re in the state (p-1, q, r). It thus follows that

V(p, q, r) = \dfrac{q}{r} \times V(p-1, q-1, r) + \left( 1 - \dfrac{q}{r} \right) \times V(p-1, q, r)

Notice that these states are well-formed, since we handled the p=0 and q=0 base cases earlier. It is possible to optimise this by adding some more sophisticated base cases, but this still gives us a clear enough method for working out the probability. For example,

  • V(2, 1, 3) =\frac{1}{3} \times V(1, 0, 3) + \frac{2}{3} \times V(1, 1, 3) = \frac{1}{3} \times 1 + \frac{2}{3} \times \frac{1}{3} = \frac{1}{3} + \frac{2}{9} = \frac{5}{9}
  • V(2, 2, 3) =\frac{2}{3} \times V(1, 1, 3) + \frac{2}{3} \times V(1, 2, 3) = \frac{2}{3} \times \frac{1}{3} + \frac{1}{3} \times 0 = \frac{2}{9}
  • V(4, 3, 3) = V(3, 2, 3) = \frac{2}{3} \times V(2, 1, 3) + \frac{2}{3} \times V(2, 2, 3) = \frac{4}{9}

 

Solving The Specific Instance

The answer to our original problem, for a given number of people N is then V(N, 365, 365). Working this out by hand is likely to be painful, so we should avoid that. It’s easy to code something simple up that is based on the recurrence relation above:

private static double findSuccessProbability(long remainingPeople, long remainingEvents, long totalEvents) {
    if (remainingEvents == 0) {
        return 1.0;
    }
    if (remainingPeople == 0) {
        return 0.0;
    }

    double probabilityOfNewEvent = ((double) remainingEvents) / totalEvents;
    double successProbabilityOnNewEvent = findSuccessProbability(remainingPeople - 1, remainingEvents - 1, totalEvents);
    double successProbabilityOnOldEvent = findSuccessProbability(remainingPeople - 1, remainingEvents, totalEvents);

    return probabilityOfNewEvent * successProbabilityOnNewEvent
            + (1 - probabilityOfNewEvent) * successProbabilityOnOldEvent;
}

We can test this and verify that indeed V(4, 3, 3) = \frac{4}{9}. However, if we try to call this with, say (500, 365, 365) the program doesn’t seem to give the answer quickly.

One solution here is to use memoisation. The naive version written above ends up computing the answer for the same state potentially exponentially many times, but we can cache the results of previous computations and use them. This could be done with a map with the 3-tuple as a cache key; alternatively, a bottom-up dynamic programming solution can be written, since there’s a clear order in which we process the subproblems. In any case, these methods should get the runtime down from exponential to O(NK).

Reconstructing The General Solution

We want to find the smallest N such that V(N, 365, 365) > 0.5. We could start from N = 365 and then keep trying larger values of N: since K is constant this is actually not that bad as we can reuse the results of computations from previous attempts when trying new values of N.

public static void main(String[] args) {
    long numPeople = 365;
    double successProbability = findSuccessProbability(numPeople, 365, 365);
    while (successProbability <= 0.5) {
        numPeople++;
        successProbability = findSuccessProbability(numPeople, 365, 365);
    }
    System.out.println(numPeople);
}

This gives us our answer: 2287. We have V(2286, 365, 365) = 0.499414 \ldots while V(2287, 365, 365) = 0.500371 \ldots.

This approach looks a bit primitive – and normally we’d use a modified binary search where we first search for an upper bound via something that grows exponentially, and then binary search up to our bound. This works, since V(p, q, r) increases as p increases for constant q, r.

However, for this specific problem and more generally for recurrences where we end up reducing parameters by 1, we still need to burn through almost all of the smaller subproblems we skip over by isolating the bound, so it won’t actually give us that much here.

Usually when working with recurrences it is nice to find a closed-form solution for our expression (i.e. we have a general expression for V(p, q, r) that doesn’t itself reference V), though I didn’t really see how to make progress with this one.