DEV Community

hahaha! I'm sorry to hear that. I've always described myself as an engineer, nothing more, nothing less. Machines: easy. People: Too hard...Not doing it. I look forward to what people have to say too. I'm self-taught for the most part in that I've never spent a day on a University Campus as a student. And I live in Portland, ME now which is very much a .NET and Node area of the country. So up until about 6-weeks ago, I've lived in my little corner or Portland in total obscurity. But now, Boston has gotten too expensive for a lot of startups and they've moved to Portland. As such, suddenly being a Mid-Senior level Python Engineer is hugely in demand in my area and I'm one of a dozen developers locally with that skillset. So, almost overnight, I've gone from "We don't do Python here" obscurity to "Holy crap, there's a dev that does Python here? And he's a freelancer so, therefore, available!?!?! Could you come in and chat with us for a minute?" πππ

Good luck kaelscion!
I would have chosen the version with a generator wrote by @rrampage with memoization.
Yours is definitely good!
Anyhow, no recursion, 200k is definitely past the default recursion limit:
>>> import sys
>>> sys.getrecursionlimit()
1000
Python doesn't optimize tail recursions so you're kind of into the unknown with a numeric algorithm like that
Let us know how did it go! :D

As it turns out, the solution proposed by @rrampage included a list comprehension that demonstrated a potential use case of the generator (they responded to let me know). Admittedly, I simply copy/pasted that solution and ran the tests on it without actually reading it π .
The second solution I proposed didn't have that list comp in it neither did their revised solution. There was a slight performance hit in x-time, but the RAM usage was much better without the generator being appended to a list. So for raw performance, I still favor the iterative solution. But for a well-balanced approach that is lighter on RAM but trivially different in x-time, I agree the generator is best.
As far as the interview went, I feel it was good. It was a 3-hour interview process. I met with 8 people from different teams who all questioned me on the topics they found most important. There was a discussion on brands, Big-O quizzing and data structure questions, product and culture-fit questions, comfort level with Agile, and finally, the fourth team of 2 gave me a whiteboard challenge.
Here is where, I feel, I struggled mightily for two reasons: 1) I was totally fried from the previous 3 teams and their questioning and 2) This was my first official engineering interview in at least 5 years. I also did not have a whiteboard available in that conference room so I was figuring out my solution in my notebook. This meant that I kept running out of room on a page, and would flip to the next page and re-write what was on the first page so that the interviewers could see what I was doing. I also overengineered the algorithm. Big time. In the end, I "couldn't see the forest through the trees" and ended up with a quasi-solution that I didn't particularly care for. Both interviewers chuckled along with me though and told me that they had done the same exact thing I did the week before when they had first seen that problem in preparation for my interview.
Ultimately, I think my thought process was good and I did talk them through my thoughts the whole time. But writing code from memory on a piece of notebook paper in the span of 30-minutes or so is never easy so I think I'll be forgiven. The thought process is what most interviewers really look for (I hope).
Either way, I had a blast, loved the people and the interviewers, and am really hoping things work out. If nothing else, it was a bit of a confidence boost because the majority of my programming experience is in the freelance space and I have no degree, just curiosity. So to be able to go in there and stand toe-to-toe with career software engineers and make any sort of impression is great.

So for raw performance, I still favor the iterative solution. But for a well-balanced approach that is lighter on RAM but trivially different in x-time, I agree the generator is best.
Yeah, that's usually it. The advantage with the generator is that you can pause it and resume it. They are basically a simplified version of continuation passing style.
Both interviewers chuckled along with me though and told me that they had done the same exact thing I did the week before when they had first seen that problem in preparation for my interview.
That's cool. If they saw that, it means they empathize and recognized that you were working towards a solution
Either way, I had a blast, loved the people and the interviewers, and am really hoping things work out.
Well, that's really important. Sometimes we go into interviews hoping the company will like us but forgetting that we have to like them as well :D
Crossing fingers, especially now that your skills are in demand!
All the best for the interview!
Another interesting approach using iteration is making the function into a generator which can be used as part of for loops, list comprehensions, etc
I am generally wary of writing code using pure recursion in Python as it can easily blow the stack due to recursion limit. For example if we try to solve using recursion as:
This takes exponential time because it recalculates
fib(n-2)
forfib(n-1)
.If we try to make it linear time using
functools.lru_cache
which will cache the previous calls at cost of O(n) memory, this still givesmaximum recursion depth exceeded in comparison
error for fib(200000).if Tail call optimization was supported in Python, the following recursive variant will be "optimized" to iterative version:
But due to no TCO, it still results in same
maximum recursion depth exceeded in comparison
forfib_tail(200000)