Subverting the software interview (2021)
nliu.net
nliu.net
> “In Lisp,” you offer. “We often write domain-specific languages to solve new problems.”
> “C is not a DSL!”
> “If you insist.” Keep going anyway.
> The Church. The lambda calculus. The gay agenda. It has known a thousand names, a thousand forms.
def inf_range(a):
while True:
yield a
a += 1
def take(n, it):
return [a for a, b in zip(it, range(n))]
def fizzbuzz():
return (a + b or str(c) for a, b, c in zip(
(a for _ in inf_range(1) for a in (("", "", "Fizz"))),
(a for _ in inf_range(1) for a in (("", "", "", "", "Buzz"))),
inf_range(1)))
print(take(30, fizzbuzz()))
For bonus points: which alphanumeric characters can be changed in the code above? def fizz_str(n):
return "FIZZ"
def buzz_str(n):
return "BUZZ"
def fizz_buzz_str(n):
return "FIZZBUZZ"
def to_str(n):
return str(n)
indexes = [3, 0, 0, 1, 0, 2, 1, 0, 0, 1, 2, 0, 1, 0, 0]
def fizz_buzz(n):
funcs = [
to_str,
fizz_str,
buzz_str,
fizz_buzz_str
]
return funcs[indexes[n % 15]](n)
for i in range(1, 101):
print(fizz_buzz(i)) fb = lambda n : n == 0 or not fb(n-1) or not print(['{}',"fizz","buzz","fizzbuzz"][((n%3)==0)|(((n%5)==0)*2)].format(n))
fb(100)I never noticed this symmetry in fizzbuzz before.
Is this style in homage to the linked-to page? I can't figure out why you're not using itertools nor re-using itertools names. Is it that translating from .. is that Haskell? .. to Python without idiomatic translation the subversion?
from itertools import islice, cycle
def fizzbuzz():
return (a + b or str(c) for c, (a, b) in enumerate(zip(
cycle(("", "", "Fizz")),
cycle(("", "", "", "", "Buzz")),
), start = 1))
>>> print(*islice(fizzbuzz(), 0, 30))
1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz
16 17 Fizz 19 Buzz Fizz 22 23 Fizz Buzz 26 Fizz 28 29 FizzBuzzOverengineering is an actual problem. For a tiny example, I'll see things like:
enum MAGIC = 67; // explanation
...
foo(MAGIC);
The use of MAGIC is the only one, and is far removed. A better solution is: foo(67); // explanation
because it improves locality.I also see things like an object fleshed out with all kinds of member functions that are never used.
If `MAGIC` was sufficient to understand what the significance of the number was and `// explanation` was the citation or derivation, then I'd be fine with this, especially if there were a bunch of other constants with explanations with similar derivations or citations (eg a bunch of trig or constants from the same standard); then it'd be preserving a different sort of locality.
If `MAGIC` wasn't sufficient to capture the purpose of the constant & such a name wasn't readily available, so that you're always going to want to read `// explanation` (rather than only in the case you think the value is wrong), then I'd agree with you.
Concrete(ish) examples: if 67 terminated the Foo section of the Bar binary file format, even if we only used it once, I'd prefer to see END_OF_FOO rather than read a comment. Reading comments is context switching, at least for me. Names help me stay in the headspace of the programming language.
If 67 was the result of an ad-hoc calculation which only made sense in the context of this particular program (how many angels can dance on the head of an Acme brand pin executing our trademarked choreography) while, and so there wasn't a great name for that calculation, or at least not a name that would make sense unless you've already read the derivation, then I'd agree in that case.
That being said, I have absolutely seen overengineering or misengineering cause real problems.
Resubmission came back with:
#define SEVENTEEN 17
Last I spoke with him, he was a Java instructor.E: in other words, those who code to live vs live to code.
#define SEVENTEEN 16
#define MAGIC_16 16
his rationale was that you had to go through all the uses and consider whether the change would cause an issue.It takes all kinds.
The best approach if you want to be future-proof while would be to label the instance in-place, so that you can look later for places where #MAGIC is being used, without losing locality:
foo(67); // #MAGIC explanation list, mist
func, gunc
church, dhurch
This is clearly the One True Naming Scheme and now that I have seen it I can't imagine ever using anything else.Here's a better enterprise version: https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpris...
Though the fact that it was written some years ago might be a weakness. Some interviewers might prefere a more modern, distributed solution.
FizzService, BuzzService, FizzBuzzService, CountingService, etc
newtype Dual a = Dual {getDual :: a}
instance Semigroup s => Dual s where
(Dual a <> Dual b) = Dual (b <> a)
instance Monoid m => Dual m where
mempty = Dual (mempty)
These are declaring instances of Dual, but they are providing method definitions for Semigroup and Monoid as if they were declaring instances for those types. I plugged this into ghc and I couldn't get this to compile either way. This isn't using an extension or some more obscure language than haskell is it? newtype Dual a = Dual {getDual :: a}
instance Semigroup s => Semigroup (Dual s) where
(Dual a) <> (Dual b) = Dual (b <> a)
instance Monoid m => Monoid (Dual m) where
mempty = Dual (mempty)The premise that modulo (%) is "slow" here doesn't quite justify the jump into Haskell, but it's still hilarious.
I feel like we all could know someone who fits these characteristics.
He called it "fun.hpp".
"Fun" times, indeed, working with him.
#include <ranges>
#include <numeric>
#include <vector>
#include <iostream>
int main() {
std::vector<int> vec = {1, 2, 3};
// map, using `std::views::transform`. Implemented in C++20
for(int elem :
std::views::transform(vec, [](int x) { return x + 1; })) {
std::cout << elem << " "; // 2 3 4
}
std::cout << "\n";
// `std::ranges::fold_left` will be available with C++23.
// Until then, we're stuck using the <numeric> iterator version, which was
// implemented in C++20.
std::cout << std::accumulate(vec.begin(), vec.end(), 1,
[](int x, int y) { return x * y; })
<< "\n"; // 6
return 0;
}
Building and running with the following: $ g++ --std=c++20 test.cpp
$ ./a.out
2 3 4
6 #include <algorithm>
#include <functional>
#include <iostream>
#include <numeric>
#include <ranges>
#include <vector>
int main()
{
std::vector<int> vec{1, 2, 3, 4, 5};
auto plus_one{[](const auto x) { return x + 1; }};
std::ranges::for_each(vec | std::views::transform(plus_one), [](const auto x) {
std::cout << x << " ";
});
std::cout << "\n";
std::cout << std::accumulate(std::begin(vec), std::end(vec), 1, std::multiplies<>()) << "\n";
return 0;
}
https://godbolt.org/z/84ePjfPhf"Know" or "be"?
:-P
(defn any-buzz
[num & words]
(or (not-empty (reduce str words))
num))
(map any-buzz
(range 1 16)
(cycle [nil nil "Fizz"])
(cycle [nil nil nil nil "Buzz"]))
Source: from a bunch of fizzbuzz code riffs I wrote to illustrate real-world programming and problem solving with Clojure:https://www.evalapply.org/posts/n-ways-to-fizzbuzz-in-clojur...
edit: formatting, detail
https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpris...
use feature say;
say <{Fizz,}> . <{Buzz,,,}> || $_ for 0..100;In the end the only "subversion" is that it was written as zipped infinite ranges rather than an explicit for-loop.
ruby -e 'puts (0..99).map {|i| srand(46308667) if (i%15).zero?; ["FizzBuzz", "Buzz", i+1, "Fizz"][rand(4)]}'It also has the side effect of making me feel better for never attempting to write my own encryption algorithms! :D
"We work hard, we play hard" in case anyone missed it :-)
As an aside, there's a lot of rightful complaining about the interview process. I've been on both sides and it sucks either way.
As a hiring manager for a small company, we never had the 'process' that bigger companies have, so it was always a seat of the pants decision. Not my favourite thing to do.
As an interviewee, I've struggled with people's favourite questions, you know the ones that you ask so much that it starts sounding like an easy question in your head?... I'm productive, I ship software but interviewing is so incredibly stressful and always makes me feel like I don't know much.
Anyhow, if I was interviewing the OP for a typical web app CRUD position or monolith to micro services refactor or some other common role, I'd think twice. Clearly he's very smart. Is he able to "deliver value" vs optimizing code? I know the post was tongue in cheek, but in the real interview setting you gotta demonstrate how you're a smart team player and allude to your capabilities. It's kinda like dating I guess. You can't show how much of a real person you're on the first date.
> by Naomi Liu
Take a day off.
This man has won the People's Honour Award for climbing the highest mountains on 5 continents and being the first man to reach the north pole solo.
So Naomi is not necessarily a dead giveaway, you guys really split hairs and raise hackles over just about nothing worthwhile. Mistaking someone's sex is not a massive deal.
I used to have on my team a guy named Joan (pronounced joe-an) who spoke really softly, so his potential new employers would call me for a reference asking about "she" and "Joan", I'd gently correct them so as not to embarass him on any phone interview in the future. Nobody needed to throw a fit over an honest mistake.
Coincidentally, that guy was the best programmer I ever employed.
Anyway, just one of many counterexamples to a non-issue.
And this is on top of calling someone else out for presuming something... and here you all are presuming that Naomi is a feminine name.
We're making a mountain out of a molehill here. This is a persistent and pernicious problem in society at large now. What is the actual point of calling out any POSSIBLE perceived remote slight that you really have to perform mental gymnastics in bad faith to even arrive at?
There was no malicious intent on the part of the original poster, and yet they are excoriated for nothing?
What a massive amount of spare time we all have to waste.
Especially when it is a unisex name.
We could be doing something to better our world, and we spend time _on this_. We do it every day on a massive scale. It's so tiring, so wasteful, and so lamentably useless when there are so many useful and actually kind things we could be doing, instead of just virtue-signalling fake empathy on the internet that amounts to nothing.
Mis-stating gender might be careless when as you imply “their” is the always the safe bet, but it’s probably not enough to justify OP’s unduly critical response. He / she or they could have just replied with “I checked their LinkedIn and Naomi’s a girl, btw”.