Как стать автором
Обновить

Комментарии 34

Хотел бы заметить, что задание, хорошее или не очень, должно укладываться в разумные сроки — не более, скажем, дня. Все задания, что получал (несколько штук) могу назвать интересными. Кроме одного, настолько «продвинутого» по условиям, что по оценке времени бы заняло 3 дня (ну или 1.5, если повезёт). Его не делал. Примечательно, что сразу после отправки его ко мне — мне позвонили, предупредив, что «не на 5 минут» и что это у них политика такая — давать достаточно ёмкие и близкие к практике задания и что кто-то его уже сделал и работает у них.

(Что было — не так интересно — какое-то дерево построить в браузере, какие-то подсказки показать. От всего веяло конкретикой.)

Наверное, это был как раз тот случай, когда хотели часть работы сделать за счёт заданий.
Как вариант — возьмите задачи с ACM, но обязательно переработайте.

ACM задачи очень жестоки к знаниям математических методов оптимизации, но если убрать из них часть с жестокой оптимизацией, сведя лишь к выбору оптимального алгоритма (но не оптимизации его, вычислении пределов и прочего) — они будут вполне сносны для собеседований.

И обязательно перевести на язык рекрута, заодно дополнив условие и убрав лирику (если надо).

Все же собеседование — это не олимпиада по спортивному программированию, и вам надо лишь узнать может ли кандидат думать как программист, а не может ли кандидат в особо сжатые сроки предложить самое лучшее, математически обоснованное решение особо не тривиальной задачи.
мое решение на javascript
str = "{Пожалуйста|Просто} сделайте так, чтобы это {удивительное|крутое|простое} тестовое предложение {изменялось {быстро|мгновенно} случайным образом|менялось каждый раз}.";

function change(str){
    str = str.replace(/\{([^{]+?)\}/g, function(full, match){
        var bits = match.split('|');
        return bits[Math.floor(Math.random(1)*bits.length)];
    });
    return str.indexOf('|') != -1 ? change(str) : str;
}

change(str);
php соответственно
function lol($rst){
	while( preg_match('#\{([^{}]*)\}#',$rst) ){
		$rst = preg_replace_callback('#\{([^{}]*)\}#iUs','rst',$rst);
	}
	return $rst;
}
function rst($r){
	$r = explode('|',$r[1]);
	return $r[rand(0,sizeof($r)-1)];
}

echo lol("{Пожалуйста|Просто} сделайте так, чтобы это {удивительное|крутое|
простое} тестовое предложение {изменялось {быстро|мгновенно} случайным 
образом|менялось каждый раз}.");

Вот только не пойму в чём нетривиальность, «блог сделать» куда сложней, если конечно у нас совпадает понимание этой фразы.
«блог сделать» можно по одному из туториалов, которых полно в интернете. Проекты компании немног другие, именно нетривиальные. Так что мы НЕ ищем людей для создания сайтов-блогов.
Можете привести примеры таких проектов?
например, дан список доменных имен, нужно определить их ценность с точки зрения покупки\перепродажи. Учитываются различные факторы, такие как выпадение из истории (weyback records), alexa rank, Google PR и пр. Эти данные нужно собирать из различных источников, учитывая ограничения и нюансы API, либо парсить страницы напрямую.
Видимо, тут основная сложность выставить конкретную цену?
с технической точки зрения что сложного в получении, например, Google PR.
Если разбить эту задачу на мелкие задачи типа «ежу понятно как» то да, сложности нет. Так ведь это и есть работа хрошего программиста. Это просто пример проекта. И сложный момент здесь может быть формула, кототрая должна показывать рейтинг даже если, например, один из источников данных для конкретного домена не доступен. Например alexa не даёт результатов для mymegaporn.kz, а домен на самом деле ценный, и это нужно увидеть. Я не смогу раскрыть здесь все детали проекта.
Похоже, людей которых вы ищете, более правильно было бы назвать аналитиками, а не программистами.
Поскольку именно работа аналитика заключается в «выводе формул» и разбиении задачи на элементарные части.
Аналитиков придумали программисты, которые не хотели вникать в задачу :)
Согласен с Petrelevich, формулой занимаются аналитики (не без помощи людей, обладающих необходимыми знаниями и опытом).
А чтобы не привлекать аналитиков придумали СППР, которые позволяют автоматизировать процесс выработки решения на основе знаний и опыта. И создание нужной СППР уже задача программиста.
P.S. еще на википедии можно про СППР почитать, но там совсем плохое описание.
Вот тоже самое, что первое пришло в голову:

