Reflections on Winning WeAreDevelopers CODE100
August 8, 2023 - 11 min readOn July 27, 2023, I won the first-ever edition of CODE100 at WeAreDevelopers World Congress in Berlin, which, with over 10,000 participants, is one of the largest developer events in the world. Participating was certainly one of the most thrilling experiences one can have in this industry.
In this article, I would like to take you on the journey of how it felt to participate in the event. And hopefully, this will be useful for those participating in the following years.
The competition consisted of 100 participants invited from an application, who competed across a total of 6 rounds:
- Playoffs (100 to 32): Solo multiple-choice quiz on the day before
- Round 1 (32 to 16): Solo multiple-choice quiz on stage
- Round 2 (16 to 8): Buzzer quiz in 4x4 teams
- Round 3 (8 to 4): Pair-programming
- Round 4 (4 to 2): Solo programming
- Round 5 (2 to 1): Solo programming
Playoffs
There isn’t much to say about the playoffs. All 100 participants gathered in front of the convention center, where the 32 finalists were selected through a 12-question multiple-choice quiz, which everyone completed on their phones.
Given the name CODE100, I, and most participants I talked to, expected to already be writing code that day. In that sense, it was a bit of a disappointment, but later I will explain why this still may have been the right call given the number of participants.
Round 1
Round 1 was the first round on stage. Everyone was feeling fresh and relaxed. Once again, we did a multiple-choice quiz on our phones. However, this time, you had to answer all 5 out of 5 questions correctly to proceed to the next round because there were so many who got all correct.
Due to having to answer all questions correctly, I almost had to leave after that round because I didn’t read the question properly. The only thing that saved me was that I accidentally didn’t submit yet and was still able to change my answer.
Don’t rush anything unless actually required because quality is usually king.
Round 2
The buzzer quiz during round 2 felt mostly luck-based. We were split up into 4 teams of 4 based on our positions in the previous round. The first team to hit the buzzer after the question was announced was allowed to answer. Correct answers were +10 points, wrong ones -5.
After 6 out of 7 rounds, one team had 30 points, and all others, including us, had 10 each. That meant that the last question would decide who gets to proceed. Fortunately, we were able to answer the question: “What is the difference between a class and an object?”
The reason why I say it felt mostly luck-based was that the questions weren’t particularly difficult. During the entire round, there was only ever one wrong answer given (by us). Instead, it all came down to who pressed the buzzer the fastest - and we are talking milliseconds here.
Round 3
Round 3 was by far the most stressful. Ahead of the event, I was 100% certain that I would be using Python throughout the competition due to its concise syntax and helpful features for data science. But this would turn out to be a pretty bad idea. Oh, and also, we couldn’t bring our own laptops, which meant that there was a noticeable learning curve for getting used to the keyboard in front of you. However, the organizers provided us with a standardized development environment powered by Daytona, including a browser-based cloud IDE which is based on VSCode. We were offered different environment presets depending on our programming language of choice. With Daytona’s assistance and Nikola Balic’s support, I was able to retrieve the code I wrote during the event.
The task was to sum up the continuous numbers within a given string: world20congress23
➡️ 43
(not 7). Throughout this and all of the following rounds, there was some boilerplate code that needed to be written every time: We were given login credentials, with which we had to fetch a JWT from an API to then get our challenge input, which after transforming, we would send to that API yet again.
Using Python turned out to be a real struggle since both my partner Thejas Malenahalli Niranjan, who I got randomly matched with, and I didn’t know how to loop over a string in Python. The solution we tried for creating a list of characters from a string was string.split('')
, but as it turns out, you cannot do that. The solution, in this case, is some syntax you just have to know: [*string]
. So, therefore, I suggest you
Stick to your home turf language and tools! This is not the time for experiments, so use what you know best. You don’t want to deal with unfamiliar quirks.
Round 3 was also the last round, where I was checking how well the others were doing. Given that we were struggling to complete the puzzle due to a lack of language knowledge and that the commentator (at least to me) made it seem like the team next to us was doing really great, I was expecting one of the other 3 teams to finish any second. But what I didn’t take into account was that everyone was struggling with the same challenges imposed by live coding.
Focus on yourself! Looking at others just takes time and, in the worst case, makes you panic.
We still managed to finish first by quite a lot. This meant that I had plenty of time to calm down, drink a whole lot of water backstage, and prepare myself mentally for the next round. Would there have already been a coding task during the playoffs for all 100 challengers, that very first round could have already ended up taking a very significant amount of time until the first 32 finish.
Round 4 - Semi-finals
I now learned from my mistake of choosing Python and went with JavaScript instead, given that I have by far the most hours working in that language.
The task was to find anagrams within an array of words and return them in a sorted order:
[ "kiwi", "melon", "apple", "lemon" ]
➡️ [ "lemon", "melon" ]
The rules stated that we could use Google but no AI tools. Having realized that, I decided it would be smart to not bother trying to write the anagram detection logic myself but rather get that logic piece from the internet. I found my solution in a Medium article. This effectively meant that I was able to greatly cut down the amount of logic I had to think through, which again gave me a huge time advantage.
Know the rules: The one who knows how to maximize their benefit within the given boundaries will be rewarded!
This was my final code for the semi-finals:
function areAnagram(str1, str2) {
// Removes spaces and convert into the lowercase letter
str1 = str1.replace(/\s/g, '').toLowerCase()
str2 = str2.replace(/\s/g, '').toLowerCase()
// console.log(str1, str2)
if (str1.length !== str2.length) {
return false
}
// Sort the characters in the given string
str1 = str1.split('').sort().join('')
str2 = str2.split('').sort().join('')
// Compare the sorted String
return str1 === str2
}
async function main() {
const res = await fetch('https://challenger.code100.dev/login', {
method:"POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"email": "ws2-round4@code100.dev",
"password":"8CH7-9K4V-XIXO"
})
})
const body = await res.json()
console.log(body)
const token = body.token
console.log(token)
const res2 = await fetch('https://challenger.code100.dev/getpuzzle', {
headers: {
"Authorization": `Bearer ${token}`
}
})
const body2 = await res2.json()
console.log(body2.input)
const words = body2.input
const anagrams = words.filter(word => {
let hasAnagram = false
for (const w of words) {
if (areAnagram(w, word) && w !== word) {
hasAnagram = true
}
}
return hasAnagram
})
anagrams.sort()
await fetch('https://challenger.code100.dev/postanswer', {
method:"POST",
headers: {
"Authorization": `Bearer ${token}`,
"content-type": "application/json"
},
body:JSON.stringify({
answer: anagrams
})
})
}
main()
As you will quickly see, this code is written rather poorly. Variable naming is bad, quote styles are all over the place, and don’t even get me started on spacing and indentation. But all of this didn’t matter because the code’s quality was not considered, and what this code did was deliver the correct solution.
Round 5 - Grand finals
Strangely enough, this round felt the least stressful to me: I was confident about my tech choice and had gotten quite used to being on stage by now. I had gotten a good idea about the kind of challenge that I could expect, and by now, I was used to the keyboard in front of me. I had learned from my mistakes, such as not adding the appropriate Content-Type
header. After another backstage break, I was ready!
Before the event started, I had raised the question of whether we could wear headphones for noise-canceling to avoid distractions. I had even prepared an entire playlist for the event. But as it turns out, at this point, I didn’t think about this at all anymore. Instead of distracting me, hearing the cheers from the crowd was rather mostly motivating and energizing. I deeply enjoyed interacting with the audience and going with the flow.
The final task was to extract the values from a linked list and return them as an ordered array:
{
"linkedList": [
{ "id": "b", "value": 2, "next": "c" },
{ "id": "c", "value": 3, "next": null },
{ "id": "a", "value": 1, "next": "b" }
],
"top": "a"
}
➡️ [ 1, 2, 3 ]
This time, I wasn’t about to take any risks. I was strategic about my code and executed it both times after writing the code for fetching the JWT and after getting the puzzle so that I could continue solving the puzzle without worrying that a previous bug would haunt me later on.
And this was the winning code:
async function main() {
const res = await fetch("https://challenger.code100.dev/login", {
method:"POST",
headers: {
"content-type":"application/json"
},
body: JSON.stringify({
email: "ws5-round5@code100.dev",
password:"7I0T-KBXI-U1N9"
})
})
const body = await res.json()
const token = body.token
console.log(token)
const res2 = await fetch("https://challenger.code100.dev/getpuzzle", {
headers: {
Authorization: `Bearer ${token}`
}
})
const body2 = await res2.json()
const input = body2.input
console.log(input)
const answer = []
let id = input.top
while (true) {
const node = input.linkedList.find(n => n.id === id)
id = node.next
answer.push(node.value)
if (!id) break
}
console.log(answer)
fetch('https://challenger.code100.dev/postanswer', {
method:"POST",
"headers": {
"content-type":"application/json",
Authorization: `Bearer ${token}`
},
body: JSON.stringify({
answer
})
})
}
main()
The solution I wrote is incredibly pragmatic: With quadratic time complexity, it is inefficient, but that was fine because the input data only consisted of 100 nodes. I have absolutely no idea about the approach my competitor took, given that I was in full tunnel vision. All I can tell you is that this piece of code secured the victory for me!
Try to find the Minimal Viable Code if a correct solution is all that’s required.
Preparation
One of the questions I got the most after the event was about what I did to prepare. Contrary to most expectations, I, in fact, didn’t specifically prepare for the competition. We were given very few hints about the challenges we would face, which means that any sort of preparation would have been based on unfounded assumptions.
The only “preparation” I did was take a 2-hour nap before the event. Being well-rested was great, but I am not sure if that was the deciding factor. I was confident in my abilities and was aiming for the stars. This time, it worked out, but there have also been plenty of occurrences where things didn’t work out as planned. My strategy has recently been to fire as many shots as possible, celebrate the victories, and not give too many Fs about the failures.
Conclusion
I believe the two key factors to my success were radical pragmatism when writing code and the courage to work within the rules to my advantage.
I am incredibly happy to have participated in this event! I’ve learned that I actually really enjoy being on stage. I found putting myself out there to be incredibly enjoyable and rewarding. And maybe the same applies to you…
Resources
Watch the full event on YouTube
Give the challenges a shot yourself on GitHub