The process started with a standard recruiter screening call, to narrow down the specific position I'd be a fit for.
I was then sent a “Python Coding Challenge” to complete in 90 minutes, within 2 days of receiving it.
The challenge was a link to a website which doesn’t even run your code, which is extremely annoying. Also, the questions were convoluted and frankly too difficult for a new grad position. I had to reread each question and the examples several times because they were so confusing.
A few days afterwards, I was told my “solutions were not performant enough to move forward”.
Honestly, this process felt disrespectful of my time, even if I had moved forward.
Log Processor
Outline:
You are developing a log processing system composed of distinct "steps" that process logs in various ways. Each step is declared in advance, and the system is built by feeding the output of one step into the inputs of others. Each step has a Python function (stored in the "action" attribute) that is evaluated to produce its output. The user interacts with the system by requesting the output of a particular step. The system will then call the action for that step (and any other actions it depends on) to return the processed log.
Each step is given an "output_name" attribute, which the user can use to retrieve the step's output. The "input_names" attribute stores a list of strings that match the "output_name" of other steps, enabling the output value from one step to be used as an input parameter for others.
Read further to see examples of the system in action, and begin with Questions 1-4.
QUESTION 1:
In example_system_1, the step for "output3" takes inputs from the steps for "output1" and "output2".
Thus, if the user requests "output3", we must first evaluate the actions for "output2" and "output1" to get their respective output values, so they can be used as inputs to the action of "output3".
To determine the correct ordering of step dependencies, complete the action_evaluation_order() function below. It should return a list of "output_name"s for the order_for_output_name parameter. Each "output_name" in the list should appear after any of its dependencies. The ordering should not contain any duplicates.
You may assume every list of StepDeclarations is valid and solvable, for example:
StepDeclaration will have only one output.StepDeclaration can have any number of dependencies (including zero).StepDeclarations will not contain duplicate "output_name"s.StepDeclaration cannot depend on its own output (directly or indirectly).For this and the following questions, assume the system operates at a large scale where efficiency is important. Correct, albeit slow, solutions will receive more marks than incorrect fast ones. You may also leave notes explaining where you would further optimize if you had the time.
QUESTION 2:
Now that we know the order in which actions must be evaluated, complete the get_output_value() function below. It should call each "action" in the correct order with the right input(s) and return the output value of the "action" function for the StepDeclaration where the output_name attribute matches the output_name parameter.
You can use your previous work if desired.
For example_system_1, the get_output_value(example_system_1, "output3") function will perform the following:
action_get_logs1() and store its output.action_get_logs2() and store its output.action_combine_logs() with the outputs from steps 1) and 2) as inputs.StepDeclaration.output_name matches the value_for_output_name parameter.(Note: As in Q1, steps 1) and 2) could happen in reverse order.)
QUESTION 3:
We expect get_output_value() to be called multiple times with varying step_declarations and value_for_output_names.
As some "actions" might be expensive to call, we should cache the output of "action" calls.
This way, if an "action" is called multiple times with the same input values, the output value can be reused without recomputing.
An "action" function may be reused in many StepDeclarations within one system or across different systems sharing a cache.
Implement get_output_value_with_caching() below, utilizing the global cache variable.
"actions" are pure functions, meaning the output value of each function depends only on its input values. In a real system, some inputs access external data (e.g., reading logs from a filesystem) rather than just fixed strings as in the examples. We can simulate this by having one of the steps that takes no inputs return a variable result.
QUESTION 4:
Another performance upgrade would be to introduce concurrency/parallelism where possible to improve system performance.
For instance, in example_system_1, a single-threaded system waits for the result of action_get_logs1() before calling action_get_logs2() (or vice versa).
However, these functions are independent and could be executed in parallel, speeding up the system.
Complete the get_output_value_with_caching_and_parallelism() function below, using concurrency/parallelism wherever possible to enhance system performance.
Your choice of parallelization primitive or library does not affect your score (e.g., you may use multithreading, multiprocessing, asyncio, etc.).
You can assume there is no performance overhead for additional workers (e.g., you have unlimited CPUs), and that all action functions are I/O-bound.
Extra for experts: Limit the number of CPU cores available to N, and assume each action can utilize a fixed number of CPUs from 1 to N. Then, schedule parallel actions to optimally utilize CPU cores without oversaturation.
The following metrics were computed from 130 interview experiences for the Tesla Software Engineer role in United States.
Tesla's interview process for their Software Engineer roles in the United States is extremely selective, failing the vast majority of engineers.
Candidates reported having good feelings for Tesla's Software Engineer interview process in United States.