$str =~ s!{([^{}]+)}!my @a=split(/\|/, $1); $a[int(rand(scalar(@a)))]!ge
while ($str =~ /[{}|]/);

Хотя уверен, что его можно доработать. И тоже что-то не пойму в чём сложность то.
Видимо приходит такой контингент, которого вгоняет в ступор такого рода задачи. :) Пришли попрограммировать в ворде а тут…
Интересно, были ли случаи, когда для решения данной задачи кандидаты пытались использовать через какие-нибудь грамматики/трансляторы?
Мне пришлось однажды участвовать в наборе программистов в новую команду. Поделюсь опытом, может вам будет интересно.

Тогда мы решили воспользоваться такой структурой

1. логика

Примеры точно не могу вспомнить, но задачи были похожи на загадки с черными и белыми шариками, обезьянками и клетками и т.д. Что-то похожее недавно промелькнуло на Хабре про вопросы к претендентам в компанию Гугл. Там еще был вопрос — почему люки на улице круглые. У нас было что-то похожее, но проще.

2. алгоритмика

Здесь идут задачки, похожие на вашу. Я вспомнил свой пример — нужно было за 15 минут написать карточную игру «Дурак» для игры между человеком и компьютером.

Успешное прохождение такого теста подразумевало умение концентрироваться на главном, умение строить очень простые модели и реально оценивать время, ну и конечно, алгоритмику. В итоге, например, один из программистов написал на Руби программку с консольным UI. Она умела тасовать колоду, раздавать карты и простое кейс-меню для хода.

3. профессионализм

Здесь проводилось классическое интервью типа вопросы-ответы по языку программирования, фреймворкам, паттернам, тонким делам типа рефлексии и тридов

нужно было за 15 минут написать карточную игру «Дурак» для игры между человеком и компьютером.


В итоге, например, один из программистов написал на Руби программку с консольным UI. Она умела тасовать колоду, раздавать карты и простое кейс-меню для хода.


Шустро! :)
Какими знаниями должен обладать хороший программист по-Вашему?
Кроме знаний, по-моему, хороший программист должен обладать абстрактым мышлением и не думать ограничениями. Знания можно получить, а вот способность «мыслить кодом» это что-то сокральное.
Скажу вам честно, это придумали программисты, чтоб поднять себе зарплату.
Да и не кодом они мыслят, а логикой )
Имхо, хороший программист должен думать уже не на уровне кода, а на уровне проекта в целом. Он должен понимать что он делает, как, почему и зачем, каковы реальные цели заказчика и т.п. Хотя, возможно, у меня слишком завышенные требования.
Согласен полностью. Программист — это не леший в заколдованном лесу :) Это проводник, который знает как пройти через лес и выйти с карзиной грибов. :)))
простите,, у вас такие странные опечатки в посте и комментариях… «карзиной», «одбора»…
просто любопытно — это ошибки или опечатки от быстрого набора? (:
Ашипки. Я, знателе ли, решил много времени на абразавание не тратить :)
на Perl короче всех:

