Meine Teilnahme an der Programmiermeisterschaft endete. Ich habe im Qualifying gute Arbeit geleistet, 4 von 6 Problemen gelöst und war auf dem 20. Platz. Es gab also Hoffnungen, dass die Top 20 im Finale stehen würden.
Aber leider nicht einmal in die Top 100 gekommen. Nach dem Kampf winken sie nicht mit den Fäusten, aber ich konnte noch einige weitere Aufgaben lösen. Ich mache Sie auf alle Aufgaben aufmerksam, die ich gelöst habe.
Besonderer Dank für die Hilfe bei den Lösungen:
miraage toster.ru/user/miraageprofesor08 toster.ru/user/profesor08SmthTo toster.ru/user/SmthToRAX7 toster.ru/user/RAX7dimoff66 toster.ru/user/dimoff66vk.com/vladilen.mininEndrunde
A. Asynchrone API aus einem Paralleluniversum. (15 Punkte)
Zustand.Ihr Mitentwickler des Paralleluniversums hat Ihnen seine neue Steuerbibliothek für Raumfahrzeuge geschickt. Weil Ein Raumschiff ist eine komplizierte Sache, dann ist die API der Bibliothek ziemlich "gewichtig", die genaue Anzahl der Methoden ist unbekannt, natürlich gibt es keine Dokumentation. Es ist jedoch bekannt, dass in einem Paralleluniversum Menschen an die Decke gehen, tagsüber schlafen, nachts arbeiten, nur asynchrone Funktionen verwenden und immer einen Rückruf als erstes Argument übergeben. Seltsame Jungs! Hier auf der Erde schreibt lange Zeit jeder über Versprechen. Die Bibliothek muss jedoch in das Projekt integriert werden. Daher haben Sie die Aufgabe erhalten, einen Wrapper zu schreiben, der dieselbe API bereitstellt, jedoch zu Versprechungen.
Eingabeformat
Beispiel für eine Quell-API:
const api = { a: { b: { c: callback => setTimeout(() => callback(null, 'hello'), 100) } }, aa: { bb: (callback, x, y) => setTimeout(() => callback(null, x + y), 200) } };
Ausgabeformat
Senden Sie Ihre Lösung als:
module.exports = function promisify(api) {
Anwendungsbeispiel:
const promisedApi = promisify(api); promisedApi.abc() .then(res => console.log(res));
Hinweise
Der Wrapper sollte im Falle eines Fehlers beim Aufrufen der Quell-API ein abgelehntes Versprechen zurückgeben. Der Rückruf akzeptiert den Fehler immer mit dem ersten Argument:
callback(error, data)
In der ursprünglichen API gibt es möglicherweise Konstanten (Zahlen, Zeichenfolgen und Boolesche Werte). Diese müssen unverändert zurückgegeben werden:
api.foo.myConst = 1; promisedApi.foo.myConst === 1;
Die Initialisierung des Wrappers sollte "faul" sein: Die Quell-API kann eine große Anzahl von Namespaces haben, und Sie müssen auf sie zugreifen, während Sie sie verwenden.
LösungIm Wettbewerb habe ich dieses Problem nicht vollständig gelöst und 12,86 von 15 möglichen Punkten für die Lösung erhalten. Ich habe die Rekursion verwendet, um alle Eigenschaften zu umgehen und zu promiskurieren, ob es sich um eine Funktion handelt.
Und nach dem Ende des Tests habe ich die Lösung mithilfe des Proxy-Objekts fertiggestellt. Nur eine solche Option hat alle Tests bestanden. Im Folgenden finden Sie eine Lösung, die Verbesserungen berücksichtigt.
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)
Beachten Sie, dass der Knoten js bereits über ein solches Dienstprogramm verfügt:
nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original . Nur er akzeptiert eine Funktion, deren Rückruf das letzte Argument ist und nicht das erste.
Alles über Proxy:
learn.javascript.ru/proxywww.youtube.com/watch?v=np08WdS9OXgB. Praktikant an Wochentagen (15 Punkte)
Zustand.Das Yandex-Team hat einen Auszubildenden Stepan. Das Timing läuft bereits ab, aber er hat keine Zeit mit dem Seitenlayout. Helfen Sie Stepan, eine davon gemäß dem Layout dieser Aufgabe zusammenzustellen.
Das Layout darf am linken und oberen Rand der Seite nicht eingerückt sein. Bilder können auch nicht verwendet werden. Hier ist das Layout:

