It’s not just putting text on my screen, it’s so much more! For example, it somehow manages to prevent my browser from scrolling the content with space bar (quite common these days), arrow keys (not that common, but happens every now and then), Page Up / Page Down (what? Not entirely unfamiliar, but surprising), and even Home / End buttons (don’t think any other website managed that). Only touchpad works.
It’s stuck this way no matter what I click (sometimes it’s just focused on some invisible element and clicking on content (and hoping I don’t hit a popup trigger) helps).
Noscript. No text. No luck. Lifting the restriction on notion.so does nothing, I’m still redirected here, with no chance to unblock whatever needs unblocking — because at this point I no longer see what I need unblocking. First time I see a website redirecting me to a different URL just to tell me I need to turn on Javascript.
Sorry I can’t comment on the actual content. I… kinda didn’t get a chance to read it.
I created a gist containing the content (hopefully I didn’t break any licenses) here. Feel free to tell me I’m wrong, I will delete it. Hopefully GitHub would work better (though it might still be bad)
You need to lift it on notion.site I think, although I gave up after I couldn’t figure it out and kept getting redirected.
Web developers, please heed my plea: don’t redirect noscripting users!! Especially not to another domain.
If I’m interested enough, I’ll enable JS for your site. I’m used to doing this, despite the fact that I primarily read text and submit basic forms on the internet. I’m even patient enough to allowlist your myriad 3rd party scripts.
I have JS on by default, but I got tripped up by that too.
I noticed that the page was a bit slow and, more importantly, that it hijacks my arrow keys which I use to finetune my scroll position. Since that is often fixed by disabling JS without any ill effects, I flipped the scripts temporarily off in uBlock for the domain and reloaded. Since it would now immediately take me to another domain, to turn the scripts back on it was easiest to just restart Firefox.
I can’t believe this is real, I thought this was a hexing the technical interview deal until the end. Hope OP gets a job that befits their vast skills.
I’m mixed on interviews like fizzbuzz. I don’t perform well on them despite going on two decades of experience, being a ruby core contributor, and open source maintainer with billions of downloads: it’s just not an interview environment I thrive in. To the point that avoiding having to do a technical interview is a non-trivial reason I’m still at my current job.
I’ve also worked with developers that seemed to be unable to write code and wished we had done some more low pass coding filtering. So u understand where interviewers are coming from.
The last intern I hired worked out incredibly well and I got to pick the technical interview tactic. I chose “show me some code you’ve written (that isn’t proprietary and you have permission to share/show) and walk me through some part of it” I also gave them the option to choose a whiteboard style question to pair on if they either didn’t have something they were able or willing to show. It worked very well. The candidate we choose showed me a PR of theirs and was able to explain what it did, why it was done that way and answer some questions about the general codebase. The code showed they could generate code, the interview part showed their communication skills. You could also get a hint of their values: were they a fast prototyper with single letter variable names or did they write tests and refactor? Did they stop when it worked or did they go back and clean up the implementation? No wrong answers, every org needs a mix of people with skills and abilities.
Ive also sat through amazing interviews from people I wish we could have hired, but we chose another candidate due to reasons outside of that candidates control (such as another candidate having a unique skill or experience fit). A lot of not getting a job has more to do with the company’s needs and candidate pool than with individual performance (assuming it’s above some baseline). Anywhoo, this is an interesting post and has some neat solutions. I hope to never need them IRL.
imho one of the best interview tactics regarding skills was the one i had at my current jobs intervew.
it was an in-person interview, and we didnt had computers at hand, except for the hr person writing notes.
to test my coding skills, they just handed me two sheets of paper with code printed (a c++ header and implementation) and they asked me to do a code review.
it was super pressure free as you can apply knowledge, but dont have to come up with solutions under pressure
from an interviewer standpoint it’s also valuable as you test how the applicant communicates.
Yeah, I’ve had this before and I’ve found it very difficult if you’re just given a piece of code. I mean, I can look for things that look surprising or incorrect, but if I can’t see the broader context for the change - the ticket and discussion that triggered it, the rest of the changes being made, the developer(s) involved, the code that was there beforehand, the libraries and internal APIs that are being used and available, etc etc - then it’s very difficult to know what to focus on.
I used to think this was a good way of doing interviews, but since experiencing it as an interviewee, I’ve gone off it a lot, to the point that it’s a bit of an amber flag at this point.
A month has passed and I got no response, no feedback, nothing…
I know being ghosted like that sucks, but it could have always been worse – they could’ve written back to offer them a position. This was a dodged bullet if I’d ever seen one.
Making challenges arbitrarily and progressively harder is a useful interviewing device, to some degree, provided that:
\1. There is some plausible connection between the restrictions you introduce and the challenges your environment presents. “Maximum of 30 lines”, “100 characters per line with natural breaks” – what the bloody hell happened here, someone ported Node.js on OS/360 and they’re writing their backend code on punchcards? “Numeric types are forbidden” for numeric algorithms? Did OP get tricked into going to a casting for The Daily WTF instead of a tech interview? You have a limited window of time to see how someone writes code and whether they’d be a good fit or not; why would you waste it asking them to write the kind of code that, hopefully, they would never deliberately write, and which would hopefully never make it past review!?
\2. You explain the context of each “rule” you’re introducing, so they understand the general context, otherwise you’re just testing for flex rather than system understanding.
You give them the exercise, they write their first iteration, then you go okay, let’s explore some scenarios – and you start with common sense and very plausible stuff, like this is an embedded system, no dynamic memory allocation or whatever. I’m not sure what the TypeScript equivalent of that is. If there isn’t one, and there’s literally nothing plausible to be concerned about, great – why even bring it up?
Once you’ve exhausted common sense – or at least common – limitations you start acknowledging that some of them are fanciful or artificial, and you begin phrasing them as open-ended questions – can we eliminate this mutex? Can we eliminate them all? Can we write it in a way that doesn’t require any local, stack-allocated variables? Once you get to the kind of things that belong in whatever the Node.js equivalent of IOCCC is, you don’t even ask them to implement a full solution anymore, that’s completely fucking pointless, at this stage you’re just checking if they know what system features to reach out for, or what restrictions they need to apply.
We do this whole “progressively harder thing” to look for three major things:
a) To see if the person you’re interviewing understands what properties of a system make various solutions possible, if they know the alternatives to each and how you use them, and if they can reason about their trade-offs.
b) To see if they can recognise when something simply isn’t feasible anymore and needs some basic assumptions or some systems design features re-examined, instead of nodding yes and trying to get something that shouldn’t even be a thing to work for weeks.
c) To see if they can examine their code critically and articulate exactly what assumptions they made, and what they need to change if they no longer hold.
If you just add arbitrary rules until they break, that’s not a coding interview, that’s just making fun of people. If you’ve deliberately pushed the whole thing to the point where it can’t be solved and you know it, it’s just basic professional courtesy to tell them. Don’t tell them “well, it’s okay if you don’t get this to work, or if you get it to work in a way that will pass my completely arbitrary bar for ‘not breaking a rule too hard’ which of course I’m not going to disclose”. Push it to that point; if they don’t “get it”, offer them a hint so they can recognize it’s unsolvable. If you’re not sure it’s solvable at that point, maybe lead with that.
\3. You “up the ante” with some sort of structure, based on #1. I.e. you add some restrictions based on each solution, just to see if someone can think critically, rather than regurgitate solutions they know by heart. But there are some restrictions that you introduce for all candidates, and those are the main markers you’re looking at. Also, you do it with a modicum of reproducibility and control. Rules 9, 10, and 11 are not just bullshit, they just skew the interview process towards people that the interviewer likes, or towards people who’ve done this kind of challenge before so they know how to formulate each solution in a way that maximizes the number of “easy” rules being introduced and avoids the “hard” ones.
Exercises like Fizzbuzz ‘used to be popular’ for a reason. They’re an insult to the intelligence of actually qualified candidates, and there are far better ways to weed out the manifestly unqualified candidates who can’t even make a start on it.
If I were interviewing from the position of already having a good job and merely scouting for potentially greener pastures, I would feel at liberty to take the piss out of such an exercise by re-interpreting it as ‘create a term-rewriting system’ or ‘create a Scheme interpreter in Prolog’. (Well, more likely I’d just end the interview; I don’t think I have quite such a skill for dreaming up such computational perversions on-the-spot.) Starting from a place of (long-term) unemployment is different; it’s probably better to just go along with whatever exercise you get and solve it in a normal way. You can maybe see it as a sign of a company culture you won’t want to stay in too long, but getting the job would nonetheless let your foot on the ladder, and let you approach future interviews from a position of confidence and not desperation.
On the other hand, changing the rules post facto because the candidate is finding follow-up questions too easy is also just a shitty move. If your interview question isn’t proving sufficiently challenging because of a candidate’s choice of tool, that’s on you for allowing a free choice of tool to begin with. Why should it be considered a negative for the candidate to have chosen a tool that made the task easier than you expected?
It’s also not hard to see racism in the way the company treated him here. Unfortunately, stereotyping southern Europeans as lazy, stupid, incompetent etc. is common here in northern Europe.
Perhaps offer them the opportunity to not require the Fizzbuzz? My last company for instance systematically proposes a “coding game”, triva and small programming problems to solve at home (~1h), before it is examined by the technical interviewer. I recall one experienced dev having refused to do it, no problem, I just picked a few relevant questions and asked him directly. He demonstrated in 5 minutes that he knew his stuff better than I did. We hired him.
I got to the part about divisors of ******* (removed for spoilers) and decided it was time to bust out “L’s Theme”, track four of the Death Note OST, and continue reading.
honestly doing zachtronics games for job jnterviews is great.
either people already have aced the games. this means you know they can solve hard problems.
or they have not, and you can then see how people handle new, unfamiliar concepts presented in a realistic way
It reminds me of those german fairytales were a farmer’s son manages to ‘win’ a princess by solving a task set up by the king, only for the king not to like his new potential son-in-law and setting him up with continuously difficult (and impossible) tasks, which the farmer’s son is able to solve by mystical intervention, often via a mysterious ‘grey man’.
A good example is the fairytale ‘Der Hasenhirt’ by Johann Wilhelm Wolf.
Seems like a case where the candidate was outperforming the interviewer :’) Sounds like you dodged a bullet there. In general, companies which don’t send a rejection are annoying and I wouldn’t want to work at a company that treats there candidates as such.
The salary didn’t seem a Netherlands-like salary, they offered 50.000€ gross / year.
I’m a software developer in the Netherlands and it’s not the highest but I wouldn’t call it low.
It’s not terribly high but I can totally see this being the salary for many junior or medior job openings.
I had an offer for 48k two years ago when I had about 4.5 years of experience (as a frontend engineer, in a relatively large city). Salaries are probably significantly higher in the financial sector in Amsterdam, and probably lower when you’re doing frontend for a small local company in Drenthe.
I’ve been paying between 400 and 1100 for rent/mortgage, it’s very feasible even in a relatively expensive city.
There are a lot of reasons not to get the job. Some things I keep in mind
You are also interviewing the company, the ‘good fit’ bridge goes both ways, (for example, your would be manager would hate you for being more brilliant than them, or the company might not appreciate genius, do you really think those are good situations to be in?)
All companies operate between -10,000 and 40% efficiency. Sometimes it’s just a fluke.
When someone is smoking the interview it is important to switch from evaluation to selling the candidate on the company as fast as possible (you want to hire this guy, right?!?!).
Trying to make the interview harder for them is a rookie move.
or example, your would be manager would hate you for being more brilliant than them
I’ve had that happened to me explicitly. I do the interview, it goes well, and a few days later they tell my manager they can’t have me, because I’m more competent than their project lead, and it wouldn’t work out. My manager was fuming, but for my part I thank them for their candour.
I wonder how Rule #7 could be applied in system languages like C, C++, Zig, Rust, …
Numeric types, number literals and their associated methods and operations are forbidden. The input array must contain a string representations of the numbers.
Strings are just arrays of numbers and 'A' is equivalent to writing 65, the same as "A" is the same as &[2]u8 { 65, 0 } (Zig Syntax), so i’m kinda confused how one should be ever able to solve this based on this rule, especially as they gave one free hand on the programming language
Rust probably shouldn’t be in that list. In rust strings are meaningfully not just arrays of number, rather they are utf-8 sequences. More importantly for the problem at hand you don’t access them via numbers, but via methods that return things like an iterator of chars (utf32 values) or other strings.
You definitely could implement this in rust without touching any numeric type. Why you would want to… how it would reflect on your ability to do normal coding tasks… well that’s another question.
I have in mind a terrible solution that just iterates over every possible input (there are only 1000 of them) and checks against a generated list of strings. Since I think I could generate (i, fizzbuzz(i)) as an iterator in only five or six lines of code without numbers (in rust).
char still is a numeric type tho, as it’s defined to be an integer number.
hm, using recursive generators would be a fun idea, especially with the base-15 trick.
then you just have to search for the index. but how would you do that without a number literal? i guess we could compare strings, ans every string lexically smaller than "1000" would be ok?
it’s a tough task for an interview tho, i wonder why they chose this.
Rust char is unrelated to C char, its not an integer, you can’t do things like char + char, you can’t assign any value in 0..=u32 (rust char is 32 bits) that you like to it - invalid codepoints are instant undefined behavior, etc. Rust just uses i8 (or u8 depending on platform, frustratingly) as its synonym for C char.
You can cast it to an int, and you can convert ints to rust char (though the latter either involves a runtime check or unsafe), but I don’t think that makes it any more a numeric type than a pointer (actually… can I use pointer arithmetic? Rust pointers are allowed to take on any value and do have arithmetic methods…).
but how would you do that without a number literal
The simple way is just a direct scan over every possibility.
re: char: Yeah, i’ve got that, i’ve read the docs before answering. Imho it’s still a numeric type with a well-defined integer semantic, but it’s a non-arithmetic type.
re: generator:
what would iter_input_output do? because if the input is invalid, the generator would generste infinitly long strings.
or well. we can also encode “recursion depth” in string length, appending a character each recursion length until we reach a predefined string. we can’t slice off characters as this would need an index of sorts, so we have to append and compare.
Rust makes it really easy to truncate iterators, thankfully
let iter_input_output = numbers.take_while(|n| n != "1001").zip(output);
I was also just going to hardcode the length of the iterator, not because I need to but because a better way to generate numbers hasn’t promptly occurred to me. There are nested function solutions that would be ugly… but… nothing elegant.
Here, I typed the rest of an untested solution (it probably has typos).
I even avoided char in case the interviewers agree with you. Of course this is still a terrible solution because it doesn’t directly compute the function at hand, I doubt I’m getting hired (or want to get hired) either.
PS. An elegant-ish version of infinite numbers using an unstable (and 2024-edition only) feature
#![feature(gen_blocks)]
fn numbers() -> Box<dyn Iterator<Item=String>> {
Box::new(gen {
for d in ["1", "2"] {
yield d.to_string()
}
for suffix in numbers() {
for d in ["0", "1", "2"] {
yield format!("{suffix}{d}")
}
}
})
}
It seems fairly clear given the requirement that “The input array must contain a string representations of the numbers.”. Without numeric operations, you can’t really take advantage of the underlying numeric nature of characters. I’d have been tempted to declare the input as being in base 15 which would make the problem easier.
While the base algorithm is very simple, the point of the exercise is that the interviewer will add new rules to test how you update the code while keeping it readable and maintainable.
Is that the point? I have only ever known FizzBuzz as a test to see if someone could program AT ALL.
I thought it was an interesting test, and one that might spread and get taken up: it’s not just testing your ability to program with a simple, well-known exercise, but it’s testing your ability to keep adapting to ever-changing goals and restrictions, which like it or not is undeniably very much a real-world skill.
I don’t believe OP’s story is completely honest, that under pressure he figured to change the base so that the trailing digit was always a multiple of a divisor of the base. Just seems random to come up with that.
I’d say that was a fairly obvious move to me, from stuff I learned in first year undergrad. Definitely stuff you could figure out on the back of an envelope if you’re already in the headspace of thinking about digits and representation of integers.
The status of numeric bases in undergraduate (and even secondary education) also seems to vary wildly by country, when you went to school, and how many leetcode-style challenges you’ve done.
I don’t remember the specifics, and I certainly can’t claim I would’ve thought about that, but I remember being shown a variant of that in 5th or 6th grade or whenever the hell they taught me numeric bases. It was something about how each numeric base has its own divisibility rules, and that they all have their own variant of “if it ends with a 5 or a 0”. When I went to school, numeric bases were definitely important enough that I remember reaching out for various “useful” properties related to them up to my last year of high school (after which I was thankfully spared the plight of exam-driven mathematics…).
Also, this seems to be surprisingly popular in some interviewing niches. Over the years I’ve ran into several interns or fresh graduate juniors who’d memorized very weird divisibility rules that are definitely not covered in school, like divisibility by 19 or that subtract-last-digit-from-twice-the-rest rule for divisibility by 12. When I asked about it (number theory is one of those things that’s always fascinated me but I never had time for so I try to live vicariously through whoever seems to have an interest in it) they all told me they have zero interest in number theory in general but these things sometimes come up in coding challenges and knowing them is useful.
The trick behind divisibility by a number n, is to check for 10^i % n, and see if you see a pattern. 2 and 5 have the easiest pattern: powers of 10 modulo 2 or 5 always equal zero, except for 10^0 (that is, 1). Which means you only have to look at the last digit to know if you have a multiple of 2 or 5.
3 and 9 have the next easiest rule. Turns out that for all i, 10^i % 3 = 1. Same for 9. In practice this means that 10*n % 3 = n % 3 (same for 9), and you can recursively divide by 10 the higher digits until you only get a sum of “unit” digits. And of course, the rule works recursively, so just rinse and repeat until you get a single digit, and voilà you know if it’s a multiple of 3 or 9.
4 I don’t know at the top of my head, but it’s easy to find:
10^0 = 1 % 4
10^1 = 2 % 4
10^2 = 0 % 4
10^3 = 0 % 4
// all zero from now on
So only the last 2 digits contribute. So for a number xxxxab, you just sum 2*a + b, and see if that is a multiple of 4. Another way of seeing it is, if a is even then b must be 0, 4, or 8. If it’s odd, b must be 2 or 6.
Since 12 = 3*4, and 3 and 4 are coprimes, to test if something is a multiple of 12 you just test if it’s a multiple of 3 and a multiple of 4. Very easy.
Now let’s try 12…
10^0 = 1 % 12
10^1 = 10 % 12 = -2 % 12
10^2 = 4 % 12
10^3 = 4 % 12
// It’s all 4 from now on
Okay, so the rule is a little unhinged: all digits count 4 times, except the first (it counts normally), and the penultimate one (it counts minus double — easier than counting 10 times). So… I would:
Sum all numbers except the last 2.
Multiply by 2.
Subtract the penultimate digit.
Multiply by 2.
Add the first digit.
Repeat the above recursively, until I get a single digit. Only good result is zero. Oh and by the way you may go through negative numbers while doing the procedure.
No fucking way that’s easier than just checking for 3 and 4, no matter how many digits… unless perhaps we start exploring more advanced strategies.
For big numbers one does not simply do sums. Okay then, let’s shave some numbers. For 3 you can:
c = 0
for each digit d
if d == 0, 3, 6, or 9 -> ignore.
if d == 1, 4, or 7 -> c = c+1
if d == 2, 5, or 8 -> c = c-1
if c == 3 or -3 -> c = 0
I believe this is as simple as it gets. O(nb_digits) time, O(1) space, I think 12’s strategy can’t get any simpler — I suspect it is nearly identical except at the end, but not simpler.
Hey! I accidentally found an algorithm to solve this stupid Fizzbuzz without having to change the base, and without the sum lookup matrix!
Err… yes, you’re correct, that’s the true insight. Now since the table is banned, I’m still gonna use a switch statement to obfuscate it into code, so they can’t say I “hardcoded” it — even though the switch statement would be even more hard coded than the table…
I have absolutely no idea. I obviously have no idea how or why that would ever come up in a coding challenge but I really don’t know how that’s a useful rule in general, either. The best hypothesis I could come up with was that maybe, since lots of units are duodecimal (12 months in a year, 12 pence in a shilling, 12 inches in a foot etc.) knowing the multiples of 12 by heart up to 120 was pretty common at some point. In that case, this is a convenient way to check for divisibility by 12 for numbers up to 600 or so without actually doing any division or multiplication – if you can add numbers, you can double them, too.
But I’m really not convinced. Anyone who knows the multiples of 12 up to 120 and can add numbers can presumably check for divisibility by 3 for numbers up to 600 or so, and you don’t need to do any arithmetic to check for divisibility by 4, either.
If I had to guess, I’d say it’s just a common result that pops up in undergrad number theory courses or something. There are similar criteria for 7, 11, 13, and probably others I don’t remember right now.
I’ve worked with people like that and I wouldn’t hire them either.
They might be great at working on their own but will have difficulty fitting into a team. They can’t resist the temptation to show off when what you really need is code that the whole team can maintain. Also trying to keep them on track is a nightmare, you may have a pressing business need that gets ignored whilst they go off in their own direction.
Erm, it’s worth remembering that they actually started with the canonical FizzBuzz implementation. They ended up with that weird type thing after the interviewers introduced additional “rules”, chief among them being that they couldn’t use numeric types, number literals, or associated methods and operators, and it all had to fit in no more than 30 lines without any minifying tricks.
They didn’t do that to show off, the interviewers literally asked for a solution like that.
A type-based implementation is actually not a bad idea at all – it’s clean, a core language feature, and easy to adapt if the “no more than 30 lines rule” turns into “no more than 20 lines actually”. The numeral base quirk was added because the interviewer objected to the sum table as “partially hardcoding the solution” (!?).
Hopefully their internal codebases doesn’t actually store numbers as strings and operates on them without any numerical operators. Why they’d ask for that kind of stuff in an interview is anyone’s guess.
Interesting write up but oh my god this website needs to load 28 mega bytes of garbage for putting some text on my screen?
Whoa! Firefox Network panel just confirmed that for me - 255 files, 28MB total (only 7MB transferred thanks to compression).
I get that Notion is an “app” but come on, that’s absurd.
lmao. The actual text is 22 kb (without markup). That’s a glorious 0.07% ratio between content and form.
It’s not just putting text on my screen, it’s so much more! For example, it somehow manages to prevent my browser from scrolling the content with space bar (quite common these days), arrow keys (not that common, but happens every now and then), Page Up / Page Down (what? Not entirely unfamiliar, but surprising), and even Home / End buttons (don’t think any other website managed that). Only touchpad works.
It’s stuck this way no matter what I click (sometimes it’s just focused on some invisible element and clicking on content (and hoping I don’t hit a popup trigger) helps).
Impressive!
Noscript. No text. No luck. Lifting the restriction on notion.so does nothing, I’m still redirected here, with no chance to unblock whatever needs unblocking — because at this point I no longer see what I need unblocking. First time I see a website redirecting me to a different URL just to tell me I need to turn on Javascript.
Sorry I can’t comment on the actual content. I… kinda didn’t get a chance to read it.
I created a gist containing the content (hopefully I didn’t break any licenses) here. Feel free to tell me I’m wrong, I will delete it. Hopefully GitHub would work better (though it might still be bad)
Fortunately, you can get GitHub to deliver you the raw binary directly
Hopefully, archive.is works better
archive.is is worse because it sometimes wants a CAPTCHA, and raw-data GitHub URL is fine for a wide range of ways to fetch it.
You need to lift it on notion.site I think, although I gave up after I couldn’t figure it out and kept getting redirected.
Web developers, please heed my plea: don’t redirect noscripting users!! Especially not to another domain.
If I’m interested enough, I’ll enable JS for your site. I’m used to doing this, despite the fact that I primarily read text and submit basic forms on the internet. I’m even patient enough to allowlist your myriad 3rd party scripts.
I have JS on by default, but I got tripped up by that too.
I noticed that the page was a bit slow and, more importantly, that it hijacks my arrow keys which I use to finetune my scroll position. Since that is often fixed by disabling JS without any ill effects, I flipped the scripts temporarily off in uBlock for the domain and reloaded. Since it would now immediately take me to another domain, to turn the scripts back on it was easiest to just restart Firefox.
I can’t believe this is real, I thought this was a hexing the technical interview deal until the end. Hope OP gets a job that befits their vast skills.
I’m mixed on interviews like fizzbuzz. I don’t perform well on them despite going on two decades of experience, being a ruby core contributor, and open source maintainer with billions of downloads: it’s just not an interview environment I thrive in. To the point that avoiding having to do a technical interview is a non-trivial reason I’m still at my current job.
I’ve also worked with developers that seemed to be unable to write code and wished we had done some more low pass coding filtering. So u understand where interviewers are coming from.
The last intern I hired worked out incredibly well and I got to pick the technical interview tactic. I chose “show me some code you’ve written (that isn’t proprietary and you have permission to share/show) and walk me through some part of it” I also gave them the option to choose a whiteboard style question to pair on if they either didn’t have something they were able or willing to show. It worked very well. The candidate we choose showed me a PR of theirs and was able to explain what it did, why it was done that way and answer some questions about the general codebase. The code showed they could generate code, the interview part showed their communication skills. You could also get a hint of their values: were they a fast prototyper with single letter variable names or did they write tests and refactor? Did they stop when it worked or did they go back and clean up the implementation? No wrong answers, every org needs a mix of people with skills and abilities.
Ive also sat through amazing interviews from people I wish we could have hired, but we chose another candidate due to reasons outside of that candidates control (such as another candidate having a unique skill or experience fit). A lot of not getting a job has more to do with the company’s needs and candidate pool than with individual performance (assuming it’s above some baseline). Anywhoo, this is an interesting post and has some neat solutions. I hope to never need them IRL.
imho one of the best interview tactics regarding skills was the one i had at my current jobs intervew. it was an in-person interview, and we didnt had computers at hand, except for the hr person writing notes.
to test my coding skills, they just handed me two sheets of paper with code printed (a c++ header and implementation) and they asked me to do a code review.
it was super pressure free as you can apply knowledge, but dont have to come up with solutions under pressure
from an interviewer standpoint it’s also valuable as you test how the applicant communicates.
Which, frankly, is much harder than writing code.
Yeah, I’ve had this before and I’ve found it very difficult if you’re just given a piece of code. I mean, I can look for things that look surprising or incorrect, but if I can’t see the broader context for the change - the ticket and discussion that triggered it, the rest of the changes being made, the developer(s) involved, the code that was there beforehand, the libraries and internal APIs that are being used and available, etc etc - then it’s very difficult to know what to focus on.
I used to think this was a good way of doing interviews, but since experiencing it as an interviewee, I’ve gone off it a lot, to the point that it’s a bit of an amber flag at this point.
It depends on the context. Here, it was an isolated piece of code, fully visible.
It wasn’t the worst code either, but it had flaws an experienced programmer could quickly recognize.
But yes, in general i agree that reviewing code is harder, but also less stressful under pressure
I know being ghosted like that sucks, but it could have always been worse – they could’ve written back to offer them a position. This was a dodged bullet if I’d ever seen one.
Making challenges arbitrarily and progressively harder is a useful interviewing device, to some degree, provided that:
\1. There is some plausible connection between the restrictions you introduce and the challenges your environment presents. “Maximum of 30 lines”, “100 characters per line with natural breaks” – what the bloody hell happened here, someone ported Node.js on OS/360 and they’re writing their backend code on punchcards? “Numeric types are forbidden” for numeric algorithms? Did OP get tricked into going to a casting for The Daily WTF instead of a tech interview? You have a limited window of time to see how someone writes code and whether they’d be a good fit or not; why would you waste it asking them to write the kind of code that, hopefully, they would never deliberately write, and which would hopefully never make it past review!?
\2. You explain the context of each “rule” you’re introducing, so they understand the general context, otherwise you’re just testing for flex rather than system understanding.
You give them the exercise, they write their first iteration, then you go okay, let’s explore some scenarios – and you start with common sense and very plausible stuff, like this is an embedded system, no dynamic memory allocation or whatever. I’m not sure what the TypeScript equivalent of that is. If there isn’t one, and there’s literally nothing plausible to be concerned about, great – why even bring it up?
Once you’ve exhausted common sense – or at least common – limitations you start acknowledging that some of them are fanciful or artificial, and you begin phrasing them as open-ended questions – can we eliminate this mutex? Can we eliminate them all? Can we write it in a way that doesn’t require any local, stack-allocated variables? Once you get to the kind of things that belong in whatever the Node.js equivalent of IOCCC is, you don’t even ask them to implement a full solution anymore, that’s completely fucking pointless, at this stage you’re just checking if they know what system features to reach out for, or what restrictions they need to apply.
We do this whole “progressively harder thing” to look for three major things:
a) To see if the person you’re interviewing understands what properties of a system make various solutions possible, if they know the alternatives to each and how you use them, and if they can reason about their trade-offs.
b) To see if they can recognise when something simply isn’t feasible anymore and needs some basic assumptions or some systems design features re-examined, instead of nodding yes and trying to get something that shouldn’t even be a thing to work for weeks.
c) To see if they can examine their code critically and articulate exactly what assumptions they made, and what they need to change if they no longer hold.
If you just add arbitrary rules until they break, that’s not a coding interview, that’s just making fun of people. If you’ve deliberately pushed the whole thing to the point where it can’t be solved and you know it, it’s just basic professional courtesy to tell them. Don’t tell them “well, it’s okay if you don’t get this to work, or if you get it to work in a way that will pass my completely arbitrary bar for ‘not breaking a rule too hard’ which of course I’m not going to disclose”. Push it to that point; if they don’t “get it”, offer them a hint so they can recognize it’s unsolvable. If you’re not sure it’s solvable at that point, maybe lead with that.
\3. You “up the ante” with some sort of structure, based on #1. I.e. you add some restrictions based on each solution, just to see if someone can think critically, rather than regurgitate solutions they know by heart. But there are some restrictions that you introduce for all candidates, and those are the main markers you’re looking at. Also, you do it with a modicum of reproducibility and control. Rules 9, 10, and 11 are not just bullshit, they just skew the interview process towards people that the interviewer likes, or towards people who’ve done this kind of challenge before so they know how to formulate each solution in a way that maximizes the number of “easy” rules being introduced and avoids the “hard” ones.
Exercises like Fizzbuzz ‘used to be popular’ for a reason. They’re an insult to the intelligence of actually qualified candidates, and there are far better ways to weed out the manifestly unqualified candidates who can’t even make a start on it.
If I were interviewing from the position of already having a good job and merely scouting for potentially greener pastures, I would feel at liberty to take the piss out of such an exercise by re-interpreting it as ‘create a term-rewriting system’ or ‘create a Scheme interpreter in Prolog’. (Well, more likely I’d just end the interview; I don’t think I have quite such a skill for dreaming up such computational perversions on-the-spot.) Starting from a place of (long-term) unemployment is different; it’s probably better to just go along with whatever exercise you get and solve it in a normal way. You can maybe see it as a sign of a company culture you won’t want to stay in too long, but getting the job would nonetheless let your foot on the ladder, and let you approach future interviews from a position of confidence and not desperation.
On the other hand, changing the rules post facto because the candidate is finding follow-up questions too easy is also just a shitty move. If your interview question isn’t proving sufficiently challenging because of a candidate’s choice of tool, that’s on you for allowing a free choice of tool to begin with. Why should it be considered a negative for the candidate to have chosen a tool that made the task easier than you expected?
It’s also not hard to see racism in the way the company treated him here. Unfortunately, stereotyping southern Europeans as lazy, stupid, incompetent etc. is common here in northern Europe.
Perhaps offer them the opportunity to not require the Fizzbuzz? My last company for instance systematically proposes a “coding game”, triva and small programming problems to solve at home (~1h), before it is examined by the technical interviewer. I recall one experienced dev having refused to do it, no problem, I just picked a few relevant questions and asked him directly. He demonstrated in 5 minutes that he knew his stuff better than I did. We hired him.
Absolutely wild rollercoaster of a story.
I got to the part about divisors of ******* (removed for spoilers) and decided it was time to bust out “L’s Theme”, track four of the Death Note OST, and continue reading.
Honestly, let’s just have people play SHENZHEN I/O in front of you instead of trying to build a poor one yourself.
honestly doing zachtronics games for job jnterviews is great. either people already have aced the games. this means you know they can solve hard problems. or they have not, and you can then see how people handle new, unfamiliar concepts presented in a realistic way
It reminds me of those german fairytales were a farmer’s son manages to ‘win’ a princess by solving a task set up by the king, only for the king not to like his new potential son-in-law and setting him up with continuously difficult (and impossible) tasks, which the farmer’s son is able to solve by mystical intervention, often via a mysterious ‘grey man’.
A good example is the fairytale ‘Der Hasenhirt’ by Johann Wilhelm Wolf.
Seems like a case where the candidate was outperforming the interviewer :’) Sounds like you dodged a bullet there. In general, companies which don’t send a rejection are annoying and I wouldn’t want to work at a company that treats there candidates as such.
I’m a software developer in the Netherlands and it’s not the highest but I wouldn’t call it low.
This is quite low. How would anybody in the Netherlands be able to rent a place on 50k gross?
It’s not terribly high but I can totally see this being the salary for many junior or medior job openings.
I had an offer for 48k two years ago when I had about 4.5 years of experience (as a frontend engineer, in a relatively large city). Salaries are probably significantly higher in the financial sector in Amsterdam, and probably lower when you’re doing frontend for a small local company in Drenthe.
I’ve been paying between 400 and 1100 for rent/mortgage, it’s very feasible even in a relatively expensive city.
Fun write up.
There are a lot of reasons not to get the job. Some things I keep in mind
You are also interviewing the company, the ‘good fit’ bridge goes both ways, (for example, your would be manager would hate you for being more brilliant than them, or the company might not appreciate genius, do you really think those are good situations to be in?)
All companies operate between -10,000 and 40% efficiency. Sometimes it’s just a fluke.
Also, they had inexperienced interviewers.
When someone is smoking the interview it is important to switch from evaluation to selling the candidate on the company as fast as possible (you want to hire this guy, right?!?!).
Trying to make the interview harder for them is a rookie move.
I’ve had that happened to me explicitly. I do the interview, it goes well, and a few days later they tell my manager they can’t have me, because I’m more competent than their project lead, and it wouldn’t work out. My manager was fuming, but for my part I thank them for their candour.
I wonder how Rule #7 could be applied in system languages like C, C++, Zig, Rust, …
Strings are just arrays of numbers and
'A'is equivalent to writing65, the same as"A"is the same as&[2]u8 { 65, 0 }(Zig Syntax), so i’m kinda confused how one should be ever able to solve this based on this rule, especially as they gave one free hand on the programming languageRust probably shouldn’t be in that list. In rust strings are meaningfully not just arrays of number, rather they are utf-8 sequences. More importantly for the problem at hand you don’t access them via numbers, but via methods that return things like an iterator of
chars (utf32 values) or other strings.You definitely could implement this in rust without touching any numeric type. Why you would want to… how it would reflect on your ability to do normal coding tasks… well that’s another question.
I have in mind a terrible solution that just iterates over every possible input (there are only 1000 of them) and checks against a generated list of strings. Since I think I could generate (i, fizzbuzz(i)) as an iterator in only five or six lines of code without numbers (in rust).
charstill is a numeric type tho, as it’s defined to be an integer number.hm, using recursive generators would be a fun idea, especially with the base-15 trick.
then you just have to search for the index. but how would you do that without a number literal? i guess we could compare strings, ans every string lexically smaller than
"1000"would be ok?it’s a tough task for an interview tho, i wonder why they chose this.
Rust
charis unrelated to Cchar, its not an integer, you can’t do things likechar + char, you can’t assign any value in 0..=u32 (rust char is 32 bits) that you like to it - invalid codepoints are instant undefined behavior, etc. Rust just usesi8(oru8depending on platform, frustratingly) as its synonym for Cchar.You can cast it to an int, and you can convert ints to rust
char(though the latter either involves a runtime check or unsafe), but I don’t think that makes it any more a numeric type than a pointer (actually… can I use pointer arithmetic? Rust pointers are allowed to take on any value and do have arithmetic methods…).The simple way is just a direct scan over every possibility.
I suppose the faster way once you’re doing more than a constant number of queries would be
re:
char: Yeah, i’ve got that, i’ve read the docs before answering. Imho it’s still a numeric type with a well-defined integer semantic, but it’s a non-arithmetic type.re: generator: what would
iter_input_outputdo? because if the input is invalid, the generator would generste infinitly long strings.or well. we can also encode “recursion depth” in string length, appending a character each recursion length until we reach a predefined string. we can’t slice off characters as this would need an index of sorts, so we have to append and compare.
Rust makes it really easy to truncate iterators, thankfully
I was also just going to hardcode the length of the iterator, not because I need to but because a better way to generate numbers hasn’t promptly occurred to me. There are nested function solutions that would be ugly… but… nothing elegant.
Here, I typed the rest of an untested solution (it probably has typos).
I even avoided char in case the interviewers agree with you. Of course this is still a terrible solution because it doesn’t directly compute the function at hand, I doubt I’m getting hired (or want to get hired) either.
PS. An elegant-ish version of infinite numbers using an unstable (and 2024-edition only) feature
Sort of amusing that this also works in any base.
Thank you for taking your time to explain!
I really like the solution, it’s incredibly cursed, but also highly readable.
“I have bad news for you about how CPUs work.”
(Even the mov hack uses implicit numeric ops!)
I mean, if your language of choice would be a CPU-native assembly, that’s probably true.
But most languages use an abstract machine to define their semantics, and they often can natively handle strings
It seems fairly clear given the requirement that “The input array must contain a string representations of the numbers.”. Without numeric operations, you can’t really take advantage of the underlying numeric nature of characters. I’d have been tempted to declare the input as being in base 15 which would make the problem easier.
[Comment removed by author]
How does this actually output? The result is a type, and i didn’t think it was possible to materialize typescript type information at runtime.
Also, what is this witchcraft with format strings in type annotations, I’ve written a lot of typescript and never seen that
Is that the point? I have only ever known FizzBuzz as a test to see if someone could program AT ALL.
That is part of why I shared this.
I thought it was an interesting test, and one that might spread and get taken up: it’s not just testing your ability to program with a simple, well-known exercise, but it’s testing your ability to keep adapting to ever-changing goals and restrictions, which like it or not is undeniably very much a real-world skill.
i wouldn’t hire them either.
Mind sharing why? Any specific mistakes or problems in OP’s story that others can learn from?
I don’t believe OP’s story is completely honest, that under pressure he figured to change the base so that the trailing digit was always a multiple of a divisor of the base. Just seems random to come up with that.
I’d say that was a fairly obvious move to me, from stuff I learned in first year undergrad. Definitely stuff you could figure out on the back of an envelope if you’re already in the headspace of thinking about digits and representation of integers.
The status of numeric bases in undergraduate (and even secondary education) also seems to vary wildly by country, when you went to school, and how many leetcode-style challenges you’ve done.
I don’t remember the specifics, and I certainly can’t claim I would’ve thought about that, but I remember being shown a variant of that in 5th or 6th grade or whenever the hell they taught me numeric bases. It was something about how each numeric base has its own divisibility rules, and that they all have their own variant of “if it ends with a 5 or a 0”. When I went to school, numeric bases were definitely important enough that I remember reaching out for various “useful” properties related to them up to my last year of high school (after which I was thankfully spared the plight of exam-driven mathematics…).
Also, this seems to be surprisingly popular in some interviewing niches. Over the years I’ve ran into several interns or fresh graduate juniors who’d memorized very weird divisibility rules that are definitely not covered in school, like divisibility by 19 or that subtract-last-digit-from-twice-the-rest rule for divisibility by 12. When I asked about it (number theory is one of those things that’s always fascinated me but I never had time for so I try to live vicariously through whoever seems to have an interest in it) they all told me they have zero interest in number theory in general but these things sometimes come up in coding challenges and knowing them is useful.
… how is that easier than just testing divisibility by 3 and 4
Probably something to do with symbolic testing of very large integers
Not really. I think.
The trick behind divisibility by a number n, is to check for
10^i % n, and see if you see a pattern. 2 and 5 have the easiest pattern: powers of 10 modulo 2 or 5 always equal zero, except for 10^0 (that is, 1). Which means you only have to look at the last digit to know if you have a multiple of 2 or 5.3 and 9 have the next easiest rule. Turns out that for all
i,10^i % 3 = 1. Same for 9. In practice this means that10*n % 3 = n % 3(same for 9), and you can recursively divide by 10 the higher digits until you only get a sum of “unit” digits. And of course, the rule works recursively, so just rinse and repeat until you get a single digit, and voilà you know if it’s a multiple of 3 or 9.4 I don’t know at the top of my head, but it’s easy to find:
So only the last 2 digits contribute. So for a number
xxxxab, you just sum2*a + b, and see if that is a multiple of 4. Another way of seeing it is, ifais even thenbmust be 0, 4, or 8. If it’s odd,bmust be 2 or 6.Since 12 = 3*4, and 3 and 4 are coprimes, to test if something is a multiple of 12 you just test if it’s a multiple of 3 and a multiple of 4. Very easy.
Now let’s try 12…
Okay, so the rule is a little unhinged: all digits count 4 times, except the first (it counts normally), and the penultimate one (it counts minus double — easier than counting 10 times). So… I would:
No fucking way that’s easier than just checking for 3 and 4, no matter how many digits… unless perhaps we start exploring more advanced strategies.
For big numbers one does not simply do sums. Okay then, let’s shave some numbers. For 3 you can:
I believe this is as simple as it gets. O(nb_digits) time, O(1) space, I think 12’s strategy can’t get any simpler — I suspect it is nearly identical except at the end, but not simpler.
Hey! I accidentally found an algorithm to solve this stupid Fizzbuzz without having to change the base, and without the sum lookup matrix!
Edit: pinging @x64k and @hwayne
I think what you did is observe that you can make the sum table much smaller by only representing it mod 3.
Err… yes, you’re correct, that’s the true insight. Now since the table is banned, I’m still gonna use a switch statement to obfuscate it into code, so they can’t say I “hardcoded” it — even though the switch statement would be even more hard coded than the table…
I have absolutely no idea. I obviously have no idea how or why that would ever come up in a coding challenge but I really don’t know how that’s a useful rule in general, either. The best hypothesis I could come up with was that maybe, since lots of units are duodecimal (12 months in a year, 12 pence in a shilling, 12 inches in a foot etc.) knowing the multiples of 12 by heart up to 120 was pretty common at some point. In that case, this is a convenient way to check for divisibility by 12 for numbers up to 600 or so without actually doing any division or multiplication – if you can add numbers, you can double them, too.
But I’m really not convinced. Anyone who knows the multiples of 12 up to 120 and can add numbers can presumably check for divisibility by 3 for numbers up to 600 or so, and you don’t need to do any arithmetic to check for divisibility by 4, either.
If I had to guess, I’d say it’s just a common result that pops up in undergrad number theory courses or something. There are similar criteria for 7, 11, 13, and probably others I don’t remember right now.
Doesn’t that explain it?
I’ve worked with people like that and I wouldn’t hire them either.
They might be great at working on their own but will have difficulty fitting into a team. They can’t resist the temptation to show off when what you really need is code that the whole team can maintain. Also trying to keep them on track is a nightmare, you may have a pressing business need that gets ignored whilst they go off in their own direction.
Erm, it’s worth remembering that they actually started with the canonical FizzBuzz implementation. They ended up with that weird type thing after the interviewers introduced additional “rules”, chief among them being that they couldn’t use numeric types, number literals, or associated methods and operators, and it all had to fit in no more than 30 lines without any minifying tricks.
They didn’t do that to show off, the interviewers literally asked for a solution like that.
A type-based implementation is actually not a bad idea at all – it’s clean, a core language feature, and easy to adapt if the “no more than 30 lines rule” turns into “no more than 20 lines actually”. The numeral base quirk was added because the interviewer objected to the sum table as “partially hardcoding the solution” (!?).
Hopefully their internal codebases doesn’t actually store numbers as strings and operates on them without any numerical operators. Why they’d ask for that kind of stuff in an interview is anyone’s guess.