Minha participação no campeonato de programação terminou. Fiz um bom trabalho na qualificação, tendo resolvido 4 dos 6 problemas e estava na 20ª posição, por isso havia esperanças de que os 20 melhores também estivessem na final.
Mas, infelizmente, nem chegou ao top 100. Após a luta, eles não agitam os punhos, mas eu consegui resolver várias outras tarefas para concluir. Trago à sua atenção todas as tarefas que resolvi.
Agradecimentos especiais pela ajuda nas soluções:
miraage toster.ru/user/miraageprofesor08 toster.ru/user/profesor08SmthTo toster.ru/user/SmthToRAX7 toster.ru/user/RAX7dimoff66 toster.ru/user/dimoff66vk.com/vladilen.mininRodada final
A. API assíncrona de um universo paralelo. (15 pontos)
Condição.Seu colega desenvolvedor do universo paralelo enviou a você sua nova biblioteca de controle de naves espaciais. Porque uma nave espacial é uma coisa complicada, a API da biblioteca é bastante "pesada", o número exato de métodos é desconhecido, é claro, não há documentação. Mas sabe-se que em um universo paralelo, as pessoas andam no teto, dormem durante o dia, trabalham à noite e também usam apenas funções assíncronas e sempre transmitem um retorno de chamada como o primeiro argumento. Caras estranhos! Aqui na Terra, por um longo tempo, todo mundo escreve sobre promessas. No entanto, a biblioteca precisa ser integrada ao projeto. Portanto, você recebeu a tarefa de escrever um wrapper que fornecerá a mesma API, mas com promessas.
Formato de entrada
API de origem de exemplo:
const api = { a: { b: { c: callback => setTimeout(() => callback(null, 'hello'), 100) } }, aa: { bb: (callback, x, y) => setTimeout(() => callback(null, x + y), 200) } };
Formato de saída
Envie sua solução como:
module.exports = function promisify(api) {
Exemplo de uso:
const promisedApi = promisify(api); promisedApi.abc() .then(res => console.log(res));
Anotações
o wrapper deve retornar uma promessa rejeitada em caso de erro ao chamar a API de origem, o retorno de chamada sempre aceita o erro com o primeiro argumento:
callback(error, data)
na API original, pode haver constantes (números, seqüências de caracteres e booleano), elas precisam ser retornadas como estão:
api.foo.myConst = 1; promisedApi.foo.myConst === 1;
a inicialização do wrapper deve ser "lenta": a API de origem pode ter um grande número de namespaces e você precisa acessá-los à medida que os usa.
SoluçãoNo concurso, não resolvi esse problema completamente e obtive 12,86 pontos em 15 possíveis para a solução. Usei a recursão para ignorar todas as propriedades e promiscurate se for uma função.
E após o final do teste, finalizei a solução usando o objeto Proxy. Somente essa opção passou em todos os testes. Abaixo está uma solução, levando em consideração as melhorias.
function promisify (obj) { const cache = {} return new Proxy(obj, { get (target, prop) { const value = target[prop] const type = Object.prototype.toString.call(value) if (type === '[object Object]') { cache[prop] = promisify(value)
Observe que o nó js já possui esse utilitário
nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original , apenas aceita uma função cujo retorno de chamada é o último argumento, e não o primeiro.
Tudo sobre o Proxy:
learn.javascript.ru/proxywww.youtube.com/watch?v=np08WdS9OXgB. Estagiário durante a semana (15 pontos)
Condição.A equipe do Yandex tem um estagiário Stepan. O tempo já está se esgotando, mas ele não tem tempo com o layout da página. Ajude o Stepan a criar um deles de acordo com o layout desta tarefa.
Não deve haver recuo no layout nas bordas esquerda e superior da página. Além disso, as imagens não podem ser usadas. Aqui está o layout:

Como você pode ver, o layout consiste em dois tamanhos de ladrilhos: padrão e duplo. A telha padrão ocupa 1/3 da largura da tela, duas vezes - 2/3. Altura fixa do ladrilho - 200px. A distância entre os blocos é de 20 pixels.
A cor de plano de fundo do bloco padrão é # 8a2be2, a cor é o dobro # 000.
Como resultado, você deve obter uma página HTML com layout para o layout. O tamanho da página não deve exceder 10 KB.
Observe:
somente modelos e estilos podem ser escritos em modelos - JavaScript e imagens não podem ser usadas;
Inicialmente, o seguinte arquivo html foi proposto:
github.com/vito2005/YandexCompetition/blob/master/final-2019/B/original.htmlSoluçãoEm princípio, você poderia ficar sem o arquivo de origem. Mas eu ainda tomei isso como base.
Fontes e scripts removidos da marcação para reduzir o peso do arquivo.
Então ele adicionou 6 divs e os embrulhou em um invólucro.
Maquiagem através da tela: grade
O resultado é o seguinte:
<html> <head> <meta charset="utf-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <style> body { margin: 0; padding: 0; } .wrapper { display: grid; grid-template-columns: repeat(3, 1fr); grid-gap: 20px; } .banner1, .banner2, .banner3, .banner4, .banner7 { background: #8a2be2; height: 200px; } .banner5 { background: #000; grid-column: 2 / 4; } .banner6 { background: #000; grid-column: 1 / 3; } </style> </head> <body> <div class="wrapper"> <div class="banner1"></div> <div class="banner2"></div> <div class="banner3"></div> <div class="banner4"></div> <div class="banner5"></div> <div class="banner6"></div> <div class="banner7"></div> </div> </body> </html>
C. Retângulos perfeitos (40 pontos)
Condição.Bob é um artista expressionista. Todas as suas obras são retângulos estritamente verticais coloridos sobre fundo branco.
Recentemente, seu trabalho foi publicado no site da famosa revista Top Art. Bob decidiu dar uma olhada mais de perto nas telas, deu um zoom na página e ficou horrorizado com os cantos borrados e as bordas confusas de seus retângulos perfeitos.
Sendo um homem completo, ele estudou o problema e decidiu converter suas obras-primas em HTML, para que as linhas permanecessem perfeitas em qualquer ângulo e escala. Para cumprir seu plano, ele escolheu você.
Escreva para ele um serviço que pode gerar html a partir de imagens.
Formato de entrada
A entrada é uma sequência que contém uma imagem em base64
Formato de saída
Retorne a função traceImage, que aceita um link para a imagem como entrada e retorna uma promessa que é resolvida na sequência. A linha deve ter um layout que repita esta imagem.
Envie sua solução como:
function traceImage(imageSrc) {
Anotações
A imagem pode ter qualquer tamanho
A imagem não é transparente
Cor do pixel em branco - Branco (r, g, b): (255, 255, 255)
A imagem mostra 1 retângulo opaco colorido
Todas as linhas são horizontais ou verticais.
O código é executado no navegador
Exemplo
A imagem é fornecida como uma string em base64 (na forma em que será passada para a função):
gist.github.com/senaev/50460323558db543256cb7f196e7d81d
Para essa imagem, você pode gerar uma linha:
<div> <div style=" position: absolute; width: 11px; height: 15px; top: 135px; left: 109px; background-color: rgb(255, 255, 0); "></div> </div>
SoluçãoA essência da solução é criar uma tela para ajustar-se à imagem, desenhar uma imagem lá e começar a usar getImageData para obter informações sobre a cor de cada pixel; então, resta iterar sobre os pixels da borda superior esquerda até obter um pixel branco. Em seguida, continue classificando os pixels ao longo dos eixos horizontal e vertical até encontrarmos novamente um pixel branco, para obter a largura e a altura do retângulo.
Este artigo detalha o trabalho com canvas e o uso de getImageData.
code.tutsplus.com/en/tutorials/canvas-from-scratch-pixel-manipulation--net-20573Infelizmente, meu código não passou em todos os testes e marcou 30 em 40 pontos, e ainda não consegui entender os erros, ficarei grato se você apontar as falhas:
function traceImage (imgSrc) { function loadImg (src) { return new Promise((resolve, reject) => { if (typeof src !== 'string') reject('wrong data') const img = new Image() img.addEventListener('load', () => resolve(img)) img.addEventListener('error', err => reject(err)) img.src = src }) } function calcElementFromImage (img) { const TRANSPARENT_COLOR = [255, 255, 255, 1] const colorFromData = (data, i) => { return [data[i], data[i + 1], data[i + 2], data[i + 3] / 255] } const w = img.naturalWidth const h = img.naturalHeight const canvas = document.createElement('canvas') canvas.width = w canvas.height = h const ctx = canvas.getContext('2d') ctx.drawImage(img, 0, 0, w, h) const data = ctx.getImageData(0, 0, w, h).data let top, left, bgColor let lastIndex = 0 for (let i = lastIndex; i < data.length; i += 4) { const color = colorFromData(data, i) if (!color.every((c, i) => c === TRANSPARENT_COLOR[i])) { const px = i / 4 left = px % w top = px / w | 0 bgColor = color lastIndex = i break } } let width const maxLeftIndex = (w - left) * 4 + lastIndex for (let i = lastIndex; i < maxLeftIndex; i += 4) { const color = colorFromData(data, i) if (color.every((c, i) => c === TRANSPARENT_COLOR[i])) { const x = i / 4 % w width = x - left break } } let height const maxTopIndex = (h - top - 1) * w * 4 + lastIndex const hStep = w * 4 for (let i = lastIndex; i < maxTopIndex; i += hStep) { const color = colorFromData(data, i) if (color.every((c, i) => c === TRANSPARENT_COLOR[i])) { const y = i / 4 / w | 0 height = y - top break } } bgColor = Object.values(bgColor).join(',') return { parentWidth: w, parentHeight: h, top, left, width, height, bgColor } } return loadImg(imgSrc).then(img => { const data = calcElementFromImage(img) const { parentWidth, parentHeight, top, left, width, height, bgColor } = data const div = `<div style=" position: relative; width: ${parentWidth}px; height: ${parentHeight}px;"> <div style=" position: absolute; top: ${top}px; left: ${left}px; width: ${width}px; height: ${height}px; background-color: rgba(${bgColor})"></div> </div>` return Promise.resolve(div) }) }
D. Equitação (40 pontos).
Condição.Gennady é um intelectual. Ele gosta de conhecer pessoas interessantes. Mas, sendo uma pessoa prudente e incrédula, ele faz isso apenas na Internet. Recentemente, Gennady descobriu que interlocutores comparáveis em QI podem ser encontrados no fórum de xadrez, mas o problema é que Gennady não é capaz de jogar xadrez e todos os professores são baseados em javascript, que Gennady desativa cuidadosamente para evitar a possibilidade de pegar o vírus.
Para ajudar a Gennady, sugerimos fazer um tutorial para jogar xadrez sem javascript, que mostrará como o cavalo anda. O professor deve parecer um tabuleiro de xadrez. Você clica na gaiola - eles mostram onde o cavalo pode ir dessa gaiola.
Formato de entrada
html-document ao carregar o tabuleiro de xadrez
Formato de saída
A tarefa será testada em um navegador real (Chrome 77).
Seu documento html será carregado no navegador. O robô clica em várias células do campo de xadrez e faz capturas de tela após cliques.
As capturas de tela devem obedecer à referência
Exemplo

Anotações
- Implementação de CSS e HTML. Javascript não pode ser usado.
- Todo o layout deve ser quadrado, sem sombras, gradientes, filetes, etc.
- Largura e altura da célula - 30 pixels
- O campo de xadrez está na página no canto superior esquerdo, sem indentação
- Cor da célula selecionada # 0000
- A cor da célula que figura # 0000ff pode ir para
- Cor da célula clara # f4cd8d
- Cor de célula escura # 745853
- Luz da célula superior esquerda
- Inicialmente nenhuma célula selecionada
A seleção ocorre clicando em uma célula específica e permanece até o próximo clique
SoluçãoInfelizmente, durante as 4 horas previstas, não consegui fornecer uma solução completa, consegui fazer o layout e clicar na célula, e somente após o término do torneio, não sem a ajuda de colegas dos fóruns, concluí a tarefa.
Portanto, a primeira coisa a fazer era colocar o tipo de entrada = radio para cada célula, vincular um rótulo a elas, definir o layout através de display: grid e dividi-lo em 8 colunas através de grid-template-columns: repeat (8, 30px). Passei muito tempo com o layout para possíveis movimentos de cavalos.
A dificuldade era que, no CSS, você não pode estilizar elementos anteriores.
E não é solucionável neste caso (quando o estilo exige tanto o anterior quanto o posterior).
Portanto, para não poluir a marcação, decidi adicionar pseudoelementos posicionados pelo absoluto e pelo fundo pintado por um gradiente linear em quadrados. Demorei muito tempo e não deu certo, mas me foi aconselhada uma excelente solução: defina 8 tons de azul para a célula selecionada e organize-a como deveria.
O resultado é o seguinte:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style>.white { background: #f4cd8d; } .black { background: #746864; } body { margin: 0; display: flex } div { display: grid; grid-template-columns: repeat(8, 30px); overflow: hidden; } input { display: none; } label { width: 30px; height: 30px; background: #f4cd8d; display: block; position: relative; } input[type="radio"]:checked + label { background: #FF0000; box-shadow: -30px -60px 0 0 #0000FF, -60px -30px 0 0 #0000FF, 30px -60px 0 0 #0000FF, 60px -30px 0 0 #0000FF, -30px 60px 0 0 #0000FF, -60px 30px 0 0 #0000FF, 30px 60px 0 0 #0000FF, 60px 30px 0 0 #0000FF; z-index: 100; position: relative; } </style> </head> <body> <div> <input type="radio" name="tag" id="a1"> <label class="white a1" for="a1"></label> <input type="radio" name="tag" id="b1"> <label class="black b1" for="b1"></label> <input type="radio" name="tag" id="c1"> <label class="white c1" for="c1"></label> <input type="radio" name="tag" id="d1"> <label class="black d1" for="d1"></label> <input type="radio" name="tag" id="e1"> <label class="white e1" for="e1"></label> <input type="radio" name="tag" id="f1"> <label class="black f1" for="f1"></label> <input type="radio" name="tag" id="g1"> <label class="white g1" for="g1"></label> <input type="radio" name="tag" id="h1"> <label class="black h1" for="h1"></label> ........... ........... <input type="radio" name="tag" id="a8"> <label class="black a8" for="a8"></label> <input type="radio" name="tag" id="b8"> <label class="white b8" for="b8"></label> <input type="radio" name="tag" id="c8"> <label class="black c8" for="c8"></label> <input type="radio" name="tag" id="d8"> <label class="white d8" for="d8"></label> <input type="radio" name="tag" id="e8"> <label class="black e8" for="e8"></label> <input type="radio" name="tag" id="f8"> <label class="white f8" for="f8"></label> <input type="radio" name="tag" id="g8"> <label class="black g8" for="g8"></label> <input type="radio" name="tag" id="h8"> <label class="white h8" for="h8"></label> </div> </body> </html>
Link para a versão de trabalhoPara continuar ...