Wie Sie sehen können, besteht das Layout aus zwei Kachelgrößen: Standard und Doppel. Standardkacheln nehmen 1/3 der Bildschirmbreite ein, doppelt - 2/3. Feste Fliesenhöhe - 200px. Der Abstand zwischen den Kacheln beträgt 20 Pixel.
Die Hintergrundfarbe der Standardkachel ist # 8a2be2, die Farbe von double ist # 000.
Daher sollten Sie eine HTML-Seite mit Layout für das Layout erhalten. Die Seitengröße sollte 10 KB nicht überschreiten.
Beachten Sie:
In Vorlagen können nur Vorlagen und Stile geschrieben werden. JavaScript und Bilder können nicht verwendet werden.
Zunächst wurde die folgende HTML-Datei vorgeschlagen:
github.com/vito2005/YandexCompetition/blob/master/final-2019/B/original.htmlLösungIm Prinzip könnten Sie auf die Quelldatei verzichten. Aber ich habe es trotzdem als Grundlage genommen.
Schriftarten und Skripte wurden aus dem Markup entfernt, um das Dateigewicht zu reduzieren.
Dann fügte er 6 Divs hinzu und wickelte sie in eine Hülle.
Make-up durch Display: Gitter
Das Ergebnis ist folgendes:
<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. Perfekte Rechtecke (40 Punkte)
Zustand.Bob ist ein expressionistischer Künstler. Alle seine Werke sind streng vertikale Rechtecke auf weißem Hintergrund.
Kürzlich wurde seine Arbeit auf der Website der berühmten Zeitschrift Top Art veröffentlicht. Bob beschloss, sich seine Leinwände genauer anzusehen, zoomte auf die Seite und war entsetzt über die verschwommenen Ecken und verschwommenen Kanten seiner perfekten Rechtecke.
Als gründlicher Mann studierte er das Problem und beschloss, seine Meisterwerke in HTML umzuwandeln, damit die Linien in jedem Winkel und in jedem Maßstab perfekt blieben. Um seinen Plan zu erfüllen, hat er dich ausgewählt.
Schreiben Sie für ihn einen Dienst, der aus Bildern HTML generieren kann.
Eingabeformat
Die Eingabe ist eine Zeichenfolge, die ein Bild in base64 enthält
Ausgabeformat
Geben Sie die Funktion traceImage zurück, die einen Link zum Bild als Eingabe akzeptiert und ein Versprechen zurückgibt, das in die Zeichenfolge aufgelöst wird. Die Linie sollte ein Layout haben, das dieses Bild wiederholt.
Senden Sie Ihre Lösung als:
function traceImage(imageSrc) {
Hinweise
Bild kann jede Größe haben
Das Bild ist nicht transparent
Leere Pixelfarbe - Weiß (r, g, b): (255, 255, 255)
Das Bild zeigt 1 farbiges undurchsichtiges Rechteck
Alle Linien sind horizontal oder vertikal.
Der Code wird im Browser ausgeführt
Beispiel
Das Bild wird in base64 als Zeichenfolge angegeben (in der Form, in der es an die Funktion übergeben wird):
gist.github.com/senaev/50460323558db543256cb7f196e7d81d
Für ein solches Bild können Sie eine Linie erzeugen:
<div> <div style=" position: absolute; width: 11px; height: 15px; top: 135px; left: 109px; background-color: rgb(255, 255, 0); "></div> </div>
LösungDas Wesentliche der Lösung besteht darin, eine Leinwand zu erstellen, die zum Bild passt, das Bild dort zu zeichnen und getImageData zu verwenden, um Informationen über die Farbe jedes Pixels abzurufen. Anschließend müssen Sie die Pixel vom oberen linken Rand durchlaufen, bis Sie ein weißes Pixel erhalten. Als nächstes sortieren Sie die Pixel entlang der horizontalen und vertikalen Achse weiter, bis wir wieder auf ein weißes Pixel stoßen, sodass wir die Breite und Höhe des Rechtecks erhalten.
Dieser Artikel beschreibt die Arbeit mit Canvas und die Verwendung von getImageData.
code.tutsplus.com/de/tutorials/canvas-from-scratch-pixel-manipulation--net-20573Leider hat mein Code nicht alle Tests bestanden und 30 von 40 Punkten erzielt, und ich konnte die Fehler immer noch nicht verstehen. Ich bin dankbar, wenn Sie auf die Mängel hinweisen:
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. Reiten (40 Punkte).
Zustand.Gennady ist ein Intellektueller. Er mag es, interessante Leute zu treffen. Aber als umsichtiger und ungläubiger Mensch tut er dies nur im Internet. Kürzlich entdeckte Gennady, dass Gesprächspartner, die mit IQ vergleichbar sind, im Schachforum zu finden sind. Das Problem ist jedoch, dass Gennady kein Schach spielen kann und alle Lehrer auf Javascript basieren, das Gennady mit Bedacht deaktiviert, um die Wahrscheinlichkeit zu vermeiden, dass der Virus entdeckt wird.
Um Gennady zu helfen, empfehlen wir, ein Tutorial zum Schachspielen ohne Javascript zu erstellen, das zeigt, wie das Pferd läuft. Der Lehrer sollte wie ein Schachbrett aussehen. Sie klicken auf den Käfig - sie zeigen Ihnen, wohin das Pferd aus diesem Käfig gehen kann.
Eingabeformat
HTML-Dokument beim Laden, das ein Schachbrett gezeichnet wird
Ausgabeformat
Die Aufgabe wird in einem echten Browser (Chrome 77) getestet.
Ihr HTML-Dokument wird in den Browser geladen. Der Roboter klickt in verschiedene Zellen des Schachfeldes und macht nach Klicks Screenshots.
Screenshots müssen der Referenz entsprechen
Beispiel

Hinweise
- CSS- und HTML-Implementierung. Javascript kann nicht verwendet werden.
- Das gesamte Layout sollte quadratisch sein, ohne Schatten, Farbverläufe, Verrundungen usw.
- Zellenbreite und -höhe - 30 Pixel
- Das Schachfeld befindet sich auf der Seite oben links ohne Einrückung
- Ausgewählte Zellenfarbe # ff0000
- Die Farbe der Zelle, zu der # 0000ff gehören kann
- Lichtzellenfarbe # f4cd8d
- Dunkle Zellenfarbe. # 745853
- Linke obere Zelle Licht
- Anfangs keine Zelle ausgewählt
Die Auswahl erfolgt durch Klicken auf eine bestimmte Zelle und bleibt bis zum nächsten Klick erhalten
LösungLeider konnte ich für die zugewiesenen 4 Stunden keine vollständige Lösung bereitstellen, es gelang mir, ein Layout zu erstellen und auf die Zelle zu klicken, und erst nach dem Ende des Turniers, nicht ohne die Hilfe von Kollegen aus den Foren, habe ich diese Aufgabe dennoch erledigt.
Das erste, was zu tun war, war, den Eingabetyp = Radio für jede Zelle zu platzieren, eine Beschriftung daran zu binden, das Layout durch display: grid festzulegen und es durch grid-template-column: repeat (8, 30px) in 8 Spalten aufzuteilen. Ich habe viel Zeit mit dem Layout für mögliche Pferdebewegungen verbracht.
Die Schwierigkeit bestand darin, dass Sie in CSS keine vorherigen Elemente formatieren können.
Und es ist in diesem Fall nicht lösbar (wenn das Styling sowohl vorher als auch nachher erfordert).
Um das Markup nicht zu verschmutzen, habe ich mich daher entschlossen, Pseudoelemente, die durch den absoluten und durch einen linearen Farbverlauf gemalten Hintergrund positioniert sind, in Quadrate einzufügen. Ich habe viel Zeit gebraucht und es hat nicht geklappt, aber mir wurde eine hervorragende Lösung empfohlen: Stellen Sie 8 Blautöne für die ausgewählte Zelle ein und ordnen Sie sie so an, wie sie sollte.
Das Ergebnis ist folgendes:
<!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 zur ArbeitsversionFortsetzung folgt…