Главная » Статьи » Повернись ко мне передом

Повернись ко мне передом

Среди разработчиков самые нетривиальные и ответственные задачи, пожалуй, решают фронтендеры. Как сделать конечный продукт понятным и удобным? Как обеспечить кроссплатформенность? Что сделать, чтобы сайт работал без тормозов? Если вас не пугают эти задачи, то мы совместно с Tinkoff.ru предлагаем вам решить несколько несложных задач для будущих разработчиков компании. После завершения теста вы можете оставить свою электронную почту и попасть на второй этап собеседования в девяти городах: Москве, Санкт-Петербурге, Нижнем Новгороде, Екатеринбурге, Ижевске, Рязани, Ростове-на-Дону, Новосибирске и Иннополисе.

Короткая программа

Фронтендер добавила в чат поддержки виджет emoji и отдала в тестирование. «У меня одни квадраты», — сообщил тестировщик с Linux. «Может, цветными их сделаем?» — спросил технолог c Windows 7.
Помогите доделать виджет — поддержите цветные emoji для всех популярных браузеров, сохраняя нативные иконки «под капотом». Наверняка придется прибегнуть к помощи сторонних библиотек, но все они работают медленнее нативных смайлов. Придется исхитриться, чтобы не испортить клиентам впечатление длительными прокрутками или скачиванием всего бандла картинок при открытии виджета с emoji.

HTML

<div class="emoji-picker"> </div>
<div class="message"> </div>

CSS

body { margin: 20px;
}
.emoji-picker { position: relative; width: 200px; height: 200px; overflow-y: scroll; background: #fff; box-shadow: 0 0 10px rgba(0, 0, 0, .5); border-radius: 5px; padding: 10px;
} .emoji-picker section + section { margin-top: 15px;
} .emoji-picker section h2 { margin: 0 0 5px; padding: 0 5px; font: 16px Arial
} .emoji-picker ul { list-style-type: none; padding: 0; margin: 0;
} .emoji-picker ul li { text-align: center; display: inline-block; cursor: pointer; padding: 3px 0 0 5px; line-height: 1.4; border-radius: 3px;
} .emoji-picker ul li:hover { background: #FFC206;
} .message { margin: 10px 0; padding: 5px 10px; background: #eee; min-height: 30px; border-radius: 5px;
}

JS

const picker = document.querySelector('.emoji-picker');
const message = document.querySelector('.message'); const EMOJI_DATA = [ { title: 'Люди', icons: ['?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?'] }, { title: 'Котики', icons: ['?', '?', '?', '?', '?', '?', '?', '?', '?'] }, { title: 'Жесты', icons: ['?', '?', '?', '✊', '✌️', '?'] }
] function addIcon(icon) { message.innerHTML += icon;
} function renderEmojiList(icons) { return icons.map(icon => `<li onclick="addIcon('${icon}')">${icon}</li>` ).join('')
} function renderIconsGroup(group) { return ` <section> <h2>${group.title}</h2> <ul> ${renderEmojiList(group.icons)} </ul> </section>
`
} function renderIcons(emojiData) { return emojiData.map(group => renderIconsGroup(group)).join('');
} picker.innerHTML = renderIcons(EMOJI_DATA);

Произвольная программа

На некоторых сайтах в комментариях программного кода страницы бывает тестовое задание или реклама, но можно пойти глубже. Попробуйте реализовать в консоли браузера рекламный баннер картинкой или гифкой, трансляцию мемов, динамический ascii-art или что захотите.

const width = 34;
const height = 34;
const ctx = document.createElement('canvas').getContext('2d');
const img = new Image(); Object.assign(ctx.canvas, {width, height}); img.src = 'data:image/gif;base64,R0lGODlhIgAiAIIAMTIwMrSeTPzfMNTOzGdjYPz58VRONLCqqCwAAAAAIgAiAAID/ii63P4wykldKTWvW87V0zUABGB4GAh1xzAcRKquhcvN230ZQI8Ktwpn2InVAMSgJQlA1Qwi5wFJZESbHcNJRD1Aj94agTD4AAfa8ujZwV5KLw8BxfMoiKMy7O2cF8FVdy8EBmUFAIaHB15OiDsnZVYkiXtDi05sIjyRQIeJhyJjojCLO5+FMkdfoGIBrq9bBX6yWFYXVJ5ZDmO3HGRmG2tcLgQCrgQBxi1usj93fG+TMMZaxQFyPWqOH21GR6EKAQbhRrNtdp0GYyh+A8XU4Si46o457iilaOTxmfdKnQW+7HHn4FoWaDJsbXF36104R/moRNjhgYo7ZAFK0FlmLmhiNGbuUHGZBIyGiE94agzJQGROixqMAoG4AKOHzZc4bCUpmfNOJyA9gwoFkQAAOw=='; function consoleLog(...messages) { let parts = ['']; for (let item of messages) { if (Array.isArray(item)) { const [message, color] = item; parts[0] += `%c${message}`; } } for (let item of messages) { if (Array.isArray(item)) { const [message, color] = item; parts.push(`font: 16px/10px monospace; background: ${color}; color: ${color}`); } else { parts.push(item); } } console.log.apply(console, parts);
} img.onload = () => { ctx.drawImage(img, 0, 0); const {data} = ctx.getImageData(0, 0, width, height); console.clear(); for (let y = 0; y < height; y++) { let attributes = []; for (let x = 0; x < width; x++) { let i = ((y * width) + x) * 4; const [r, g, b, a] = data.slice(i , i + 4); attributes.push([`${i}`.padStart(2).substr(-2), `rgba(${r}, ${g}, ${b}, ${a})`]); } consoleLog(...attributes); }
};

Классика

Два числа представлены в виде связных списков, где каждый узел содержит одну цифру. Цифры хранятся в списке в обратном порядке. Необходимо перемножить такие списки.

Пример:
   Вход: (7 → 1 → 6 → 2)×(5 → 9 → 2), то есть 2617×295
   Выход: (5 → 1 → 0 → 2 → 7 → 7), то есть 772015

Реализуйте функцию multiplyLists(headNode1, headNode2), которая в качестве аргументов принимает головы двух списков и возвращает голову третьего списка, который является произведением первых двух. Чтобы реализовать эту функцию, необходимо реализовать еще несколько вспомогательных функций: сложение, умножение на цифру, а также сдвиг по разрядам. Конвертировать список в число и обратно не разрешается. Оперировать можно только узлами.

class Node { constructor(value, next = null) { this.value = value; this.next = next; }
} function multiplyListByNumber(headNode, num, carry = 0) { …
} function shiftListByZeros(headNode, digitsСounter) { …
} function sumLists(headNode1, headNode2, carry = 0) { …
} function multiplyLists(headNode1, headNode2) { …
} const headNodeOfList1 = new Node(7, new Node(1, new Node(6, new Node(2))));
const headNodeOfList2 = new Node(5, new Node(9, new Node(2))); const multipliedHeadNode = multiplyLists(headNodeOfList1, headNodeOfList2);
// Node {value: 5, next: Node {value: 1, next: Node {value: 0, next: Node {value: 2, next: Node {value: 7, next: Node {value: 7, next: null}}}}}