$s = '{Пожалуйста|Просто} сделайте так, чтобы это {удивительное|крутое|простое} тестовое предложение {изменялось {быстро|мгновенно} случайным образом|менялось каждый раз}.';
1 while $s =~ s/{([^{}]+)}/@arr = split '\|',$1; $arr[rand scalar @arr]/eg;
print "Result: $s\n";
ну и на питоне для коллекции (:

import re, random

def repl(m):
  while True:
    m, n = re.subn(r"{([^{}]*)}", lambda x: random.choice(x.group(1).split("|")), m)
    if (n == 0): break
  return m

print repl(u"{Пожалуйста|Просто} сделайте так, чтобы это {удивительное|крутое|простое} тестовое предложение {изменялось {быстро|мгновенно} случайным образом|менялось каждый раз}.")
# -*- coding: utf-8 -*-
import re
from random import choice

print re.sub(r'\{(.+?)\}', lambda x: choice(x.group(1).split('|')), '{Пожалуйста|Просто} сделайте так, чтобы это {удивительное|крутое|простое} тестовое предложение изменялось {быстро|мгновенно|случайным образом|менялось каждый раз}.')
Предложу такой вариант на Javascript:

    function Token(type, pos, value) {
        this.type = type;
        this.pos = pos;
        this.value = value;
    }
    Token.END_OF_LINE = 0;
    Token.OPERATOR = 1;
    Token.TEXT = 2;

    function Parser(text) {
        this._text = text;
        this._pos = 0;
        this._len = text.length;
    }
    Parser.prototype = {
        operators: {'{': true, '}': true, '|': true},
        nextToken: function() {
            if (this._pos >= this._len) return new Token(Token.END_OF_LINE);
            if (this._text[this._pos] in this.operators) {
                return new Token(Token.OPERATOR, this._pos, this._text[this._pos++]);
            }
            var text = '', start = this._pos;
            while ((this._pos < this._len) && !(this._text[this._pos] in this.operators)) {
                text += this._text[this._pos];
                this._pos++;
            }
            return new Token(Token.TEXT, start, text);
        },
        getNextToken: function() {
            var pos = this._pos, result = this.nextToken();
            this._pos = pos;
            return result;
        }
    };

    function Interpretter(text) {
        this._parser = new Parser(text);
    }
    Interpretter.prototype = {
        value: function() {
            var result = '', token = this._parser.getNextToken();
            while (token.type == Token.TEXT || (token.type == Token.OPERATOR && token.value == '{')) {
                token = this._parser.nextToken();
                if (token.type == Token.OPERATOR) {
                    if (token.value == '{') {
                        result += this.expression();
                    } else {
                        throw 'Syntax error at pos ' + token.pos;
                    }
                } else {
                    result += token.value;
                }
                token = this._parser.getNextToken();
            }
            return result;
        },
        expression: function() {
            var variants = [this.value()], token = this._parser.nextToken();
            while (token.value == '|') {
                variants.push(this.value());
                token = this._parser.nextToken();
            }
            if (!token.type == '}') 'Syntax error at pos ' + token.pos;
            return variants[Math.floor(Math.random(1) * variants.length)];
        }
    };

    var text = '{Пожалуйста|Просто} сделайте так, чтобы это {удивительное|крутое|простое} тестовое предложение {изменялось {быстро|мгновенно} случайным образом|менялось каждый раз}.';
    var interpretter = new Interpretter(text);
    alert(interpretter.value());


* This source code was highlighted with Source Code Highlighter.
Я попробовал ООП-версию и получилось, что она по скорости от функциональной недалека.

Отказ от копипаста хорош для проверки знаний, но в реальной работе мне кажется лучше за 20 минут найти готовый пример в интернете, чем тратить полдня на его разработку и отладку.
php без регекспов
$p1=$p2=false;
while (($p2 = strpos($str,'}'))!==false && ($p1 = strrpos(substr($str,0,$p2),'{'))!==false) {
    $a = explode('|', substr($str, $p1+1,$p2-$p1-1));
    $str = substr_replace($str, $a[rand(0,count($a)-1)], $p1, $p2+1-$p1);
}
Оставлю здесь решение под .Net
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)        
        {
            string text = "{Пожалуйста|Просто} сделайте так, чтобы это {удивительное|крутое|простое} тестовое предложение {изменялось {быстро|мгновенно} случайным образом|менялось каждый раз}.";
            StringRandomizerConfig config = new StringRandomizerConfig() { delim = '|', beginBrase = '{', endBrase='}'  };

            var rnd = new StringRandomizer(config);
            
            for (int i = 0; i < 10; i++)
			{
			    Console.WriteLine(rnd.Rand(text));
			}
            Console.ReadKey();
        }
    }

    public struct StringRandomizerConfig
    {
        public char delim;
        public char beginBrase;
        public char endBrase;
    }

    class StringRandomizer
    {
        public StringRandomizerConfig config { get; private set; }
        private Random random = new Random();

        public StringRandomizer(StringRandomizerConfig config)
        {
            this.config = config;
        }

        public string Rand(string text)
        {
            var stack = new Stack<int>();
            if (text.IndexOf(config.beginBrase) > -1)
            {
                int i = 0;
                do
                {
                    if (text[i] == config.beginBrase)
                    {
                        stack.Push(i);
                    }
                    if (text[i] == config.endBrase)
                    {
                        var firstPos = stack.Pop();
                        var lastPos = i;

                        var lenBefore = text.Length;
                        text = text.Replace(text.Substring(firstPos, lastPos - firstPos + 1),
                            Rand(text.Substring(firstPos + 1, lastPos - firstPos - 1)));
                        i -= lenBefore - text.Length;
                    }

                } while (++i < text.Length);

                return text;
            }
            else
            {
                var pieces = text.Split(new[] {config.delim}, StringSplitOptions.RemoveEmptyEntries);
                return pieces[random.Next(pieces.Count() - 1)];
            }
            

        }

    }
}

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории