What can I learn about the candidate for the test task

    Some time ago, a wave of articles on finding a job and passing interviews swept through Habr. Both employers and job seekers have spoken out many times. But, unfortunately, the topic of test items was not sufficiently addressed.

    After all, the test task is not limited to the categories of "completed" and "not completed." By carefully observing the process and studying the final result, you can end up saying a lot about a person without working for a day with him. And sometimes, and learn something new.

    I bring to your attention a test task that I have been giving candidates for a long time in the company where I work:

    On the screen there is a grid M by N of colored squares. It is necessary to realize the following effect on this grid - by clicking from left to right with a speed V, a wave runs through, changing the color of the squares to another (common for the whole wave). The effect should work for any values ​​of M, N, V. The wave always starts at the left wall. Several waves of different colors can go at the same time.
    Animation example: http://dl.dropbox.com/u/3601116/wave.swf (click on flash drive).

    I have no doubt that this task will be easily done by all programmers visiting Habr.

    And I got the following statistics:

    1. As a result, a little more than 20 people took the task.
    2. A couple of people did nothing.
    3. Half of the remaining (according to my criteria) could not cope with it.
    4. Candidates clearly divided into very interesting groups.

    Think a little about how you would complete this task, and go under the cat, where I will tell you more about everything.


    In this article, I do not touch on the ethics, complexity and necessity of test tasks as such - I understand that everyone here has their own opinion on this topic. I will be glad to hear it in the comments as an addition to the material, but I do not welcome the kindling of any holivor.

    The task

    A few words about the assignment. I didn’t care what the person was implementing it on, but two conditions were immediately discussed:

    • I can run it
    • I can understand the code if they wake me up at 7 a.m.


    As I said, the candidates were divided into distinct (intersecting) groups, which will be discussed below.

    Getting a person into a certain group by itself can already tell a lot about him, both from the good and from the bad side. And this absolutely does not mean in any way that a person is immediately put up with a cross. Being in a group only sets the topics for further communication in order to find out whether the candidate is suitable for me and whether we are suitable for him.

    Schaz all will be! I'll do it tomorrow!

    Of course, several people zealously rushed into the battle ... but they didn’t do anything. For those that disappeared right away, I immediately scored, but a couple of people stubbornly fed breakfasts, and then eventually merged somewhere.

    Conclusion: I will know with whom it is not worth working either in the office or on freelance. It was quite possible to write a letter and refuse further communication so as not to waste either my time or the time of the candidate. As practice shows, the market is actually small.

    It's simple, you need to do like this and like this

    To my surprise, I came across people who for a long time (and voluminously) explained to me how to do this task, how to build architecture, how to optimize rendering. Technical terms poured and knowledge of win32 api was displayed. In the end, I could not stand it and spoke bluntly, they say, excellent, now go and do this task.

    And you know what? .. They all had difficulties with him.

    Conclusion: in practice, theory and practice are very different. Often people create a thin shell of professionalism around them, which hides overt amateurism. It’s good to understand and use it in time.

    We were taught at the university C in the second year

    IMPERATIVE was written in huge yellow letters on the door of this group. As expected for solving the problem from the second year of the university, the matrix featured a matrix, a number of variables with the beginnings and ends of the waves, as well as variables i, j, k, m, n and others in huge quantities.

    The code could not be understood, and in most cases it worked with jambs and / or slowly.

    So, i is from zero to the point of wave propagation, j and k are symmetrical in both directions ... and this is a boundary condition ... so, and what kind of m now goes back to the border of the current color ... so, and what does it work for and why ?? ! argh! fuck it!

    The dialogue with the candidate was delayed by a dozen letters, in which each new one began with the words "corrected everything, now it works." I felt like a computer science teacher. Needless to say, no one has completed the project from the end of this group. So much for Russian education.

    Conclusion: Unfortunately, in the overheated IT market, most of the candidates have very mediocre knowledge and want a lot of money and BMW right away. The test task (even in fact completed) can say a lot about how a person is used to writing code and his approach to solving algorithmic problems.

    Add (new Wave ());

    Basically, the people, of course, immediately in the wording saw the division of the task into classes and elementary architecture - who controls whom. We create waves, and let them already do something there.

    At the same time, they also managed to show miracles of the OOP of the Brain. But, nevertheless, the majority coped with the task.

    Somewhere there were a couple of people who tried very hard not to get into the previous group, but anyway, they couldn’t stand in places and rudely encapsulated in the textbook OOP code.

    Conclusion: a good OOP code structured according to the canons is a sign of an experienced developer who can competently break down a task into modules and assemble an application from them. Attention should be paid to the signs of overengineering and violation of abstractions.

    The specificity of my work lies in the tight deadlines for which you can’t afford to go deep into the abstraction of architecture. And at the same time, you must adhere to the rules and not scatter yourself the same rake along the route.

    I write everything from scratch

    The assignment did not specifically set limits on the use of languages, frameworks, and libraries. But people from this group persistently chose a difficult solution path and wrote the infrastructure for themselves (for example, displaying a mesh screen in 3d space). As a result, everyone coped with the task.

    Conclusion: At first glance, the candidates had sufficient knowledge to implement a solution to the problem from scratch on their favorite instrument and not get confused in the algorithm. But immediately there was a suspicion of “Not Invented Here Mentality” and doubts that a person would be able to effectively use existing developments and third-party libraries.

    I am not looking for easy ways!

    Strongly overlapping with the previous one, this group includes all those who were already close with creating a framework for developing applications with traveling colored waves in a vacuum: waves moving in any directions, each in its own flow, rendering an unmanaged image with code from a managed application, and other monstrous decisions.

    Man tried to show that he can write multithreaded highly loaded systems? On such a test task? ..

    - Why did you do it like this? After all, it could be made much easier.
    - What for? I can do that!

    Conclusion: It’s worth considering. A person, most likely, is an expert in his field and has extensive knowledge, but can he solve specific problems quickly without creating a framework for solving such problems? Do you have a framework for which you can put it?

    I'm redrawing everything / I'm not redrawing everything

    Many immediately realized that in the algorithm of motion of the waves superimposed from each other from left to right, the rendering can be greatly optimized. But, sadly, many of them dug their own grave, entangled in their own code.

    But, there were a couple of interesting points. For example, three or four in one way or another, instead of adding a moving wave in terms of OOP, considered when and in what color the cell should be repainted. In fact, the “addition" of the wave only changed the existing temporary color switching program.

    Conclusion: On the one hand, I didn’t care at all about redrawing if the application worked correctly and quickly. On the other hand, people understood that everything can be done more optimally. But, did he first make a working non-optimal option, and only then began to optimize it? Often not. And this makes you think.

    I don’t care what it looks like if it compiles

    Several people sent completed tasks with frank graphic shoals. Even without reading the code, one could understand that something inside was wrong. It was impossible not to notice them, so the conclusion was obvious: a person does not care.

    Almost everyone at one rate or another agreed to solve the problems, but one friend surprised me. You see, he knows very well how to fix the jambs and the rendering speed, but he believes that he will not spend an hour of his time for a test task.

    Conclusion: It is very important that a person closes the task only at the moment when he is sure that the work is done. Passing an application with an obvious jamb for verification (in the hope that they will not notice it?), He spends not only his time, but also the time of the inspector. And the comrade who knows how to solve the problem, but will not solve it, because ... - will behave the same way at work.

    I don’t care how they run it

    Several times I had difficulty launching the application:

    • Some libraries were used that are not clear where to get quickly.
    • It was necessary to install IDE, SDK and everything in the world, just to compile the app.
    • I obviously didn’t have all the project files, and with an unfamiliar language I didn’t have much desire to tinker with configuring it.

    The code was clear, but there was no way to see the result. One of the candidates magically fell off at this stage ...

    Yes, I myself wrote at the beginning of the article that I don’t care what the code was written on, but still it’s worthwhile to value my time and attach, for example, a compiled file, a couple of lines of what and how to open it better ... send complete projects, not a set of source files , eventually. Unless of course, your task is not to write everything on Brainfuck and to mock me (as suggested here below). But, you must understand that I can not appreciate this move.

    Conclusion: Also some kind of unpleasant pofigisticheskoe attitude to the inspector. As a result, a lot more time was spent on additional correspondence.


    Each candidate had in one way or another a unique approach to solving the problem. Having studied it, you could immediately say a lot about a person as a developer:

    1. What is his experience and in what projects.
    2. How abstractly he thinks.
    3. Is he able to implement a simple algorithm.
    4. Can he clearly close the tasks himself.

    Being in a particular group does not in itself mean that a person is good or bad. I have some needs, you have others. I am looking for some qualities and I am alarmed at the sight of others, but you, for sure, have some of your own selection criteria.

    Some decisions made me lose faith in humanity, from others my eyes became square, others seemed to some extent interesting and unusual. You read the code, and as if you penetrate the head of its author - how he approached the problem, how he built the algorithm and what difficulties he came across. After each solution I sent, I began to look differently at the task as a whole.

    Of course, the most popular was the OOP approach with creating instances of the Wave class, updating it by timer and cleaning it when some criterion was reached. But, at the same time, people in different ways approached the propagation of the wave and redrawing the grid.

    I am glad that some of the source code allowed me to learn something myself!


    * Paragraph amended.

    History would be incomplete if I had not attached my canonically correct decision here.

    In fact, initially it was not. Only by the end of the second dozen “proven works” I began to think, but how would I solve this problem ... One feature of all the solutions was interesting - everyone ... absolutely everyone looked at the problem, following the letter to the letter to its description at the beginning of the post: grid, on it the wave runs ...

    If we abstract from the wave and to some extent from the grid, look at the problem on the other hand, we can see that this effect is nothing more than a cellular automaton on squares with some rules. But which ones?

    Indeed, let the cell take a positive integer from 0 to infinity. Each tick cell takes the maximum value of its four neighbors. It is not difficult to see that by setting the value of one of the left boundary cells to N + 1 (where N is the maximum value of the cells on the grid), we get exactly the desired wave propagation effect.

    for (var i:uint = 1; i < Width-1; i++) {
    	for (var j:uint = 1; j < Height-1; j++) {
    		buffer.setPixel(i, j, Math.max(bmp.getPixel(i, j), bmp.getPixel(i-1, j), bmp.getPixel(i, j-1), bmp.getPixel(i, j+1)));

    It would be possible to leave everything this way, but it is easier to have another array with random colors. As a result, all the code on the flash looks like this ( https://gist.github.com/valyard/6084814 ):

    View code
    var Size:uint = 10;
    var Width:uint = int(stage.stageWidth/Size);
    var Height:uint = int(stage.stageHeight/Size);
    var bmp:BitmapData = new BitmapData(Width, Height, false, 0x000000);
    var buffer:BitmapData = new BitmapData(Width, Height, false, 0x000000);
    var display:BitmapData = new BitmapData(Width*Size, Height*Size, false);
    var zeroPoint:Point = new Point(0, 0);  
    var colors:Array = [0xFFFFFF];
    addChild(new Bitmap(display));
    stage.addEventListener(MouseEvent.CLICK, clickHandler);
    stage.addEventListener(Event.ENTER_FRAME, frameHandler);
    function clickHandler(e:MouseEvent):void {
    	addWave((e.localY % display.height)/Size);
    function addWave(position:uint):void {
    	if (position == 0) position = 1
    	else if (position >= Height-1) position = Height-2;
    	bmp.setPixel(1, position, colors.length);
    	colors.push(0xFF000000 + int(Math.random()*0xFFFFFF));
    function frameHandler(e:Event):void {
    	for (var i:uint = 1; i < Width-1; i++) {
    		for (var j:uint = 1; j < Height-1; j++) {
    			buffer.setPixel(i, j, Math.max(bmp.getPixel(i, j), bmp.getPixel(i-1, j), bmp.getPixel(i, j-1), bmp.getPixel(i, j+1)));
    	bmp.copyPixels(buffer, buffer.rect, zeroPoint);
    	var rect:Rectangle = new Rectangle(0, 0, Size, Size);
    	for (i = 0; i < Width; i++) {
    		for (j = 0; j < Height; j++) {
    			rect.x = i*Size;
    			rect.y = j*Size;
    			display.fillRect(rect, colors[bmp.getPixel(i,j)]);

    As you can see, the code is minimal and very simple. But no one ever showed me anything like this.

    Update: Of course, as the comments pointed out right away, this is not the easiest solution. It is immediately clear that only the left line changes, and everything else moves to the right. Or, that you can already generate the entire pyramid on the left behind the visible area and move the picture to the right. Anyway, that you can move vector triangles.


    All names are invented, all coincidences are random. If you have ever completed the same test task, I don’t know anything about it, it wasn’t me who invented it, and in general, nothing happens ... there is nothing to see here ... we are divided, gentlemen!

    PS thanks for the spelling tips and typos.

    Also popular now: