├── utils.js ├── march_2024 └── lesson_1 │ ├── A.png │ ├── A.test.js │ ├── A.go │ ├── B.test.js │ ├── A.js │ ├── B.go │ └── B.js ├── .editorconfig ├── lefthook.yml ├── september_2021_B ├── lesson_3 │ ├── A.test.js │ ├── C.test.js │ ├── B.test.js │ ├── B.js │ ├── C.js │ ├── A.js │ ├── E.test.js │ ├── D.test.js │ ├── D.js │ └── E.js ├── lesson_7 │ ├── D.test.js │ ├── B.test.js │ ├── A.test.js │ ├── C.test.js │ ├── A.js │ ├── B.js │ ├── D.js │ └── C_draft.js ├── lesson_6 │ ├── A.test.js │ ├── C.test.js │ ├── B.test.js │ ├── A.js │ └── B.js ├── lesson_2 │ ├── E.test.js │ ├── C.test.js │ ├── A.test.js │ ├── B.test.js │ ├── D.test.js │ ├── C.js │ ├── A.js │ ├── E.js │ ├── B.js │ └── D.js ├── lesson_1 │ ├── C.test.js │ ├── B.test.js │ ├── E.test.js │ ├── D.test.js │ ├── A.test.js │ ├── C.js │ ├── B.js │ ├── D.js │ └── A.js └── lesson_4 │ ├── B.test.js │ ├── C.js │ ├── C.test.js │ ├── A.test.js │ ├── B.js │ ├── A.js │ ├── D.test.js │ ├── E.test.js │ ├── E.js │ └── D.js ├── june_2021 ├── lesson_1 │ ├── G.test.js │ ├── B.js │ ├── E.test.js │ ├── I.js │ ├── D.js │ ├── F.js │ ├── G.js │ ├── C.js │ ├── A.js │ ├── E.js │ └── H.js ├── lesson_6 │ ├── B.test.js │ ├── A.test.js │ ├── C.test.js │ ├── A.js │ ├── B.js │ └── C.js ├── lesson_3 │ ├── A.js │ ├── D.js │ ├── B.js │ ├── G.js │ ├── E.js │ ├── H.js │ ├── I.js │ ├── C.js │ └── F.js ├── lesson_2 │ ├── A.js │ ├── D.js │ ├── C.js │ ├── H.js │ ├── G.js │ ├── B.js │ ├── F.js │ ├── E.js │ ├── J.js │ └── I.js ├── lesson_4 │ ├── B.js │ ├── C.js │ ├── E.js │ ├── D.js │ ├── F.js │ ├── G.js │ └── I.js └── lesson_5 │ ├── B.js │ ├── A.js │ └── C.js ├── february_2023_B └── lesson_1 │ ├── 8.test.js │ ├── 9.test.js │ ├── 2.test.js │ ├── 3.test.js │ ├── 6.test.js │ ├── 4.test.js │ ├── 5.test.js │ ├── 7.test.js │ ├── 1.test.js │ ├── 8.js │ ├── 5.js │ ├── 6.js │ ├── 9.js │ ├── 1.js │ ├── 3.js │ ├── 2.js │ └── 7.js ├── task-template.js ├── package.json ├── contest-io-template.js ├── september_2021_A └── lesson_1 │ ├── A.test.js │ ├── A.js │ ├── B.test.js │ └── B.js ├── biome.json ├── LICENSE ├── input-output_dev.js ├── .gitignore └── README.md /utils.js: -------------------------------------------------------------------------------- 1 | export const multiLineStrToArrStr = (str) => str.trim().split('\n'); 2 | -------------------------------------------------------------------------------- /march_2024/lesson_1/A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feeedback/yandex-algorithm-training/HEAD/march_2024/lesson_1/A.png -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | root = true 3 | charset = utf-8 4 | insert_final_newline = true 5 | end_of_line = lf 6 | indent_style = space 7 | indent_size = 2 8 | max_line_length = 120 -------------------------------------------------------------------------------- /lefthook.yml: -------------------------------------------------------------------------------- 1 | pre-commit: 2 | commands: 3 | check: 4 | glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}" 5 | run: npx @biomejs/biome check --write --no-errors-on-unmatched --files-ignore-unknown=true --colors=off {staged_files} 6 | stage_fixed: true 7 | -------------------------------------------------------------------------------- /september_2021_B/lesson_3/A.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './A.js'; 4 | 5 | describe('september_2021_B/lesson_3/A', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn(['1 3 2', '4 3 2']), 2); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /september_2021_B/lesson_7/D.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './D.js'; 4 | 5 | describe('september_2021_B/lesson_7/D', () => { 6 | test('// no test?', () => { 7 | assert.deepStrictEqual(fn(['2 1', '0 1', '0 1']), [2]); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /september_2021_B/lesson_6/A.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './A.js'; 4 | 5 | describe('september_2021_B/lesson_6/A', () => { 6 | test('1', () => { 7 | assert.strictEqual( 8 | fn(['5', '10 1 10 3 4', '4', '1 10', '2 9', '3 4', '2 2']), 9 | '5 2 2 0' 10 | ); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /september_2021_B/lesson_2/E.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './E.js'; 4 | 5 | describe('september_2021_B/lesson_2/E', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn(['2', '2 1']), 1); 8 | }); 9 | 10 | test('My', () => { 11 | assert.strictEqual(fn(['3', '1000 2 5']), 7); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /september_2021_B/lesson_3/C.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './C.js'; 4 | 5 | describe('september_2021_B/lesson_3/C', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn(['1 2 2 3 3 3']), '1'); 8 | }); 9 | 10 | test('2', () => { 11 | assert.strictEqual(fn(['4 3 5 2 5 1 3 5']), '4 2 1'); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /september_2021_B/lesson_3/B.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './B.js'; 4 | 5 | describe('september_2021_B/lesson_3/B', () => { 6 | test('1', () => { 7 | assert.deepStrictEqual(fn(['1 2 3 2 3 4']), [ 8 | 'NO', 9 | 'NO', 10 | 'NO', 11 | 'YES', 12 | 'YES', 13 | 'NO', 14 | ]); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /september_2021_B/lesson_7/B.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './B.js'; 4 | 5 | describe('september_2021_B/lesson_7/B', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn(['3', '3 2', '4 2', '5 2']), 2); 8 | }); 9 | 10 | test('2', () => { 11 | assert.strictEqual(fn(['5', '13 4', '15 1', '11 5', '12 3', '10 3']), 3); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /june_2021/lesson_1/G.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './G.js'; 4 | 5 | describe('june_2021/lesson_1/G', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn(['10 5 2']), '4'); 8 | }); 9 | test('2', () => { 10 | assert.strictEqual(fn(['13 5 3']), '3'); 11 | }); 12 | test('2', () => { 13 | assert.strictEqual(fn(['14 5 3']), '4'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /september_2021_B/lesson_2/C.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './C.js'; 4 | 5 | describe('september_2021_B/lesson_2/C', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn(['a']), 0); 8 | }); 9 | test('2', () => { 10 | assert.strictEqual(fn(['ab']), 1); 11 | }); 12 | test('3', () => { 13 | assert.strictEqual(fn(['cognitive']), 4); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /march_2024/lesson_1/A.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './A.js'; 4 | 5 | describe('march_2024/lesson_1/A', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn(['0 7', '12 5']), 25); 8 | }); 9 | 10 | test('2', () => { 11 | assert.strictEqual(fn(['2 3', '10 3']), 14); 12 | }); 13 | 14 | test('my', () => { 15 | assert.strictEqual(fn(['-3 3', '1 2']), 10); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /february_2023_B/lesson_1/8.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import { multiLineStrToArrStr as toLines } from '../../utils.js'; 4 | import fn from './8.js'; 5 | 6 | describe('february_2023_B/lesson_1/8', () => { 7 | test('1', () => { 8 | assert.strictEqual( 9 | fn( 10 | toLines( 11 | `3 12 | 1 1 13 | 1 10 14 | 5 5` 15 | ) 16 | ), 17 | '1 1 5 10' 18 | ); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /september_2021_B/lesson_2/A.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './A.js'; 4 | 5 | describe('september_2021_B/lesson_2/A', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn([1, 7, 9, 0]), 1); 8 | }); 9 | 10 | test('2', () => { 11 | assert.strictEqual(fn([1, 3, 3, 1, 0]), 2); 12 | }); 13 | 14 | test('My', () => { 15 | assert.strictEqual(fn([1, 3, 3, 1, 0, 3]), 2); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /task-template.js: -------------------------------------------------------------------------------- 1 | const fnLogic = () => {}; 2 | 3 | /** 4 | * "< task name >" {@link "< contest link >} 5 | * 6 | * < description > 7 | * 8 | * @param { string[] } lines < input description > 9 | * 10 | * @return { number } < output description & type > 11 | */ 12 | function inputProcessing(lines) { 13 | // const N = Number(lines[0]); 14 | // const secondLineNumbers = lines[1].split(' ').map(Number); 15 | 16 | return fnLogic(); 17 | } 18 | 19 | export default inputProcessing; 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yandex-algorithm-training", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "node --test" 8 | }, 9 | "author": "Alexander Rzhanitsyn", 10 | "license": "ISC", 11 | "engines": { 12 | "node": ">=22" 13 | }, 14 | "type": "module", 15 | "wallaby": { 16 | "autoDetect": true 17 | }, 18 | "bin": {}, 19 | "devDependencies": { 20 | "@biomejs/biome": "2.0.0-beta.1", 21 | "lefthook": "^1.11.10" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /september_2021_B/lesson_1/C.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './C.js'; 4 | 5 | describe('september_2021_B/lesson_1/C', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn(['1 2 2003']), 0); 8 | }); 9 | test('2', () => { 10 | assert.strictEqual(fn(['2 29 2008']), 1); 11 | }); 12 | 13 | test('My', () => { 14 | assert.strictEqual(fn(['1 1 2008']), 1); 15 | assert.strictEqual(fn(['19 19 2008']), 1); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /february_2023_B/lesson_1/9.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import { multiLineStrToArrStr as toLines } from '../../utils.js'; 4 | import fn from './9.js'; 5 | 6 | describe('february_2023_B/lesson_1/9', () => { 7 | test('1', () => { 8 | assert.deepStrictEqual( 9 | fn( 10 | toLines( 11 | `3 3 2 12 | 1 2 3 13 | 4 5 6 14 | 7 8 9 15 | 2 2 3 3 16 | 1 1 2 3 17 | ` 18 | ) 19 | ), 20 | [28, 21] 21 | ); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /september_2021_B/lesson_1/B.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './B.js'; 4 | 5 | describe('september_2021_B/lesson_1/B', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn(['100 5 6']), 0); 8 | }); 9 | test('2', () => { 10 | assert.strictEqual(fn(['10 1 9']), 1); 11 | }); 12 | 13 | test('My', () => { 14 | assert.strictEqual(fn(['8 7 5']), 1); 15 | }); 16 | 17 | test('My', () => { 18 | assert.strictEqual(fn(['8 8 1']), 0); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /september_2021_B/lesson_1/E.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './E.js'; 4 | 5 | describe('september_2021_B/lesson_1/E', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn([5, '1 1']), 0); 8 | }); 9 | 10 | test('2', () => { 11 | assert.strictEqual(fn([3, '-1 -1']), 1); 12 | }); 13 | 14 | test('3', () => { 15 | assert.strictEqual(fn([4, '4 4']), 2); 16 | }); 17 | 18 | test('4', () => { 19 | assert.strictEqual(fn([4, '2 2']), 0); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /contest-io-template.js: -------------------------------------------------------------------------------- 1 | const readline = require('readline'); 2 | 3 | const rl = readline.createInterface({ 4 | input: process.stdin, 5 | output: process.stdout, 6 | }); 7 | 8 | const inputLines = []; 9 | 10 | rl.on('line', (data) => { 11 | const dataStr = data.toString().trim(); 12 | inputLines.push(dataStr); 13 | }); 14 | 15 | rl.on('close', () => { 16 | // eslint-disable-next-line no-undef 17 | const outputLines = inputProcessing(inputLines); 18 | process.stdout.write( 19 | Array.isArray(outputLines) ? outputLines.join('\n') : String(outputLines) 20 | ); 21 | }); 22 | -------------------------------------------------------------------------------- /september_2021_A/lesson_1/A.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './A.js'; 4 | 5 | describe('september_2021_A/lesson_1/A', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn(['1', '1', '2', '2']), 'NO'); 8 | }); 9 | 10 | test('2', () => { 11 | assert.strictEqual(fn([2, -4, 7, 1]), 2); 12 | }); 13 | 14 | test('3', () => { 15 | assert.strictEqual(fn([35, 14, 11, -3]), 'NO'); 16 | }); 17 | 18 | test('my', () => { 19 | assert.strictEqual(fn([0, 0, 11, -3]), 'INF'); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /september_2021_B/lesson_7/A.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './A.js'; 4 | 5 | describe('september_2021_B/lesson_7/A', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn(['1', '10 20']), 10); 8 | }); 9 | 10 | test('2', () => { 11 | assert.strictEqual(fn(['1', '10 10']), 0); 12 | }); 13 | 14 | test('3', () => { 15 | assert.strictEqual(fn(['2', '10 20', '20 40']), 30); 16 | }); 17 | 18 | test('3 my', () => { 19 | assert.strictEqual(fn(['2', '10 20', '30 40']), 20); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /february_2023_B/lesson_1/2.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './2.js'; 4 | 5 | describe('february_2023_B/lesson_1/2', () => { 6 | test('simplified two chars test - max at begin', () => { 7 | assert.strictEqual(fn(['2', 'abbaaba']), 5); 8 | }); 9 | 10 | test('simplified two chars test - max at end', () => { 11 | assert.strictEqual(fn(['2', 'bbabaa']), 5); 12 | }); 13 | 14 | test('1', () => { 15 | assert.strictEqual(fn(['2', 'abcaz']), 4); 16 | }); 17 | 18 | test('2', () => { 19 | assert.strictEqual(fn(['2', 'helto']), 3); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /september_2021_B/lesson_1/D.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './D.js'; 4 | 5 | describe('september_2021_B/lesson_1/D', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn([4, '1 2 3 4']), 3); 8 | }); 9 | 10 | test('2', () => { 11 | assert.strictEqual(fn([3, '-1 0 1']), 0); 12 | }); 13 | 14 | test('My', () => { 15 | assert.strictEqual(fn([2, '10 10']), 10); 16 | }); 17 | test('My 2', () => { 18 | assert.strictEqual(fn([4, '0 0 0 10']), 0); 19 | }); 20 | test('3 from bot', () => { 21 | assert.strictEqual(fn([5, '-9 -1 8 9 10']), 8); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /february_2023_B/lesson_1/3.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './3.js'; 4 | 5 | describe('february_2023_B/lesson_1/3', () => { 6 | test('1', () => { 7 | assert.deepStrictEqual(fn(['1', '5', '2', '4 6']), [0, 1]); 8 | }); 9 | 10 | test('1_my', () => { 11 | assert.deepStrictEqual(fn(['1', '5', '2', '5 6']), [0, 1]); 12 | }); 13 | 14 | test('2', () => { 15 | assert.deepStrictEqual(fn(['3', '100 1 50', '3', '300 0 75']), [3, 0, 2]); 16 | }); 17 | 18 | test('4', () => { 19 | assert.deepStrictEqual(fn(['4', '3 3 2 2', '4', '3 3 4 2']), [1, 1, 2, 0]); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /september_2021_B/lesson_1/A.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './A.js'; 4 | 5 | describe('september_2021_B/lesson_1/A', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn([0, 0, 0]), 0); 8 | }); 9 | test('2', () => { 10 | assert.strictEqual(fn([-1, 0, 1]), 3); 11 | }); 12 | test('3', () => { 13 | assert.strictEqual(fn([42, 1, 6]), 6); 14 | }); 15 | test('4', () => { 16 | assert.strictEqual(fn([44, 7, 4]), 1); 17 | }); 18 | test('5', () => { 19 | assert.strictEqual(fn([1, 4, 0]), 3); 20 | }); 21 | test('6', () => { 22 | assert.strictEqual(fn([-3, 2, 4]), 2); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /september_2021_B/lesson_1/C.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "C. Даты" {@link "https://contest.yandex.ru/contest/28730/problems/C/} 3 | * 4 | * @param { number } x день или месяц 1≤x≤31 5 | * @param { number } y день или месяц 1≤y≤31 6 | * @param { number } year дата 1970≤z≤2069 7 | * 8 | * @return { 0|1 } Выведите 1, если дата определяется однозначно, и 0 в противном случае. 9 | */ 10 | function parseDate(x, y, year) { 11 | return Number(x > 12 || y > 12 || x === y); 12 | } 13 | 14 | // eslint-disable-next-line no-unused-vars 15 | function inputProcessing(lines) { 16 | const [x, y, year] = lines[0].split(' ').map(Number); 17 | 18 | return parseDate(x, y, year); 19 | } 20 | 21 | export default inputProcessing; 22 | -------------------------------------------------------------------------------- /september_2021_B/lesson_2/B.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './B.js'; 4 | 5 | describe('september_2021_B/lesson_2/B', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn(['2 0 1 1 0 1 0 2 1 2']), 3); 8 | 9 | // Примечания; 10 | // В примере из условия дальше всего идти до ближайшего магазина жителям четвертого дома: ближайший 11 | // к их дому магазин находится в первом доме, и им нужно пройти три дома до него. Жителям других 12 | // домов придется пройти меньшее расстояние до ближайшего магазина, поэтому ответ 3. 13 | }); 14 | test('My', () => { 15 | assert.strictEqual(fn(['2 1 1 1']), 3); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /september_2021_B/lesson_3/B.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "B. Встречалось ли число раньше" {@link "https://contest.yandex.ru/contest/28964/problems/B} 3 | * 4 | * @param { number[] } list 5 | * 6 | * @return { Array<'YES'|'NO'> } для каждого числа выведите YES, если это число ранее встречалось или NO, если не встречалось 7 | */ 8 | function mapIsThisNumberPreviouslyOccurred(list) { 9 | const setVisited = new Set(); 10 | 11 | return list.map((num) => 12 | setVisited.has(num) ? 'YES' : setVisited.add(num) && 'NO' 13 | ); 14 | } 15 | 16 | function inputProcessing(lines) { 17 | const list = lines[0].split(' ').map(Number); 18 | 19 | return mapIsThisNumberPreviouslyOccurred(list); 20 | } 21 | 22 | export default inputProcessing; 23 | -------------------------------------------------------------------------------- /september_2021_B/lesson_3/C.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "C. Уникальные элементы" {@link "https://contest.yandex.ru/contest/28964/problems/C} 3 | * 4 | * @param { number[] } list список чисел 5 | * 6 | * @return { string } элементы, которые встречаются в списке только один раз 7 | */ 8 | function filterOnlyOneOccurrences(list) { 9 | const occurrences = new Map(); 10 | for (const num of list) { 11 | occurrences.set(num, (occurrences.get(num) || 0) + 1); 12 | } 13 | 14 | return list.filter((num) => occurrences.get(num) === 1).join(' '); 15 | } 16 | 17 | function inputProcessing(lines) { 18 | const list = lines[0].split(' ').map(Number); 19 | 20 | return filterOnlyOneOccurrences(list); 21 | } 22 | 23 | export default inputProcessing; 24 | -------------------------------------------------------------------------------- /june_2021/lesson_6/B.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './B.js'; 4 | 5 | describe('june_2021/lesson_6/B', () => { 6 | test('1', () => { 7 | assert.deepStrictEqual( 8 | fn(['5 5', '1 3 5 7 9', '2 4 8 1 6']), 9 | [1, 3, 7, 1, 5] 10 | ); 11 | }); 12 | 13 | test('2', () => { 14 | assert.deepStrictEqual( 15 | fn(['6 11', '1 1 4 4 8 120', '1 2 3 4 5 6 7 8 63 64 65']), 16 | [1, 1, 4, 4, 4, 4, 8, 8, 8, 8, 120] 17 | ); 18 | }); 19 | 20 | test('3', () => { 21 | assert.deepStrictEqual( 22 | fn(['10 10', '-5 1 1 3 5 5 8 12 13 16', '0 3 7 -17 23 11 0 11 15 7']), 23 | [1, 3, 8, -5, 16, 12, 1, 12, 16, 8] 24 | ); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /february_2023_B/lesson_1/6.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import { multiLineStrToArrStr as toLines } from '../../utils.js'; 4 | import fn from './6.js'; 5 | 6 | describe('february_2023_B/lesson_1/6', () => { 7 | // В первом тесте имеется по одной дощечке с каждой из 3 различных букв. Ответ 2 достигается на строке "abc" 8 | test('1', () => { 9 | assert.strictEqual( 10 | fn( 11 | toLines( 12 | `10 13 | 3 14 | 1 3 15 | 4 7 16 | 3 4 17 | ` 18 | ) 19 | ), 20 | 1 21 | ); 22 | }); 23 | 24 | test('2', () => { 25 | assert.strictEqual( 26 | fn( 27 | toLines(`10 28 | 4 29 | 1 3 30 | 4 5 31 | 7 8 32 | 4 6 33 | `) 34 | ), 35 | 3 36 | ); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /february_2023_B/lesson_1/4.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import { multiLineStrToArrStr as toLines } from '../../utils.js'; 4 | import fn from './4.js'; 5 | 6 | describe('february_2023_B/lesson_1/4', () => { 7 | test('1', () => { 8 | assert.strictEqual( 9 | fn( 10 | toLines( 11 | `25 12 | 2 13 | 1 14 | 2` 15 | ) 16 | ), 17 | '2 2' 18 | ); 19 | }); 20 | 21 | test('2', () => { 22 | assert.strictEqual( 23 | fn( 24 | toLines(`25 25 | 13 26 | 7 27 | 1`) 28 | ), 29 | '-1' 30 | ); 31 | }); 32 | 33 | test('4', () => { 34 | assert.strictEqual( 35 | fn( 36 | toLines(`11 37 | 5 38 | 3 39 | 2`) 40 | ), 41 | '1 1' 42 | ); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /september_2021_B/lesson_4/B.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './B.js'; 4 | 5 | describe('september_2021_B/lesson_4/B', () => { 6 | test('1', () => { 7 | assert.deepStrictEqual( 8 | fn(['McCain 10', 'McCain 5', 'Obama 9', 'Obama 8', 'McCain 1']), 9 | ['McCain 16', 'Obama 17'] 10 | ); 11 | }); 12 | 13 | test('2', () => { 14 | assert.deepStrictEqual( 15 | fn([ 16 | 'ivanov 100', 17 | 'ivanov 500', 18 | 'ivanov 300', 19 | 'petr 70', 20 | 'tourist 1', 21 | 'tourist 2', 22 | ]), 23 | ['ivanov 900', 'petr 70', 'tourist 3'] 24 | ); 25 | }); 26 | 27 | test('3', () => { 28 | assert.deepStrictEqual(fn(['bur 1']), ['bur 1']); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /september_2021_B/lesson_3/A.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "A. Количество совпадающих" {@link "https://contest.yandex.ru/contest/28964/problems/A/} 3 | * 4 | * @param { number[] } list1 5 | * @param { number[] } list2 6 | * 7 | * @return { number } Выведите ответ на задачу 8 | */ 9 | function calcCountIntersection(list1, list2) { 10 | const set1 = new Set(list1); 11 | const set2 = new Set(list2); 12 | let intersectionCount = 0; 13 | 14 | for (const num of set1) { 15 | if (set2.has(num)) { 16 | intersectionCount += 1; 17 | } 18 | } 19 | return intersectionCount; 20 | } 21 | 22 | function inputProcessing(lines) { 23 | const list1 = lines[0].split(' ').map(Number); 24 | const list2 = lines[1].split(' ').map(Number); 25 | 26 | return calcCountIntersection(list1, list2); 27 | } 28 | 29 | export default inputProcessing; 30 | -------------------------------------------------------------------------------- /september_2021_B/lesson_6/C.test.js: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'node:test'; 2 | 3 | // import assert from 'node:assert/strict'; 4 | // import fn from './C.js'; 5 | 6 | describe('september_2021_B/lesson_6/C', () => { 7 | // 1x^3+-3x^2+3x+-1=0 8 | // x = 1 9 | 10 | test('1', () => { 11 | // assert.approximately(fn(['1 -3 3 -1']), 1.0000036491, 5); 12 | }); 13 | 14 | // test('2', () => { 15 | // assert.approximately(fn(['-1 -6 -12 -7']), -1.0000000111, 5); 16 | // }); 17 | 18 | // test('my 1', () => { 19 | // assert.approximately(fn(['2 5 3 -3']), 1 / 2, 5); 20 | // }); 21 | // test('my 2', () => { 22 | // assert.approximately(fn(['1000 1 1 1']), -0.096991, 5); 23 | // }); 24 | // test('my 2', () => { 25 | // assert.approximately(fn(['1 -1000 -1000 -1000']), -0.096991, 5); 26 | // }); 27 | }); 28 | -------------------------------------------------------------------------------- /june_2021/lesson_3/A.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27663/problems/A 2 | 3 | // Дан список чисел, который может содержать до 100000 чисел. Определите, сколько в нем встречается 4 | // различных чисел. 5 | 6 | // Формат ввода 7 | // Вводится список целых чисел. Все числа списка находятся на одной строке. 8 | 9 | // Формат вывода 10 | // Выведите ответ на задачу. 11 | 12 | function inputProcessing(lines) { 13 | const list = lines[0].split(' ').map(Number); 14 | 15 | return new Set(list).size; 16 | } 17 | 18 | (async () => { 19 | // const inputLines = await input(1); 20 | const inputLines = ['1 2 3 4 5 1 2 1 2 7 3']; 21 | console.log({ inputLines }); 22 | const outputLines = inputProcessing(inputLines); 23 | console.log({ outputLines }); 24 | // output(outputLines); 25 | })(); 26 | 27 | export default inputProcessing; 28 | -------------------------------------------------------------------------------- /september_2021_B/lesson_2/D.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './D.js'; 4 | 5 | describe('september_2021_B/lesson_2/D', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn(['5 2', '0 2']), '2'); 8 | }); 9 | 10 | test('2', () => { 11 | assert.strictEqual(fn(['13 4', '1 4 8 11']), '4 8'); 12 | }); 13 | 14 | test('3', () => { 15 | assert.strictEqual(fn(['14 6', '1 6 8 11 12 13']), '6 8'); 16 | }); 17 | 18 | test('My', () => { 19 | assert.strictEqual(fn(['6 6', '0 1 2 3 4 5']), '2 3'); 20 | 21 | assert.strictEqual(fn(['6 2', '0 5']), '0 5'); 22 | 23 | assert.strictEqual(fn(['6 2', '0 4']), '0 4'); 24 | }); 25 | 26 | test('4 from bot', () => { 27 | assert.strictEqual(fn(['4 4', '0 1 2 3']), '1 2'); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/2.0.0-beta.1/schema.json", 3 | "vcs": { 4 | "enabled": true, 5 | "clientKind": "git", 6 | "useIgnoreFile": true, 7 | "defaultBranch": "main" 8 | }, 9 | "files": { 10 | "ignoreUnknown": false 11 | }, 12 | "formatter": { 13 | "enabled": true, 14 | "useEditorconfig": true 15 | }, 16 | "linter": { 17 | "enabled": true, 18 | "rules": { 19 | "recommended": true 20 | } 21 | }, 22 | "javascript": { 23 | "formatter": { 24 | "quoteStyle": "single", 25 | "trailingCommas": "es5", 26 | "semicolons": "always", 27 | "arrowParentheses": "always" 28 | } 29 | }, 30 | "assist": { 31 | "enabled": true, 32 | "actions": { 33 | "source": { 34 | "organizeImports": "on" 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /september_2021_B/lesson_2/C.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "C. Изготовление палиндромов" {@link "https://contest.yandex.ru/contest/28738/problems/C/} 3 | * 4 | * @param { string } str непустая строка, состоящую из строчных латинских букв. Длина строки не превосходит 10^4 5 | * 6 | * @return { number } минимальное количество символов заменив которые строка станет палиндромом 7 | */ 8 | function calcCountMinCharsReplaceToBePalindrome(str) { 9 | const maxIndex = str.length - 1; 10 | let charsNeedReplaceCount = 0; 11 | 12 | for (let i = 0; i < str.length / 2; i += 1) { 13 | if (str[i] !== str[maxIndex - i]) { 14 | charsNeedReplaceCount += 1; 15 | } 16 | } 17 | 18 | return charsNeedReplaceCount; 19 | } 20 | 21 | function inputProcessing(lines) { 22 | return calcCountMinCharsReplaceToBePalindrome(lines[0]); 23 | } 24 | 25 | export default inputProcessing; 26 | -------------------------------------------------------------------------------- /june_2021/lesson_2/A.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27472/problems/ 2 | 3 | // Дан список. Определите, является ли он монотонно возрастающим 4 | // (то есть верно ли, что каждый элемент этого списка больше предыдущего). 5 | 6 | // Выведите YES, если массив монотонно возрастает и NO в противном случае. 7 | 8 | function inputProcessing(lines) { 9 | const list = lines[0].split(' ').map(Number); 10 | 11 | let last = Number.NEGATIVE_INFINITY; 12 | for (const num of list) { 13 | if (num <= last) { 14 | return 'NO'; 15 | } 16 | last = num; 17 | } 18 | return 'YES'; 19 | } 20 | 21 | (async () => { 22 | // const inputLines = await input(1); 23 | const inputLines = ['-1 -2']; 24 | console.log({ inputLines }); 25 | const outputLines = inputProcessing(inputLines); 26 | console.log({ outputLines }); 27 | // output(outputLines); 28 | })(); 29 | 30 | export default inputProcessing; 31 | -------------------------------------------------------------------------------- /february_2023_B/lesson_1/5.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import { multiLineStrToArrStr as toLines } from '../../utils.js'; 4 | import fn from './5.js'; 5 | 6 | describe('february_2023_B/lesson_1/5', () => { 7 | // В первом тесте имеется по одной дощечке с каждой из 3 различных букв. Ответ 2 достигается на строке "abc" 8 | test('1', () => { 9 | assert.strictEqual( 10 | fn( 11 | toLines( 12 | `3 13 | 1 14 | 1 15 | 1 16 | ` 17 | ) 18 | ), 19 | 2 20 | ); 21 | }); 22 | 23 | test('2', () => { 24 | assert.strictEqual( 25 | fn( 26 | toLines(`2 27 | 3 28 | 4 29 | `) 30 | ), 31 | 3 32 | ); 33 | }); 34 | 35 | test('my', () => { 36 | assert.strictEqual( 37 | fn( 38 | toLines(`1 39 | 99 40 | `) 41 | ), 42 | 0 43 | ); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /june_2021/lesson_1/B.js: -------------------------------------------------------------------------------- 1 | // Даны три натуральных числа. 2 | // Возможно ли построить треугольник с такими сторонами. 3 | // Если это возможно, выведите строку YES, иначе выведите строку NO. 4 | 5 | // Треугольник — это три точки, не лежащие на одной прямой. 6 | 7 | // Формат ввода 8 | // Вводятся три натуральных числа. 9 | 10 | // Формат вывода 11 | // Выведите ответ на задачу. 12 | 13 | import { input, output } from '../../input-output_dev.js'; 14 | 15 | function inputProcessing(lines) { 16 | const [a, b, c] = lines.map(Number); 17 | 18 | let isPossible = 'NO'; 19 | if (a < b + c && b < a + c && c < a + b) { 20 | isPossible = 'YES'; 21 | } 22 | return [isPossible]; 23 | } 24 | 25 | (async () => { 26 | const inputLines = await input(3); 27 | console.log({ inputLines }); 28 | const outputLines = [inputProcessing(inputLines)]; 29 | console.log({ outputLines }); 30 | output(outputLines); 31 | })(); 32 | -------------------------------------------------------------------------------- /february_2023_B/lesson_1/7.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import { multiLineStrToArrStr as toLines } from '../../utils.js'; 4 | import fn from './7.js'; 5 | 6 | describe('february_2023_B/lesson_1/7', () => { 7 | test('1', () => { 8 | assert.strictEqual( 9 | fn( 10 | toLines( 11 | `15:01:00 12 | 18:09:45 13 | 15:01:40` 14 | ) 15 | ), 16 | '18:10:05' 17 | ); 18 | }); 19 | 20 | test('2', () => { 21 | assert.strictEqual( 22 | fn( 23 | toLines( 24 | `11:37:00 25 | 23:51:00 26 | 23:59:59` 27 | ) 28 | ), 29 | '06:02:30' 30 | ); 31 | }); 32 | 33 | test('9', () => { 34 | assert.strictEqual( 35 | fn( 36 | toLines( 37 | `21:00:00 38 | 22:00:00 39 | 06:00:00` 40 | ) 41 | ), 42 | '02:30:00' 43 | ); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /june_2021/lesson_3/D.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27663/problems/D 2 | 3 | // Во входном файле (вы можете читать данные из sys.stdin, подключив библиотеку sys) записан текст. 4 | // Словом считается последовательность непробельных символов идущих подряд, 5 | // слова разделены одним или большим числом пробелов или символами конца строки. 6 | // Определите, сколько различных слов содержится в этом тексте. 7 | 8 | // Формат ввода 9 | // Вводится текст. 10 | 11 | // Формат вывода 12 | // Выведите ответ на задачу. 13 | 14 | import fs from 'fs'; 15 | 16 | // const fs = require('fs'); 17 | 18 | function inputProcessing() { 19 | const data = fs.readFileSync('input.txt', 'utf8'); 20 | // const list = data.split(/[\s\n]/).filter((word) => word !== ''); 21 | const list = data.match(/[^\s\n]+/g); 22 | const words = new Set(list); 23 | // console.log({ words }); 24 | return words.size; 25 | } 26 | 27 | process.stdout.write(String(inputProcessing())); 28 | -------------------------------------------------------------------------------- /june_2021/lesson_6/A.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './A.js'; 4 | 5 | describe('june_2021/lesson_6/A', () => { 6 | test('1', () => { 7 | assert.deepStrictEqual( 8 | fn([ 9 | '10 10', 10 | '1 61 126 217 2876 6127 39162 98126 712687 1000000000', 11 | '100 6127 1 61 200 -10000 1 217 10000 1000000000', 12 | ]), 13 | ['NO', 'YES', 'YES', 'YES', 'NO', 'NO', 'YES', 'YES', 'NO', 'YES'] 14 | ); 15 | }); 16 | 17 | test('2', () => { 18 | assert.deepStrictEqual( 19 | fn(['10 10', '-8 -6 -4 -4 -2 -1 0 2 3 3 ', '8 3 -3 -2 2 -1 2 9 -8 0']), 20 | ['NO', 'YES', 'NO', 'YES', 'YES', 'YES', 'YES', 'NO', 'YES', 'YES'] 21 | ); 22 | }); 23 | 24 | test('3', () => { 25 | assert.deepStrictEqual( 26 | fn(['10 5', '1 2 3 4 5 6 7 8 9 10', '-2 0 4 9 12']), 27 | ['NO', 'NO', 'YES', 'YES', 'NO'] 28 | ); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /september_2021_B/lesson_2/A.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "A. Количество равных максимальному" {@link "https://contest.yandex.ru/contest/28738/problems/A/} 3 | * 4 | * @param { Array countB - countA || a.localeCompare(b)) 20 | .map(([word]) => word); 21 | } 22 | 23 | function inputProcessing(lines) { 24 | const text = lines.join(' '); 25 | 26 | return frequencyAnalysis(text); 27 | } 28 | 29 | export default inputProcessing; 30 | -------------------------------------------------------------------------------- /june_2021/lesson_2/D.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27472/problems/D/ 2 | 3 | // Дан список чисел. Определите, сколько в этом списке элементов, 4 | // которые больше двух своих соседей и выведите количество таких элементов. 5 | 6 | // Формат ввода 7 | // Вводится список чисел. Все числа списка находятся на одной строке. 8 | 9 | // Формат вывода 10 | // Выведите ответ на задачу. 11 | 12 | function inputProcessing(lines) { 13 | const list = lines[0].split(' ').map(Number); 14 | 15 | let count = 0; 16 | 17 | for (let i = 1; i < list.length - 1; i++) { 18 | if (list[i - 1] < list[i] && list[i] > list[i + 1]) { 19 | count += 1; 20 | } 21 | } 22 | return count; 23 | } 24 | 25 | (async () => { 26 | // const inputLines = await input(1); 27 | const inputLines = ['1 2 3 4 5']; 28 | console.log({ inputLines }); 29 | 30 | const outputLines = inputProcessing(inputLines); 31 | console.log({ outputLines }); 32 | // output(outputLines); 33 | })(); 34 | export default inputProcessing; 35 | -------------------------------------------------------------------------------- /june_2021/lesson_6/C.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './C.js'; 4 | 5 | describe('june_2021/lesson_6/C', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn(['2 3 10']), 9); 8 | }); 9 | 10 | test('My. Square', () => { 11 | assert.strictEqual(fn(['1 1 1']), 1); 12 | assert.strictEqual(fn(['1 1 2']), 2); 13 | assert.strictEqual(fn(['1 1 3']), 2); 14 | assert.strictEqual(fn(['1 1 4']), 2); 15 | assert.strictEqual(fn(['1 1 5']), 3); 16 | }); 17 | test('My 1', () => { 18 | assert.strictEqual(fn(['5 2 1']), 5); 19 | assert.strictEqual(fn(['2 5 1']), 5); 20 | }); 21 | test('My 2', () => { 22 | assert.strictEqual(fn(['5 2 10']), 10); 23 | assert.strictEqual(fn(['2 5 10']), 10); 24 | }); 25 | 26 | test('bot. 7', () => { 27 | assert.strictEqual(fn(['5 10 9']), 25); 28 | }); 29 | 30 | test('bot. 11', () => { 31 | assert.strictEqual(fn(['149 651 741']), 8493); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /june_2021/lesson_1/E.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './E.js'; 4 | 5 | describe('june_2021/lesson_1/E', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn(['89 20 41 1 11']), '2 3'); 8 | }); 9 | test('2', () => { 10 | assert.strictEqual(fn(['11 1 1 1 1']), '0 1'); 11 | }); 12 | test('3', () => { 13 | assert.strictEqual(fn(['3 2 2 2 1']), '-1 -1'); 14 | }); 15 | test('4', () => { 16 | assert.strictEqual(fn(['5 20 2 1 1']), '1 0'); 17 | }); 18 | test('5', () => { 19 | assert.strictEqual(fn(['11 2 4 1 2']), '0 2'); 20 | }); 21 | test('6', () => { 22 | assert.strictEqual(fn(['1000 1 449 449 1']), '1000 1'); 23 | }); 24 | test('7', () => { 25 | assert.strictEqual(fn(['40 5 60 6 5']), '4 5'); 26 | }); 27 | test('9', () => { 28 | assert.strictEqual(fn(['753 10 1000 1 1']), '1 1'); 29 | }); 30 | test('14', () => { 31 | assert.strictEqual(fn(['41 10 41 1 10']), '-1 -1'); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /february_2023_B/lesson_1/1.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './1.js'; 4 | 5 | describe('february_2023_B/lesson_1/1', () => { 6 | test('1', () => { 7 | assert.strictEqual( 8 | fn('Hello, world!'), 9 | ` # 10 | ## 11 | ######### 12 | !,Hdelorw` 13 | ); 14 | }); 15 | 16 | test('2', () => { 17 | assert.strictEqual( 18 | fn(`Twas brillig, and the slithy toves 19 | Did gyre and gimble in the wabe; 20 | All mimsy were the borogoves, 21 | And the mome raths outgrabe.`), 22 | ` # 23 | # 24 | # 25 | # 26 | # 27 | # # 28 | # # # 29 | # # ### #### 30 | ## ###### #### 31 | ############## 32 | ############## ## 33 | # # ############## ### 34 | ######################## 35 | ,.;ADTabdeghilmnorstuvwy` 36 | ); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /september_2021_A/lesson_1/A.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "A. Сложное уравнение" {@link "https://contest.yandex.ru/contest/28724/problems/A/} 3 | * 4 | * Решить в целых числах уравнение (ax + b)/(cx + d) = 0 5 | * 6 | * @param { number } a 7 | * @param { number } b 8 | * @param { number } c c и d не равны нулю одновременно 9 | * @param { number } d c и d не равны нулю одновременно 10 | * 11 | * @return { number|"NO"|"INF" } вывести все целочисленные решения, если их число конечно, “NO” (без 12 | * кавычек), если целочисленных решений нет, и “INF” (без кавычек), если их бесконечно много. 13 | */ 14 | function fractionalEquationSolver(a, b, c, d) { 15 | if (a === 0 && b === 0) { 16 | return 'INF'; 17 | } 18 | if (a === 0 || b * c === a * d) { 19 | return 'NO'; 20 | } 21 | if (b % a === 0) { 22 | return -b / a; 23 | } 24 | return 'NO'; 25 | } 26 | 27 | function inputProcessing(lines) { 28 | const [a, b, c, d] = lines.map(Number); 29 | 30 | return fractionalEquationSolver(a, b, c, d); 31 | } 32 | 33 | export default inputProcessing; 34 | -------------------------------------------------------------------------------- /september_2021_B/lesson_6/B.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './B.js'; 4 | 5 | describe('september_2021_B/lesson_6/B', () => { 6 | const splitLine = (str) => str.trim().split('\n'); 7 | 8 | const data = [ 9 | [ 10 | `4 11 | 1 2 2 3 12 | 4 13 | 4 3 2 1 14 | `, 15 | `0 0 16 | 4 4 17 | 2 3 18 | 1 1 19 | `, 20 | ], 21 | [ 22 | `10 23 | 1 2 3 4 5 6 7 7 8 9 24 | 10 25 | 7 3 3 1 3 7 9 7 7 10 26 | `, 27 | `7 8 28 | 3 3 29 | 3 3 30 | 1 1 31 | 3 3 32 | 7 8 33 | 10 10 34 | 7 8 35 | 7 8 36 | 0 0 37 | 38 | `, 39 | ], 40 | [ 41 | `10 42 | 1 3 3 3 3 6 8 8 9 10 43 | 10 44 | 2 9 6 4 2 9 3 7 9 7 45 | `, 46 | `0 0 47 | 9 9 48 | 6 6 49 | 0 0 50 | 0 0 51 | 9 9 52 | 2 5 53 | 0 0 54 | 9 9 55 | 0 0 56 | `, 57 | ], 58 | ]; 59 | 60 | for (let i = 1; i <= data.length; i++) { 61 | const [input, output] = data[i - 1]; 62 | 63 | test(`${i}`, () => { 64 | assert.deepStrictEqual(fn(splitLine(input)), splitLine(output)); 65 | }); 66 | } 67 | }); 68 | -------------------------------------------------------------------------------- /september_2021_B/lesson_2/E.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "E. Дипломы в папках" {@link "https://contest.yandex.ru/contest/28738/problems/E/} 3 | * 4 | * @param { number } folderCount целое число N (1 ≤ N ≤ 100) - количество папок 5 | * @param { Array } diplomasCountByFolder массив целых чисел a1, a2, ..., aN (1 ≤ ai ≤ 100) - количество дипломов в каждой из папок. 6 | * 7 | * @return { number } минимальное количество секунд, необходимое в худшем случае для определения того, в какой папке содержится диплом. 8 | */ 9 | function calcMinSecondToFoundDiplomas(folderCount, diplomasCountByFolder) { 10 | return ( 11 | diplomasCountByFolder 12 | .sort((a, b) => a - b) 13 | .reduce((sum, diplomasCount) => sum + diplomasCount, 0) - 14 | diplomasCountByFolder[folderCount - 1] 15 | ); 16 | } 17 | 18 | function inputProcessing(lines) { 19 | const folderCount = Number(lines[0]); 20 | const diplomasCountByFolder = lines[1].split(' ').map(Number); 21 | 22 | return calcMinSecondToFoundDiplomas(folderCount, diplomasCountByFolder); 23 | } 24 | 25 | export default inputProcessing; 26 | -------------------------------------------------------------------------------- /september_2021_B/lesson_1/B.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "B. Кольцевая линия метро" {@link "https://contest.yandex.ru/contest/28730/problems/B/} 3 | * 4 | * @param { number } stationN (1<=100) общее количество станций кольцевой линии 5 | * @param { number } start N станции, на которой он должен войти. 6 | * @param { number } finish N станции, на которой он должен выйти. Числа i и j не совпадают. 7 | * 8 | * @return { number } минимальное количество промежуточных станций (не считая станции посадки и высадки), которые необходимо проехать 9 | */ 10 | function calcMinStation(stationN, start, finish) { 11 | // Можно ехать в обе стороны и через конец проезжать в начало и наоборот 12 | if (finish < start) { 13 | return Math.min(start - finish, stationN - start + finish) - 1; 14 | } 15 | return Math.min(finish - start, stationN - finish + start) - 1; 16 | } 17 | 18 | // eslint-disable-next-line no-unused-vars 19 | function inputProcessing(lines) { 20 | const [stationN, start, finish] = lines[0].split(' ').map(Number); 21 | 22 | return calcMinStation(stationN, start, finish); 23 | } 24 | 25 | export default inputProcessing; 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Alexander Rzhanitsyn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /march_2024/lesson_1/A.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | func countPaintedTrees(treeIndexV, treeIndexM, radiusV, radiusM int) int { 9 | minIndexV := treeIndexV - radiusV 10 | maxIndexV := treeIndexV + radiusV 11 | 12 | minIndexM := treeIndexM - radiusM 13 | maxIndexM := treeIndexM + radiusM 14 | 15 | maxIndex := int(math.Max(float64(minIndexV), math.Max(float64(maxIndexV), math.Max(float64(minIndexM), float64(maxIndexM))))) 16 | minIndex := int(math.Min(float64(minIndexV), math.Min(float64(maxIndexV), math.Min(float64(minIndexM), float64(maxIndexM))))) 17 | 18 | maxDistance := maxIndex - minIndex 19 | 20 | gap := 0 21 | if minIndexV > maxIndexM { 22 | gap = int(math.Max(0, float64(minIndexV-maxIndexM-1))) 23 | } 24 | if minIndexM > maxIndexV { 25 | gap = int(math.Max(0, float64(minIndexM-maxIndexV-1))) 26 | } 27 | 28 | paintedTrees := maxDistance - gap + 1 29 | 30 | return paintedTrees 31 | } 32 | 33 | func mainA() { 34 | var treeIndexV, treeIndexM, radiusV, radiusM int 35 | fmt.Scan(&treeIndexV, &radiusV, &treeIndexM, &radiusM) 36 | 37 | fmt.Print(countPaintedTrees(treeIndexV, treeIndexM, radiusV, radiusM)) 38 | } 39 | -------------------------------------------------------------------------------- /june_2021/lesson_1/I.js: -------------------------------------------------------------------------------- 1 | // За многие годы заточения узник замка Иф проделал в стене прямоугольное отверстие размером D × E. 2 | // Замок Иф сложен из кирпичей, размером A × B × C. 3 | // Определите, сможет ли узник выбрасывать кирпичи в море через это отверстие, 4 | // если стороны кирпича должны быть параллельны сторонам отверстия. 5 | 6 | // Формат ввода 7 | // Программа получает на вход числа A, B, C, D, E. 8 | 9 | // Формат вывода 10 | // Программа должна вывести слово YES или NO. 11 | 12 | function inputProcessing(lines) { 13 | const [X, Y, Z, windowX, windowY] = lines.map(Number); 14 | const [windowMin, windowMax] = [windowX, windowY].sort((a, b) => a - b); 15 | const [brickMin, brickAverage] = [X, Y, Z].sort((a, b) => a - b); 16 | 17 | if (!(windowMin >= brickMin && windowMax >= brickAverage)) { 18 | return 'NO'; 19 | } 20 | return 'YES'; 21 | } 22 | 23 | (async () => { 24 | // const inputLines = await input(1); 25 | const inputLines = [2, 33, 3, 3, 2]; 26 | console.log({ inputLines }); 27 | const outputLines = inputProcessing(inputLines); 28 | console.log({ outputLines }); 29 | // output(outputLines); 30 | })(); 31 | 32 | export default inputProcessing; 33 | -------------------------------------------------------------------------------- /september_2021_B/lesson_4/C.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './C.js'; 4 | 5 | describe('september_2021_B/lesson_4/C', () => { 6 | test('1', () => { 7 | assert.deepStrictEqual( 8 | fn([ 9 | 'hi', 10 | 'hi', 11 | 'what is your name', 12 | 'my name is bond', 13 | 'james bond', 14 | 'my name is damme', 15 | 'van damme', 16 | 'claude van damme', 17 | 'jean claude van damme', 18 | ]), 19 | [ 20 | 'damme', 21 | 'is', 22 | 'name', 23 | 'van', 24 | 'bond', 25 | 'claude', 26 | 'hi', 27 | 'my', 28 | 'james', 29 | 'jean', 30 | 'what', 31 | 'your', 32 | ] 33 | ); 34 | }); 35 | 36 | test('2', () => { 37 | assert.deepStrictEqual( 38 | fn(['oh you touch my tralala', 'mmm my ding ding dong']), 39 | ['ding', 'my', 'dong', 'mmm', 'oh', 'touch', 'tralala', 'you'] 40 | ); 41 | }); 42 | 43 | test('3', () => { 44 | assert.deepStrictEqual(fn(['ai ai ai ai ai ai ai ai ai ai']), ['ai']); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /june_2021/lesson_1/D.js: -------------------------------------------------------------------------------- 1 | // Решите в целых числах уравнение: 2 | // a, b, c – данные целые числа: найдите все решения или сообщите, что решений в целых числах нет. 3 | 4 | // Формат ввода 5 | // Вводятся три числа a, b и c по одному в строке. 6 | 7 | // Формат вывода 8 | // Программа должна вывести все решения уравнения в порядке возрастания, либо NO SOLUTION (заглавными буквами), если решений нет. Если решений бесконечно много, вывести MANY SOLUTIONS. 9 | 10 | import { input, output } from '../../input-output_dev.js'; 11 | 12 | function inputProcessing(lines) { 13 | const zeroRoot = 'NO SOLUTION'; 14 | const infinitelyRoot = 'MANY SOLUTIONS'; 15 | 16 | const [a, b, c] = lines.map(Number); 17 | if (c < 0) { 18 | return zeroRoot; 19 | } 20 | if (a === 0) { 21 | return c ** 2 === b ? infinitelyRoot : zeroRoot; 22 | } 23 | 24 | const x = (c ** 2 - b) / a; 25 | 26 | if (Number.isInteger(x)) { 27 | return x; 28 | } 29 | return zeroRoot; 30 | } 31 | 32 | (async () => { 33 | const inputLines = await input(3); 34 | console.log({ inputLines }); 35 | const outputLines = inputProcessing(inputLines); 36 | console.log({ outputLines }); 37 | output(outputLines); 38 | })(); 39 | -------------------------------------------------------------------------------- /june_2021/lesson_3/B.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27663/problems/B/ 2 | 3 | // Даны два списка чисел, которые могут содержать до 10000 чисел каждый. Выведите все числа, 4 | // которые входят как в первый, так и во второй список в порядке возрастания. Примечание. И даже 5 | // эту задачу на Питоне можно решить в одну строчку. 6 | 7 | // Формат ввода 8 | // Вводятся два списка целых чисел. Все числа каждого списка находятся на отдельной строке. 9 | 10 | // Формат вывода 11 | // Выведите ответ на задачу. 12 | 13 | function inputProcessing(lines) { 14 | const set1 = new Set(lines[0].split(' ').map(Number)); 15 | const set2 = new Set(lines[1].split(' ').map(Number)); 16 | 17 | const intersection = []; 18 | for (const num of set1) { 19 | if (set2.has(num)) { 20 | intersection.push(num); 21 | } 22 | } 23 | return intersection.sort((a, b) => a - b); 24 | } 25 | 26 | (async () => { 27 | // const inputLines = await input(1); 28 | const inputLines = ['1 3 2', '4 3 2']; 29 | 30 | // console.log({ inputLines }); 31 | const outputLines = inputProcessing(inputLines); 32 | console.log({ outputLines }); 33 | // output(outputLines); 34 | })(); 35 | 36 | export default inputProcessing; 37 | -------------------------------------------------------------------------------- /september_2021_B/lesson_1/D.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "D. Строительство школы" {@link "https://contest.yandex.ru/contest/28730/problems/D/} 3 | * 4 | * @param { number } studentsCount количество учеников (0 < N < 100001) 5 | * @param { Array } studentsHomeCoordArr идут в строго возрастающем порядке координаты домов учеников — целые числа, 6 | * не превосходящие 2×10^9 по модулю. 7 | * 8 | * @return { number } Выведите одно целое число — координату точки, в которой лучше всего построить школу. 9 | * Если ответов несколько, выведите любой из них. 10 | */ 11 | function calcBetterCoordForBuildSchool(studentsCount, studentsHomeCoordArr) { 12 | const lowMiddle = Math.floor((studentsCount - 1) / 2); 13 | const highMiddle = Math.ceil((studentsCount - 1) / 2); 14 | const median = 15 | (studentsHomeCoordArr[lowMiddle] + studentsHomeCoordArr[highMiddle]) / 2; 16 | 17 | return Math.round(median); 18 | } 19 | 20 | // eslint-disable-next-line no-unused-vars 21 | function inputProcessing(lines) { 22 | const studentsCount = Number(lines[0]); 23 | const studentsHomeCoordAr = lines[1].split(' ').map(Number); 24 | 25 | return calcBetterCoordForBuildSchool(studentsCount, studentsHomeCoordAr); 26 | } 27 | // inputProcessing([5, '-9 -1 8 9 10']); 28 | export default inputProcessing; 29 | -------------------------------------------------------------------------------- /february_2023_B/lesson_1/8.js: -------------------------------------------------------------------------------- 1 | const calcMinRectangle = (cells) => { 2 | const MIN = { x: Infinity, y: Infinity }; 3 | const MAX = { x: -Infinity, y: -Infinity }; 4 | 5 | for (const [x, y] of cells) { 6 | if (x < MIN.x) MIN.x = x; 7 | if (y < MIN.y) MIN.y = y; 8 | 9 | if (x > MAX.x) MAX.x = x; 10 | if (y > MAX.y) MAX.y = y; 11 | } 12 | return [MIN.x, MIN.y, MAX.x, MAX.y].join(' '); 13 | }; 14 | 15 | /** 16 | * "8. Минимальный прямоугольник" {@link "https://contest.yandex.ru/contest/45468/problems/8} 17 | * 18 | * На клетчатой плоскости закрашено K клеток. Требуется найти минимальный по площади прямоугольник, 19 | * со сторонами, параллельными линиям сетки, покрывающий все закрашенные клетки. 20 | * 21 | * @param { string[] } lines Во входном файле, на первой строке, находится число K (1 ≤ K ≤ 100). 22 | * На следующих K строках находятся пары чисел Xi и Yi – координаты закрашенных клеток (|Xi|, |Yi| 23 | * ≤ 109). 24 | * 25 | * @return { string } Выведите в выходной файл координаты левого нижнего и правого верхнего углов 26 | * прямоугольника. 27 | */ 28 | function inputProcessing(lines) { 29 | const cells = lines.slice(1).map((xy) => xy.split(' ').map(Number)); 30 | 31 | return calcMinRectangle(cells); 32 | } 33 | 34 | export default inputProcessing; 35 | -------------------------------------------------------------------------------- /june_2021/lesson_4/B.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27665/problems/B 2 | 3 | // Во входном файле (вы можете читать данные из файла input.txt) записан текст. Словом считается 4 | // последовательность непробельных символов идущих подряд, слова разделены одним или большим числом 5 | // пробелов или символами конца строки. Для каждого слова из этого текста подсчитайте, сколько раз 6 | // оно встречалось в этом тексте ранее. 7 | 8 | // Формат ввода 9 | // Вводится текст. 10 | 11 | // Формат вывода 12 | // Выведите ответ на задачу. 13 | 14 | import fs from 'fs'; 15 | 16 | // const fs = require('fs'); 17 | 18 | function inputProcessing() { 19 | const data = fs.readFileSync('input.txt', 'utf8'); 20 | const words = data.match(/[^\s\n]+/g); 21 | const mapWordToCount = {}; 22 | const mapCountEarlier = []; 23 | 24 | if (!words) { 25 | return ''; 26 | } 27 | for (const word of words) { 28 | if (!mapWordToCount[word]) { 29 | mapWordToCount[word] = 1; 30 | mapCountEarlier.push(0); 31 | } else { 32 | mapCountEarlier.push(mapWordToCount[word]); 33 | mapWordToCount[word] += 1; 34 | } 35 | } 36 | // console.log({ words, mapWordToCount, mapCountEarlier }); 37 | return mapCountEarlier.join(' '); 38 | } 39 | 40 | process.stdout.write(String(inputProcessing())); 41 | -------------------------------------------------------------------------------- /september_2021_B/lesson_7/C.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './C_draft.js'; 4 | 5 | describe('september_2021_B/lesson_7/C_draft', () => { 6 | test('1', () => { 7 | assert.strictEqual(fn(['1', '-1 0', '-5 -3', '2 5', '0 0']), 'No solution'); 8 | }); 9 | 10 | test('2', () => { 11 | assert.deepStrictEqual(fn(['1', '-1 0', '0 1', '0 0']), ['1', '0 1']); 12 | }); 13 | 14 | test('my', () => { 15 | assert.deepStrictEqual(fn(['2', '0 2', '0 0']), ['1', '0 2']); 16 | }); 17 | 18 | test('my 2', () => { 19 | assert.deepStrictEqual(fn(['2', '0 5', '0 0']), ['1', '0 5']); 20 | }); 21 | 22 | test('my 3', () => { 23 | assert.strictEqual(fn(['2', '2 5', '0 0']), 'No solution'); 24 | }); 25 | 26 | test('my 4', () => { 27 | assert.deepStrictEqual(fn(['2', '0 1', '1 1', '1 2', '0 0']), [ 28 | '2', 29 | '0 1', 30 | '1 2', 31 | ]); 32 | }); 33 | 34 | // test('my 5', () => { 35 | // assert.strictEqual(fn(['2', '0 1', '1 1', '1 2', '0 3', '0 0']), ['1', '0 3']); 36 | // }); 37 | 38 | // TODO: DRAFT version, solution not ready, test failed 39 | // test('my 6', () => { 40 | // assert.strictEqual(fn(['2', '0 1', '1 2', '0 2', '0 0']), ['1', '0 2']); 41 | // }); 42 | }); 43 | -------------------------------------------------------------------------------- /march_2024/lesson_1/B.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './B.js'; 4 | 5 | describe('march_2024/lesson_1/B', () => { 6 | test('team1 >', () => { 7 | assert.strictEqual(fn(['2:0', '0:0', '1']), 0); 8 | }); 9 | test('team2 > (team2 > opponent pitch)', () => { 10 | assert.strictEqual(fn(['0:2', '0:0', '1']), 2 + 1); // 3:0 11 | }); 12 | test('team2 > (first match 0:0) (team2 > home pitch)', () => { 13 | assert.strictEqual(fn(['0:0', '0:2', '1']), 2); // 2:2 14 | }); 15 | test('team2 > (first match 0:0) (team2 > opponent pitch)', () => { 16 | assert.strictEqual(fn(['0:0', '0:2', '2']), 2 + 1); // 3:2 17 | }); 18 | test('team2 > (team2 > home pitch)', () => { 19 | assert.strictEqual(fn(['0:2', '0:2', '1']), 4); // 4:2 20 | }); 21 | test('team2 = team1', () => { 22 | assert.strictEqual(fn(['0:0', '0:0', '2']), 0 + 1); // 1:0 23 | }); 24 | 25 | test('1 (team2 = team1)', () => { 26 | assert.strictEqual(fn(['0:0', '0:0', '1']), 0 + 1); 27 | }); 28 | test('2', () => { 29 | assert.strictEqual(fn(['0:2', '0:3', '1']), 5); 30 | }); 31 | test('3', () => { 32 | assert.strictEqual(fn(['0:2', '0:3', '2']), 5 + 1); 33 | }); 34 | test('5', () => { 35 | assert.strictEqual(fn(['2:2', '1:1', '2']), 0); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /september_2021_B/lesson_3/E.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './E.js'; 4 | 5 | describe('september_2021_B/lesson_3/E', () => { 6 | test('1', () => { 7 | assert.deepStrictEqual( 8 | fn(['3', 'ABC', 'A37', 'BCDA', '2', 'A317BD', 'B137AC']), 9 | ['B137AC'] 10 | ); 11 | }); 12 | 13 | test('2', () => { 14 | assert.deepStrictEqual( 15 | fn(['2', '1ABC', '3A4B', '3', 'A143BC', 'C143AB', 'AAABC1']), 16 | ['A143BC', 'C143AB'] 17 | ); 18 | }); 19 | test('3 from Bot', () => { 20 | assert.deepStrictEqual( 21 | fn([ 22 | '1', 23 | 'AAAAAAAAAAAA', 24 | '13', 25 | 'AAAAAAAAAAAAAB', 26 | 'BASD234234', 27 | 'ASDBSBF', 28 | 'BBBBBDS', 29 | 'SDASDSD', 30 | 'AAAAAA', 31 | 'BBBBBDS', 32 | 'ASDBSBF', 33 | 'AAAAAA', 34 | 'BABA', 35 | 'AB', 36 | 'A', 37 | 'AAAAAAAAAAAAAAAAAAAA', 38 | ]), 39 | [ 40 | 'AAAAAAAAAAAAAB', 41 | 'BASD234234', 42 | 'ASDBSBF', 43 | 'SDASDSD', 44 | 'AAAAAA', 45 | 'ASDBSBF', 46 | 'AAAAAA', 47 | 'BABA', 48 | 'AB', 49 | 'A', 50 | 'AAAAAAAAAAAAAAAAAAAA', 51 | ] 52 | ); 53 | }); 54 | }); 55 | -------------------------------------------------------------------------------- /input-output_dev.js: -------------------------------------------------------------------------------- 1 | import readline from 'readline'; 2 | 3 | const rl = readline.createInterface({ 4 | input: process.stdin, 5 | output: process.stdout, 6 | }); 7 | 8 | const promisedReadline = () => 9 | new Promise((resolve, reject) => { 10 | const id = setTimeout(() => { 11 | // throw new Error('TIMEOUT wait line stdin'); 12 | // eslint-disable-next-line prefer-promise-reject-errors 13 | reject('TIMEOUT wait line stdin'); 14 | }, 10000); 15 | 16 | rl.once('line', (data) => { 17 | clearTimeout(id); 18 | resolve(data); 19 | }); 20 | }); 21 | 22 | export const input = async (INPUT_LINE_COUNT = 1) => { 23 | const inputLines = []; 24 | 25 | do { 26 | try { 27 | const data = await promisedReadline(); 28 | inputLines.push(data.toString().trim()); 29 | } catch (error) { 30 | console.log(error); 31 | console.log( 32 | `Received ${inputLines.length} just lines. Expected ${INPUT_LINE_COUNT}` 33 | ); 34 | rl.close(); 35 | return inputLines; 36 | } 37 | } while (inputLines.length < INPUT_LINE_COUNT); 38 | 39 | rl.close(); 40 | 41 | return inputLines; 42 | }; 43 | 44 | export const output = (outputLines) => { 45 | process.stdout.write( 46 | Array.isArray(outputLines) ? outputLines.join('\n') : String(outputLines) 47 | ); 48 | // process.exit(); 49 | }; 50 | -------------------------------------------------------------------------------- /september_2021_B/lesson_4/A.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './A.js'; 4 | 5 | describe('september_2021_B/lesson_4/A', () => { 6 | test('1', () => { 7 | assert.deepStrictEqual( 8 | fn([ 9 | '7', 10 | '1 5', 11 | '10 -5', 12 | '1 10', 13 | '4 -2', 14 | '4 3', 15 | '4 1', 16 | '4 0', // 17 | ]), 18 | [ 19 | '1 15', 20 | '4 2', 21 | '10 -5', // 22 | ] 23 | ); 24 | }); 25 | 26 | test('2', () => { 27 | assert.deepStrictEqual( 28 | fn([ 29 | '5', 30 | '5 -10000', 31 | '-5 100000000000', 32 | '10 2000000000000', 33 | '-5 -300000000000', 34 | '0 10000000000000', // 35 | ]), 36 | [ 37 | '-5 -200000000000', 38 | '0 10000000000000', 39 | '5 -10000', 40 | '10 2000000000000', // 41 | ] 42 | ); 43 | }); 44 | test('4 BOT', () => { 45 | assert.deepStrictEqual( 46 | fn([ 47 | '5', 48 | '5 -10000', 49 | '-5 100000000000', 50 | '10 2000000000000', 51 | '-5 -300000000000', 52 | '0 10000000000000', // 53 | ]), 54 | [ 55 | '-5 -200000000000', 56 | '0 10000000000000', 57 | '5 -10000', 58 | '10 2000000000000', // 59 | ] 60 | ); 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /september_2021_B/lesson_4/B.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "B. Выборы в США" {@link "https://contest.yandex.ru/contest/28970/problems/B/} 3 | * 4 | * Чему будут равны значения чисел, если сложить между собой все те, что имеют одинаковый цвет. 5 | * Напишите, пожалуйста, программу, которая выводит результат. 6 | * 7 | * @param { Array<[string, number] } surnameWithVotes список - фамилия кандидата, за которого отдают 8 | * голоса выборщики этого штата, и количество выборщиков, отдавших голоса за этого кандидата. 9 | * 10 | * @return { string[] } Выведите фамилии всех кандидатов в лексикографическом порядке, затем, через 11 | * пробел, количество отданных за них голосов. 12 | */ 13 | function calcVotesInTheElections(surnameWithVotes) { 14 | const votesBySurname = new Map(); 15 | 16 | for (let index = 0; index < surnameWithVotes.length; index++) { 17 | const [surname, votesCount] = surnameWithVotes[index]; 18 | 19 | votesBySurname.set( 20 | surname, 21 | BigInt(votesBySurname.get(surname) || 0) + BigInt(votesCount) 22 | ); 23 | } 24 | const surnames = [...votesBySurname.keys()].sort((a, b) => 25 | a.localeCompare(b) 26 | ); 27 | 28 | return surnames.map((color) => `${color} ${votesBySurname.get(color)}`); 29 | } 30 | 31 | function inputProcessing(lines) { 32 | const surnameWithVotes = lines.map((line) => line.split(' ')); 33 | 34 | return calcVotesInTheElections(surnameWithVotes); 35 | } 36 | 37 | export default inputProcessing; 38 | -------------------------------------------------------------------------------- /june_2021/lesson_2/C.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27472/problems/C/ 2 | 3 | // Напишите программу, которая находит в массиве элемент, самый близкий по величине к данному числу. 4 | 5 | // Формат ввода 6 | // В первой строке задается одно натуральное число N, не превосходящее 1000 – размер массива. 7 | // Во второй строке содержатся N чисел – элементы массива(целые числа, не превосходящие по модулю 1000). 8 | // В третьей строке вводится одно целое число x, не превосходящее по модулю 1000. 9 | 10 | // Формат вывода 11 | // Вывести значение элемента массива, ближайшее к x. Если таких чисел несколько, выведите любое из них. 12 | 13 | function inputProcessing(lines) { 14 | // const arrLength = Number(lines[0]); 15 | const X = Number(lines[2]); 16 | const list = lines[1].split(' ').map(Number); 17 | 18 | let minDiff = Infinity; 19 | let numMinDiff = null; 20 | 21 | for (const num of list) { 22 | const diff = Math.abs(num - X); 23 | 24 | if (diff < minDiff) { 25 | if (diff === 0) { 26 | return num; 27 | } 28 | 29 | minDiff = diff; 30 | numMinDiff = num; 31 | } 32 | } 33 | return numMinDiff; 34 | } 35 | 36 | (async () => { 37 | // const inputLines = await input(1); 38 | const inputLines = [5, '-2 5 4 -3 -2 2 1 0', -1]; 39 | console.log({ inputLines }); 40 | 41 | const outputLines = inputProcessing(inputLines); 42 | console.log({ outputLines }); 43 | // output(outputLines); 44 | })(); 45 | export default inputProcessing; 46 | -------------------------------------------------------------------------------- /september_2021_B/lesson_4/A.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-nested-ternary */ 2 | /** 3 | * "A. Толя-Карп и новый набор структур, часть 2" {@link "https://contest.yandex.ru/contest/28970/problems/A/} 4 | * 5 | * Чему будут равны значения чисел, если сложить между собой все те, что имеют одинаковый цвет. 6 | * Напишите, пожалуйста, программу, которая выводит результат. 7 | * 8 | * @param { BigInt } count число n (0 ≤ n ≤ 2*10^5) 9 | * @param { Array<[BigInt, BigInt] } colorWithValues список по два числа: цвет числа в ящике di и 10 | * значение числа ai (-10^18 ≤ di ai ≤ 10^18). 11 | * 12 | * @return { string[] } Выведите в порядке возрастания номера цвета пары чисел, каждая в новой 13 | * строке: номер цвета и сумму всех чисел данного цвета. 14 | */ 15 | function calcColorsBoxCounts(count, colorWithValues) { 16 | const colorsSums = new Map(); 17 | 18 | for (let index = 0; index < count; index++) { 19 | const [color, value] = colorWithValues[index]; 20 | colorsSums.set(color, BigInt(colorsSums.get(color) || 0) + value); 21 | } 22 | 23 | const colors = [...colorsSums.keys()].sort((a, b) => 24 | a < b ? -1 : a > b ? 1 : 0 25 | ); 26 | 27 | return colors.map((color) => `${color} ${colorsSums.get(color)}`); 28 | } 29 | 30 | function inputProcessing(lines) { 31 | const count = BigInt(lines[0]); 32 | const colorWithValues = lines 33 | .slice(1) 34 | .map((line) => line.split(' ').map((n) => BigInt(n))); 35 | 36 | return calcColorsBoxCounts(count, colorWithValues); 37 | } 38 | 39 | export default inputProcessing; 40 | -------------------------------------------------------------------------------- /march_2024/lesson_1/A.js: -------------------------------------------------------------------------------- 1 | function countPaintedTrees(treeIndexV, treeIndexM, radiusV, radiusM) { 2 | const minIndexV = treeIndexV - radiusV; 3 | const maxIndexV = treeIndexV + radiusV; 4 | 5 | const minIndexM = treeIndexM - radiusM; 6 | const maxIndexM = treeIndexM + radiusM; 7 | 8 | const maxIndex = Math.max(minIndexV, maxIndexV, minIndexM, maxIndexM); 9 | const minIndex = Math.min(minIndexV, maxIndexV, minIndexM, maxIndexM); 10 | 11 | const maxDistance = maxIndex - minIndex; 12 | 13 | let gap = 0; 14 | if (minIndexV > maxIndexM) { 15 | gap = Math.max(0, minIndexV - maxIndexM - 1); 16 | } 17 | if (minIndexM > maxIndexV) { 18 | gap = Math.max(0, minIndexM - maxIndexV - 1); 19 | } 20 | 21 | const paintedTrees = maxDistance - gap + 1; 22 | 23 | return paintedTrees; 24 | } 25 | 26 | /** 27 | * "A. Покраска деревьев" {@link "https://contest.yandex.ru/contest/59539/problems/A} 28 | * 29 | * @param { string[] } lines В первой строке содержится два целых числа P и V — номер дерева, у 30 | * которого стоит ведро Васи и на сколько деревьев он может от него удаляться. В второй строке 31 | * содержится два целых числа Q и M — аналогичные данные для Маши. 32 | * Все числа целые и по модулю не превосходят 10^8 33 | 34 | * @return { number } Выведите одно число — количество деревьев, которые могут быть покрашены. 35 | */ 36 | function inputProcessing(lines) { 37 | const [P, V] = lines[0].split(' ').map(Number); 38 | const [Q, M] = lines[1].split(' ').map(Number); 39 | 40 | return countPaintedTrees(P, Q, V, M); 41 | } 42 | 43 | export default inputProcessing; 44 | -------------------------------------------------------------------------------- /september_2021_B/lesson_4/D.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './D.js'; 4 | 5 | describe('september_2021_B/lesson_4/D', () => { 6 | test('1', () => { 7 | assert.deepStrictEqual( 8 | fn(['Party One 100000', 'Party Two 200000', 'Party Three 400000']), 9 | ['Party One 64', 'Party Two 129', 'Party Three 257'] 10 | ); 11 | }); 12 | 13 | test('2', () => { 14 | assert.deepStrictEqual(fn(['Party number one 100', 'Partytwo 100']), [ 15 | 'Party number one 225', 16 | 'Partytwo 225', 17 | ]); 18 | }); 19 | 20 | test('3', () => { 21 | assert.deepStrictEqual(fn(['Party number one 449', 'Partytwo 1']), [ 22 | 'Party number one 449', 23 | 'Partytwo 1', 24 | ]); 25 | }); 26 | 27 | test('My "Если же для двух партий эти дробные части равны, то преимущество отдается той партии, которая получила большее число голосов"', () => { 28 | assert.deepStrictEqual(fn(['a 12', 'b 5', 'c 43']), [ 29 | 'a 90', 30 | 'b 37', 31 | 'c 323', 32 | ]); 33 | }); 34 | 35 | // Поиск случая когда важно условия из теста выше 36 | 37 | // import { randomInt } from 'crypto'; 38 | // const aCode = 'a'.charCodeAt(); 39 | // const size = 3; 40 | // for (let n = 0; n < 10000; n++) { 41 | // const data = new Array(size) 42 | // .fill(null) 43 | // .map((_, i) => `${String.fromCharCode(aCode + (i % size))} ${randomInt(1, 50)}`); 44 | // const result = fn(data); 45 | // if (result === null) { 46 | // console.log(data); 47 | // break; 48 | // } 49 | // } 50 | }); 51 | -------------------------------------------------------------------------------- /september_2021_B/lesson_7/A.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "A. Закраска прямой" {@link "https://contest.yandex.ru/contest/29396/problems/A/} 3 | * 4 | * На числовой прямой окрасили N отрезков. Известны координаты левого и правого концов каждого 5 | * отрезка (Li и Ri). Найти длину окрашенной части числовой прямой. 6 | * 7 | * @param { number } n длина массива (1 ≤ N ≤ 15000) 8 | * @param { Array } segments - пары Li и Ri (целые числа, -10^9 ≤ Li ≤ Ri ≤ 10^9) 9 | * 10 | * @return { number } Вывести одно число - длину окрашенной части прямой. 11 | */ 12 | function lengthWhenWasAtLeastOne(n, segments) { 13 | const EVENT_TYPE = { begin: 0, end: 1 }; 14 | const events = []; 15 | 16 | for (let i = 0; i < n; i++) { 17 | const [begin, end] = segments[i]; 18 | 19 | events.push({ time: begin, type: EVENT_TYPE.begin }); 20 | events.push({ time: end, type: EVENT_TYPE.end }); 21 | } 22 | 23 | events.sort((prev, next) => prev.time - next.time || prev.type - next.type); 24 | 25 | let nowCount = 0; 26 | let atLeastOneLength = 0; 27 | 28 | for (let i = 0; i < n * 2; i++) { 29 | if (nowCount > 0) { 30 | atLeastOneLength += events[i].time - events[i - 1].time; 31 | } 32 | 33 | if (events[i].type === EVENT_TYPE.begin) { 34 | nowCount += 1; 35 | } else if (events[i].type === EVENT_TYPE.end) { 36 | nowCount -= 1; 37 | } 38 | } 39 | 40 | return atLeastOneLength; 41 | } 42 | 43 | function inputProcessing(lines) { 44 | const n = Number(lines[0]); 45 | const segmentsLR = lines.slice(1).map((lr) => lr.split(' ').map(Number)); 46 | 47 | return lengthWhenWasAtLeastOne(n, segmentsLR); 48 | } 49 | 50 | export default inputProcessing; 51 | -------------------------------------------------------------------------------- /september_2021_B/lesson_7/B.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "B. Таможня" {@link "https://contest.yandex.ru/contest/29396/problems/B/} 3 | * 4 | * ...какое минимальное количество аппаратов необходимо заказать на заводе, если на одном аппарате 5 | * может одновременно обрабатываться только один груз 6 | * 7 | * @param { number } n длина массива (0 ≤ N ≤ 50 000) 8 | * @param { Array } segments - Ti и Li – время прибытия соответствующего груза и время, 9 | * требуемое для его обработки (1 ≤ Ti ≤ 10^6, 1 ≤ Li ≤ 10^6). 10 | * 11 | * @return { number } наименьшее количество аппаратов 12 | */ 13 | function maxCountSegmentsAtSameTime(n, segments) { 14 | const EVENT_TYPE = { begin: 0, end: -1 }; // сначала освобождение аппарата 15 | const events = []; 16 | 17 | for (let i = 0; i < n; i++) { 18 | const [begin, duration] = segments[i]; 19 | 20 | events.push({ time: begin, type: EVENT_TYPE.begin }); 21 | events.push({ time: begin + duration, type: EVENT_TYPE.end }); 22 | } 23 | 24 | events.sort((prev, next) => prev.time - next.time || prev.type - next.type); 25 | 26 | let nowCount = 0; 27 | let max = 0; 28 | 29 | for (let i = 0; i < n * 2; i++) { 30 | if (events[i].type === EVENT_TYPE.begin) { 31 | nowCount += 1; 32 | } else if (events[i].type === EVENT_TYPE.end) { 33 | nowCount -= 1; 34 | } 35 | 36 | max = Math.max(max, nowCount); 37 | } 38 | 39 | return max; 40 | } 41 | 42 | function inputProcessing(lines) { 43 | const n = Number(lines[0]); 44 | const segmentsLR = lines.slice(1).map((lr) => lr.split(' ').map(Number)); 45 | 46 | return maxCountSegmentsAtSameTime(n, segmentsLR); 47 | } 48 | 49 | export default inputProcessing; 50 | -------------------------------------------------------------------------------- /february_2023_B/lesson_1/5.js: -------------------------------------------------------------------------------- 1 | const calcGoodValueForString = (alphabetLength, countCharsInString) => { 2 | let goodValue = 0; 3 | 4 | for (let i = 0; i < alphabetLength - 1; i++) { 5 | goodValue += Math.min(countCharsInString[i], countCharsInString[i + 1]); 6 | } 7 | return goodValue; 8 | }; 9 | 10 | /** 11 | * "5. Хорошая строка" {@link "https://contest.yandex.ru/contest/45468/problems/5} 12 | * 13 | * Прямо сейчас юный исследователь полностью поглощён изучением хорошести строк. Хорошестью строки 14 | * называется количество позиций от 1 до L-1 (где L — длина строки), таких, что следующая буква в 15 | * строке является следующей по алфавиту. Например, хорошесть строки "abcdefghijklmnopqrstuvwxyz" 16 | * равна 25, а строки "abdc" — только 1. 17 | * 18 | * @param { string[] } lines Первая строка ввода содержит единственное целое число N — количество 19 | * различных букв в наборе (1 ≤ N ≤ 26). Обратите внимание: в наборе всегда используются N первых 20 | * букв латинского алфавита. 21 | * Следующие N строк содержат целые положительные числа ci — количество букв соответствующего типа 22 | * (1 ≤ ci ≤ 10^9) 23 | * Таким образом, первое число означает количество букв "a", второе число задаёт количество букв 24 | * "b" и так далее. 25 | * 26 | * @return { number } Выведите единственное целое число — максимально возможную хорошесть строки, 27 | * которую можно собрать из имеющихся дощечек. 28 | */ 29 | function inputProcessing(lines) { 30 | const alphabetLength = Number(lines[0]); 31 | const countCharsInString = lines.slice(1).map(Number); 32 | 33 | return calcGoodValueForString(alphabetLength, countCharsInString); 34 | } 35 | 36 | export default inputProcessing; 37 | -------------------------------------------------------------------------------- /september_2021_B/lesson_1/A.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "A. Interactor" {@link "https://contest.yandex.ru/contest/28730/problems/A/} 3 | * 4 | * @param { number } exitCode (−128≤r≤127) — код завершения задачи, 5 | * @param { number } verdictI (0≤i≤7) — вердикт интерактора, 6 | * @param { number } verdictC (0≤c≤7) — вердикт чекера. 7 | * 8 | * @return { number } одно целое число от 0<=r<=7 — итоговый вердикт системы. 9 | */ 10 | function checkSystem(exitCode, verdictI, verdictC) { 11 | // Если интерактор выдал вердикт 0, итоговый вердикт равен 3 в случае, 12 | // если программа завершилась с ненулевым кодом, и вердикту чекера в противном случае. 13 | // Если интерактор выдал вердикт 1, итоговый вердикт равен вердикту чекера. 14 | // Если интерактор выдал вердикт 4, итоговый вердикт равен 3 в случае, 15 | // если программа завершилась с ненулевым кодом, и 4 в противном случае. 16 | // Если интерактор выдал вердикт 6, итоговый вердикт равен 0. 17 | // Если интерактор выдал вердикт 7, итоговый вердикт равен 1. 18 | // В остальных случаях итоговый вердикт равен вердикту интерактора. 19 | 20 | const mapVerdictItoFnResult = { 21 | 0: (code, c) => (code !== 0 ? 3 : c), 22 | 4: (code, c) => (code !== 0 ? 3 : 4), 23 | 1: (code, c) => c, 24 | 6: (code, c) => 0, 25 | 7: (code, c) => 1, 26 | }; 27 | 28 | if (mapVerdictItoFnResult[verdictI]) { 29 | return mapVerdictItoFnResult[verdictI](exitCode, verdictC); 30 | } 31 | 32 | return verdictI; 33 | } 34 | 35 | function inputProcessing(lines) { 36 | const [exitCode, verdictI, verdictC] = lines.map(Number); 37 | 38 | return checkSystem(exitCode, verdictI, verdictC); 39 | } 40 | 41 | export default inputProcessing; 42 | -------------------------------------------------------------------------------- /june_2021/lesson_4/C.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27665/problems/C 2 | 3 | // Во входном файле (вы можете читать данные из файла input.txt) записан текст. Словом считается 4 | // последовательность непробельных символов идущих подряд, слова разделены одним или большим числом 5 | // пробелов или символами конца строки. Для каждого слова из этого текста подсчитайте, сколько раз 6 | // оно встречалось в этом тексте ранее. 7 | 8 | // Формат ввода 9 | // Вводится текст. 10 | 11 | // Формат вывода 12 | // Выведите ответ на задачу. 13 | 14 | import fs from 'fs'; 15 | 16 | // const fs = require('fs'); 17 | 18 | function inputProcessing() { 19 | const data = fs.readFileSync('input.txt', 'utf8'); 20 | const words = data.match(/[^\s\n]+/g); 21 | const mapWordToCount = {}; 22 | 23 | if (!words) { 24 | return ''; 25 | } 26 | for (const word of words) { 27 | if (!mapWordToCount[word]) { 28 | mapWordToCount[word] = 0; 29 | } 30 | mapWordToCount[word] += 1; 31 | } 32 | const mapCountToWord = {}; 33 | 34 | for (const [word, count] of Object.entries(mapWordToCount)) { 35 | if (!mapCountToWord[count]) { 36 | mapCountToWord[count] = []; 37 | } 38 | mapCountToWord[count].push(word); 39 | } 40 | const [, wordsMaxCount] = Object.entries(mapCountToWord).sort( 41 | ([countA], [countB]) => +countB - +countA 42 | )[0]; 43 | const wordsFreq = wordsMaxCount.sort((countA, countB) => 44 | String(countA).localeCompare(countB) 45 | ); 46 | const [wordMaxFreq] = wordsFreq; 47 | 48 | // console.log({ words, mapWordToCount, mapCountToWord, wordMaxFreq }); 49 | return wordMaxFreq; 50 | } 51 | 52 | process.stdout.write(String(inputProcessing())); 53 | -------------------------------------------------------------------------------- /september_2021_B/lesson_6/A.js: -------------------------------------------------------------------------------- 1 | const intDivision = (a, b) => Math.floor(a / b); 2 | 3 | const binarySearch = (leftInit = 0, rightInit, checkFn) => { 4 | let left = leftInit; 5 | let right = rightInit; 6 | 7 | while (left < right) { 8 | const middle = intDivision(left + right, 2); 9 | 10 | if (checkFn(middle)) { 11 | right = middle; 12 | } else { 13 | left = middle + 1; 14 | } 15 | } 16 | 17 | return left; 18 | }; 19 | 20 | /** 21 | * "A. Быстрый поиск в массиве" {@link "https://contest.yandex.ru/contest/29188/problems/A/} 22 | * 23 | * @param { Array } sortedNums отсортированный массив целых чисел от -10^9 до 10^9 24 | * @param { number } N длина массива 25 | * @param { number } l целые числа от -10^9 до 10^9 26 | * @param { number } r целые числа от -10^9 до 10^9 27 | * 28 | * @return { Array } для каждой пары LR чисел вывести “Сколько чисел имеют значения от L до R?” через пробел 29 | */ 30 | function howManyElementsBetweenLR(sortedNums, N, l, r) { 31 | const rIdx = binarySearch(0, N, (middleIndex) => sortedNums[middleIndex] > r); 32 | const lIdx = binarySearch( 33 | 0, 34 | N, 35 | (middleIndex) => sortedNums[middleIndex] >= l 36 | ); 37 | 38 | return rIdx - lIdx; 39 | } 40 | 41 | function inputProcessing(lines) { 42 | const N = Number(lines[0]); // 1-10^5 43 | const sortedNums = lines[1] 44 | .split(' ') 45 | .map(Number) 46 | .sort((a, b) => a - b); 47 | const K = Number(lines[2]); // 1-10^5 48 | const pairsLR = lines.slice(3, 3 + K).map((lr) => lr.split(' ').map(Number)); 49 | 50 | return pairsLR 51 | .map(([l, r]) => howManyElementsBetweenLR(sortedNums, N, l, r)) 52 | .join(' '); 53 | } 54 | 55 | export default inputProcessing; 56 | -------------------------------------------------------------------------------- /june_2021/lesson_1/F.js: -------------------------------------------------------------------------------- 1 | // В школе решили на один прямоугольный стол поставить два прямоугольных ноутбука. 2 | // Ноутбуки нужно поставить так, чтобы их стороны были параллельны сторонам стола. 3 | // Определите, какие размеры должен иметь стол, чтобы оба ноутбука на него поместились, и площадь стола была минимальна. 4 | 5 | // Формат ввода 6 | // Вводится четыре натуральных числа, первые два задают размеры одного ноутбука, а следующие два — размеры второго. Числа не превышают 1000. 7 | 8 | // Формат вывода 9 | // Выведите два числа — размеры стола. Если возможно несколько ответов, выведите любой из них (но только один). 10 | 11 | // import { input, output } from '../../input-output_dev.js'; 12 | 13 | function inputProcessing(lines) { 14 | const [x1, y1, x2, y2] = lines[0].split(' ').map(Number); 15 | // console.log({ x1, y1, x2, y2 }); 16 | 17 | const side1 = x1 + x2; 18 | const side2 = Math.max(y1, y2); 19 | 20 | const side3 = y1 + y2; 21 | const side4 = Math.max(x1, x2); 22 | 23 | const side5 = x1 + y2; 24 | const side6 = Math.max(x2, y1); 25 | 26 | const side7 = x2 + y1; 27 | const side8 = Math.max(x1, y2); 28 | 29 | const figures = { 30 | [side1 * side2]: [side1, side2], 31 | [side3 * side4]: [side3, side4], 32 | [side5 * side6]: [side5, side6], 33 | [side7 * side8]: [side7, side8], 34 | }; 35 | // console.log({ res }); 36 | const minAreaSides = figures[Math.min(...Object.keys(figures).map(Number))]; 37 | return minAreaSides; 38 | } 39 | 40 | (async () => { 41 | // const inputLines = await input(1); 42 | const inputLines = ['10 2 2 10']; 43 | console.log({ inputLines }); 44 | const outputLines = inputProcessing(inputLines); 45 | console.log({ outputLines }); 46 | // output(outputLines); 47 | })(); 48 | -------------------------------------------------------------------------------- /june_2021/lesson_3/G.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27663/problems/G 2 | 3 | // Широко известна следующая задача для младших школьников. Три черепахи ползут по дороге. Одна 4 | // черепаха говорит: “Впереди меня две черепахи”. Другая черепаха говорит: “Позади меня две 5 | // черепахи”. Третья черепаха говорит: “Впереди меня две черепахи и позади меня две черепахи”. Как 6 | // такое может быть? Ответ: третья черепаха врет! По дороге одна за другой движутся N черепах. 7 | // Каждая черепаха говорит фразу вида: “Впереди меня ai черепах, а позади меня bi черепах”. Ваша 8 | // задача определить, сколько самое большее количество черепах могут говорить правду. 9 | 10 | // Формат ввода 11 | // В первой строке вводится целое число N (1 ≤ N ≤ 10000) строк, содержащих целые числа ai и bi, по 12 | // модулю не превосходящие 10000, описывающие высказывание i-ой черепахи. 13 | 14 | // Формат вывода 15 | // Выведите целое число M – максимальное количество черепах, которые могут говорить правду. 16 | 17 | function inputProcessing(lines) { 18 | const [nRaw, ...rest] = lines; 19 | const N = Number(nRaw); 20 | const used = new Set(); 21 | const digits = rest.map((ab) => ab.split(' ').map(Number)); 22 | // console.log({ N, digits }); 23 | 24 | for (const [a, b] of digits) { 25 | if (a >= 0 && b >= 0 && a + b === N - 1 && !used.has(a)) { 26 | used.add(a); 27 | } 28 | } 29 | 30 | return used.size; 31 | } 32 | 33 | (async () => { 34 | // const inputLines = await input(1); 35 | // const inputLines = ['1 2 3', '1123']; 36 | const inputLines = ['3', '2 0', '0 2', '2 2']; 37 | 38 | console.log({ inputLines }); 39 | const outputLines = inputProcessing(inputLines); 40 | console.log({ outputLines }); 41 | // output(outputLines); 42 | })(); 43 | 44 | export default inputProcessing; 45 | -------------------------------------------------------------------------------- /june_2021/lesson_4/E.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27665/problems/E 2 | 3 | // Для строительство двухмерной пирамиды используются прямоугольные блоки, каждый из которых 4 | // характеризуется шириной и высотой. Можно поставить один блок на другой, только если ширина 5 | // верхнего блока строго меньше ширины нижнего. Самым нижним в пирамиде может быть блок любой 6 | // ширины. По заданному набору блоков определите, пирамиду какой наибольшей высоты можно построить 7 | // из них. 8 | 9 | // Формат ввода 10 | // В первой строке входных данных задается число 11 | // N — количество блоков (1 ≤ N ≤ 1 0 0 0 0 0 ). 12 | // В следующий N строках задаются пары натуральных чисел w и h 13 | // ( 1 ≤ w , h ≤ 1 0^ 9) — ширина и высота блока соответственно. 14 | 15 | // Формат вывода 16 | // Выведите одно целое число — максимальную высоту пирамиды. 17 | 18 | function inputProcessing(lines) { 19 | const [, ...blocksRaw] = lines; 20 | const blocks = blocksRaw.map((widthAndHeight) => 21 | widthAndHeight.split(' ').map(Number) 22 | ); 23 | 24 | const mapWidthToBlocks = {}; 25 | let sumHeight = 0; 26 | 27 | for (const [width, height] of blocks) { 28 | if (!mapWidthToBlocks[width]) { 29 | mapWidthToBlocks[width] = height; 30 | sumHeight += height; 31 | } else if (height > mapWidthToBlocks[width]) { 32 | sumHeight += height - mapWidthToBlocks[width]; 33 | mapWidthToBlocks[width] = height; 34 | } 35 | } 36 | 37 | return sumHeight; 38 | } 39 | 40 | (async () => { 41 | // const inputLines = await input(1); 42 | const inputLines = ['3', '3 1', '2 2', '3 3']; 43 | // const inputLines = input; 44 | console.log({ inputLines }); 45 | const outputLines = inputProcessing(inputLines); 46 | console.log({ outputLines }); 47 | // output(outputLines); 48 | })(); 49 | 50 | export default inputProcessing; 51 | -------------------------------------------------------------------------------- /june_2021/lesson_3/E.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27663/problems/E 2 | 3 | // В новой программе OpenCalculator появилась новая возможность – можно настроить, какие кнопки отображаются, а какие – нет. 4 | // Если кнопка не отображается на экране, то ввести соответствующую цифру с клавиатуры или копированием из другой программы нельзя. 5 | // Петя настроил калькулятор так, что он отображает только кнопки с цифрами x, y, z. 6 | // Напишите программу, определяющую, сможет ли Петя ввести число N, а если нет, 7 | // то какое минимальное количество кнопок надо дополнительно отобразить на экране для его ввода. 8 | 9 | // Формат ввода 10 | // Сначала вводятся три различных числа из диапазона от 0 до 9: x, y и z (числа разделяются пробелами). 11 | // Далее вводится целое неотрицательное число N, которое Петя хочет ввести в калькулятор.Число N не превышает 10000. 12 | 13 | // Формат вывода 14 | // Выведите, какое минимальное количество кнопок должно быть добавлено для того, 15 | // чтобы можно было ввести число N(если число может быть введено с помощью уже имеющихся кнопок, выведите 0) 16 | 17 | function inputProcessing(lines) { 18 | const xyz = new Set(lines[0].split(' ').map(Number)); 19 | const queryNumber = Number(lines[1]); 20 | const digits = new Set(String(queryNumber).split('').map(Number)); 21 | const tail = []; 22 | 23 | for (const num of digits) { 24 | if (!xyz.has(num)) { 25 | tail.push(num); 26 | } 27 | } 28 | 29 | return tail.length; 30 | } 31 | 32 | (async () => { 33 | // const inputLines = await input(1); 34 | // const inputLines = ['1 2 3', '1123']; 35 | const inputLines = ['5 7 3', '123']; 36 | 37 | console.log({ inputLines }); 38 | const outputLines = inputProcessing(inputLines); 39 | console.log({ outputLines }); 40 | // output(outputLines); 41 | })(); 42 | 43 | export default inputProcessing; 44 | -------------------------------------------------------------------------------- /june_2021/lesson_3/H.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27663/problems/H/ 2 | 3 | // Вы никогда не задумывались, почему в Angry Birds у птиц нет крыльев? Тем же вопросом задались разработчики новой игры. 4 | // В их версии смысл игры прямо противоположен Angry Birds: 5 | // зеленая свинка стреляет по злым птицам из лазерного ружья(завязка явно не хуже исходной игры). 6 | 7 | // Птицы в игре представляются точками на плоскости. Выстрел сбивает только ближайшую птицу 8 | // находящуюся на линии огня.При этом сбитая птица падая сбивает всех птиц, находящихся ровно под 9 | // ней. 10 | 11 | // Две птицы не могут находиться в одной точке.По заданному расположению птиц 12 | // необходимо определить, какое минимальное количество выстрелов необходимо, чтобы все птицы были сбиты. 13 | 14 | // Формат ввода 15 | // Первая строка входного файла содержит единственное целое число N (1 ≤ N ≤ 1000) — количество птиц. 16 | 17 | // Следующие N строк содержат по два натуральных числа каждая xi, yi — координаты i-ой птицы (0 < x, y ≤ 109). 18 | // Свинка находится в точке с координатами(0, 0). 19 | 20 | // Формат вывода 21 | // Единственная строка выходного файла должна содержать 22 | // одно целое число — минимальное количество выстрелов, необходимое для того, чтобы сбить всех птиц. 23 | 24 | function inputProcessing(lines) { 25 | const [, ...birdsXYRaw] = lines; 26 | // const N = Number(NRaw); // N (1 ≤ N ≤ 1000) 27 | 28 | const birdsXY = birdsXYRaw.map((xy) => xy.split(' ').map(Number)); 29 | 30 | return new Set(birdsXY.map(([x]) => x)).size; 31 | } 32 | 33 | (async () => { 34 | const inputLines = ['6', '1 1', '2 2', '3 3', '2 1', '3 2', '3 1']; 35 | // const inputLines = [6, '1 1', '2 2', '3 3', '2 1', '3 2', '3 4']; 36 | console.log({ inputLines }); 37 | 38 | const outputLines = inputProcessing(inputLines); 39 | console.log({ outputLines }); 40 | })(); 41 | 42 | export default inputProcessing; 43 | -------------------------------------------------------------------------------- /june_2021/lesson_1/G.js: -------------------------------------------------------------------------------- 1 | // Имеется N кг металлического сплава. Из него изготавливают заготовки массой K кг каждая. 2 | // После этого из каждой заготовки вытачиваются детали массой M кг каждая (из каждой заготовки вытачивают максимально возможное количество деталей). 3 | // Если от заготовок после этого что - то остается, то этот материал возвращают к началу производственного цикла и сплавляют с тем, 4 | // что осталось при изготовлении заготовок.Если того сплава, который получился, достаточно для изготовления хотя бы одной заготовки, 5 | // то из него снова изготавливают заготовки, из них – детали и т.д. 6 | // Напишите программу, которая вычислит, какое количество деталей может быть получено по этой технологии из имеющихся исходно N кг сплава. 7 | 8 | // Формат ввода 9 | // Вводятся N, K, M. Все числа натуральные и не превосходят 200. 10 | 11 | // Формат вывода 12 | // Выведите одно число — количество деталей, которое может получиться по такой технологии. 13 | 14 | // import { input, output } from '../../input-output_dev.js'; 15 | 16 | function inputProcessing(lines) { 17 | const [N, K, M] = lines[0].split(' ').map(Number); 18 | 19 | if (K < M) { 20 | return 0; 21 | } 22 | 23 | let tailFromParts = 0; 24 | let sum = N; 25 | let partsRes = 0; 26 | 27 | while (sum >= K) { 28 | const blanksCount = Math.floor(sum / K); 29 | sum -= blanksCount * K; 30 | 31 | const partsCount = Math.floor(K / M) * blanksCount; 32 | partsRes += partsCount; 33 | tailFromParts = (K % M) * blanksCount; 34 | sum += tailFromParts; 35 | } 36 | 37 | return String(partsRes); 38 | } 39 | 40 | // (async () => { 41 | // // const inputLines = await input(1); 42 | // const inputLines = ['30 5 7']; 43 | // console.log({ inputLines }); 44 | // const outputLines = inputProcessing(inputLines); 45 | // console.log({ outputLines }); 46 | // // output(outputLines); 47 | // })(); 48 | 49 | export default inputProcessing; 50 | -------------------------------------------------------------------------------- /june_2021/lesson_1/C.js: -------------------------------------------------------------------------------- 1 | // Телефонные номера в адресной книге мобильного телефона имеют один из следующих форматов: +7<код><номер> 8<код><номер> <номер> где <номер> — это семь цифр, а <код> — это три цифры или три цифры в круглых скобках. Если код не указан, то считается, что он равен 495. Кроме того, в записи телефонного номера может стоять знак “-” между любыми двумя цифрами (см. пример). На данный момент в адресной книге телефона Васи записано всего три телефонных номера, и он хочет записать туда еще один. Но он не может понять, не записан ли уже такой номер в телефонной книге. Помогите ему! Два телефонных номера совпадают, если у них равны коды и равны номера. Например, +7(916)0123456 и 89160123456 — это один и тот же номер. 2 | 3 | // Формат ввода 4 | // В первой строке входных данных записан номер телефона, который Вася хочет добавить в адресную книгу своего телефона. В следующих трех строках записаны три номера телефонов, которые уже находятся в адресной книге телефона Васи. Гарантируется, что каждая из записей соответствует одному из трех приведенных в условии форматов. 5 | 6 | // Формат вывода 7 | // Для каждого телефонного номера в адресной книге выведите YES (заглавными буквами), если он совпадает с тем телефонным номером, который Вася хочет добавить в адресную книгу или NO (заглавными буквами) в противном случае. 8 | 9 | import { input, output } from '../../input-output_dev.js'; 10 | 11 | function inputProcessing(lines) { 12 | const [basePhone, ...phones] = lines.map((phonesRaw) => 13 | phonesRaw.replace(/\D/g, '').padStart(11, '8495').slice(1) 14 | ); 15 | 16 | const result = phones.map((phone) => (phone === basePhone ? 'YES' : 'NO')); 17 | return result; 18 | } 19 | 20 | (async () => { 21 | const inputLines = await input(4); 22 | console.log({ inputLines }); 23 | const outputLines = inputProcessing(inputLines); 24 | console.log({ outputLines }); 25 | output(outputLines); 26 | })(); 27 | // 8(495)430-23-97 28 | // +7-4-9-5-43-023-97 29 | // 4-3-0-2-3-9-7 30 | // 8-495-430 31 | -------------------------------------------------------------------------------- /september_2021_B/lesson_2/B.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "B. Дома и магазины" {@link "https://contest.yandex.ru/contest/28738/problems/B/} 3 | * 4 | * @param { Array maxDistance) { 31 | maxDistance = distance; 32 | } 33 | } 34 | houseWithoutTwoShop = []; 35 | } 36 | 37 | prevShopIndex = index; 38 | break; 39 | } 40 | } 41 | 42 | for (const houseIndex of houseWithoutTwoShop) { 43 | const distance = Math.abs(houseIndex - prevShopIndex); 44 | 45 | if (distance > maxDistance) { 46 | maxDistance = distance; 47 | } 48 | } 49 | 50 | return maxDistance; 51 | } 52 | 53 | function inputProcessing(lines) { 54 | const nums = lines[0].split(' ').map(Number); 55 | 56 | return calcMaxDistanceFromHomeToShop(nums); 57 | } 58 | 59 | export default inputProcessing; 60 | -------------------------------------------------------------------------------- /september_2021_A/lesson_1/B.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './B.js'; 4 | 5 | describe('september_2021_A/lesson_1/B', () => { 6 | test('1', () => { 7 | assert.deepStrictEqual( 8 | fn(['3', '1 1 4 2 3 0 2 3', '1 1 5 2 2 3 3 0', '0 0 5 1 6 3 1 2']), 9 | ['YES', 'NO', 'YES'] 10 | ); 11 | }); 12 | 13 | test('2 from Bot', () => { 14 | assert.deepStrictEqual( 15 | fn(['2', '10 10 12 12 11 14 13 16', '10 10 20 9 19 19 9 20']), 16 | ['YES', 'YES'] 17 | ); 18 | }); 19 | 20 | test('8 from Bot. check self-intersecting', () => { 21 | assert.deepStrictEqual( 22 | fn([ 23 | '9', 24 | '100 100 -100 -100 -1 1 1 -1', 25 | '100 100 -1 1 1 -1 -100 -100', 26 | '100 100 -1 1 -100 -100 1 -1', 27 | '-10 -10 -14 -14 -11 -12 -12 -13', 28 | '-10 -10 -14 -14 -12 -13 -11 -12', 29 | '-10 -10 -11 -12 -14 -14 -12 -13', 30 | '-11 -5 -1 -5 0 0 -10 0', 31 | '-11 -5 0 0 -1 -5 -10 0', 32 | '-11 -5 -10 0 -1 -5 0 0', 33 | ]), 34 | [ 35 | 'YES', 36 | 'YES', 37 | 'YES', 38 | 'NO', 39 | 'NO', 40 | 'NO', 41 | 'YES', 42 | 'YES', 43 | 'YES', 44 | // 45 | ] 46 | ); 47 | }); 48 | 49 | test('10 from Bot', () => { 50 | assert.deepStrictEqual( 51 | fn([ 52 | '10', 53 | '0 0 -5 0 -10 0 -7 4', 54 | '0 0 -5 0 -7 4 -10 0 ', 55 | '-7 4 0 0 -5 0 -10 0', 56 | '0 0 10 0 10 0 5 5', 57 | '0 0 10 0 5 5 10 0', 58 | '10 0 0 0 10 0 5 5', 59 | '0 0 10 0 1 1 9 1', 60 | '0 0 10 0 9 1 1 1', 61 | '9 1 0 0 10 0 1 1', 62 | '0 0 5 0 1 1 6 1', 63 | ]), 64 | [ 65 | 'NO', 66 | 'NO', 67 | 'NO', 68 | 'NO', 69 | 'NO', 70 | 'NO', 71 | 'NO', 72 | 'NO', 73 | 'NO', 74 | 'YES', 75 | // 76 | ] 77 | ); 78 | }); 79 | }); 80 | -------------------------------------------------------------------------------- /september_2021_B/lesson_2/D.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "D. Лавочки в атриуме" {@link "https://contest.yandex.ru/contest/28738/problems/D/} 3 | * 4 | * @param { number } benchLength длина лавочки 1- 10 000 5 | * @param { number } leftCoordsBlock различных целых неотрицательных чисел, задающих положение 6 | * каждой ножки. Положение ножки определяется расстоянием от левого края плиты до левого края ножки 7 | * (ножка - это куб размером 1×1×1). Ножки перечислены слева направо (то есть начиная с ножки с 8 | * меньшим расстоянием до левого края). 9 | * 10 | * @return { string } Требуется перечислить ножки, которые студентам нужно оставить. Для каждой 11 | * ножки нужно выдать ее положение, как оно задано во входных данных. Ножки следует перечислять 12 | * слева направо, в том порядке, в котором они встречаются во входных данных. 13 | */ 14 | function calcWhichBlockStay(benchLength, leftCoordsBlock) { 15 | const minBlockNeed = benchLength % 2 === 0 ? 2 : 1; 16 | const setBlock = new Set(leftCoordsBlock); 17 | const centerIndex = Math.floor((benchLength - 1) / 2); 18 | let leftBlock = null; 19 | let rightBlock = null; 20 | 21 | for (let delta = 0; delta <= centerIndex + 1; delta++) { 22 | const indexL = centerIndex - delta; 23 | const indexR = centerIndex + delta; 24 | 25 | if (leftBlock === null && setBlock.has(indexL)) { 26 | if (minBlockNeed === 1 && indexL === centerIndex) { 27 | return `${indexL}`; 28 | } 29 | leftBlock = indexL; 30 | } 31 | if (rightBlock === null && indexR !== leftBlock && setBlock.has(indexR)) { 32 | rightBlock = indexR; 33 | } 34 | 35 | if (leftBlock !== null && rightBlock !== null) { 36 | break; 37 | } 38 | } 39 | 40 | return `${leftBlock} ${rightBlock}`; 41 | } 42 | 43 | function inputProcessing(lines) { 44 | const [benchLength] = lines[0].split(' ').map(Number); // ,blockCount 45 | const leftCoordsBlock = lines[1].split(' ').map(Number); 46 | 47 | return calcWhichBlockStay(benchLength, leftCoordsBlock); 48 | } 49 | 50 | export default inputProcessing; 51 | -------------------------------------------------------------------------------- /september_2021_B/lesson_6/B.js: -------------------------------------------------------------------------------- 1 | const intDivision = (a, b) => Math.floor(a / b); 2 | 3 | const binarySearch = (leftInit = 0, rightInit, checkFn) => { 4 | let left = leftInit; 5 | let right = rightInit; 6 | 7 | while (left < right) { 8 | const middle = intDivision(left + right, 2); 9 | 10 | if (checkFn(middle)) { 11 | right = middle; 12 | } else { 13 | left = middle + 1; 14 | } 15 | } 16 | 17 | return left; 18 | }; 19 | 20 | /** 21 | * "B. Номер левого и правого вхождения" 22 | * {@link "https://contest.yandex.ru/contest/29188/problems/B/} 23 | * 24 | * Требуется определить в заданном массиве номер самого левого и самого правого элемента, равного 25 | * искомому числу. 26 | * 27 | * @param { Array } sortedNums отсортированный массив целых чисел от -10^9 до 10^9 28 | * @param { number } N длина массива 29 | * @param { number } num целые числа от -10^9 до 10^9 30 | * 31 | * @return { [number, number]} Для каждого запроса выведите в через пробел два числа: номер 32 | * элемента самого левого и самого правого элементов массива, равных числу-запросу. Элементы 33 | * массива нумеруются с единицы. Если в массиве нет такого числа, выведите в соответствующей строке 34 | * два нуля, разделенных пробелом. 35 | */ 36 | function howManyElementsBetweenLR(sortedNums, N, num) { 37 | const rIdx = binarySearch( 38 | 0, 39 | N, 40 | (middleIndex) => sortedNums[middleIndex] > num 41 | ); 42 | const lIdx = binarySearch( 43 | 0, 44 | N, 45 | (middleIndex) => sortedNums[middleIndex] >= num 46 | ); 47 | 48 | if (rIdx === lIdx) { 49 | return [0, 0]; 50 | } 51 | return [lIdx + 1, rIdx + 1 - 1]; 52 | } 53 | 54 | function inputProcessing(lines) { 55 | const N = Number(lines[0]); // 1-10^5 56 | const sortedNums = lines[1].split(' ').map(Number); 57 | // const K = Number(lines[2]); // 1-10^5 58 | const queryNums = lines[3].split(' ').map(Number); 59 | 60 | return queryNums.map((num) => 61 | howManyElementsBetweenLR(sortedNums, N, num).join(' ') 62 | ); 63 | } 64 | 65 | export default inputProcessing; 66 | -------------------------------------------------------------------------------- /june_2021/lesson_6/A.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "A. Двоичный поиск" {@link "https://contest.yandex.ru/contest/27844/problems/A/} 3 | * 4 | * @param { Array } sortedArrN целые числа, каждое из которых по модулю не превосходит 10^9 5 | * @param { Array } arrayK целые числа, каждое из которых по модулю не превосходит 10^9 6 | * 7 | * @return { Array } для каждого из K чисел вывести в отдельную строку "YES", если это 8 | * число встречается в первом массиве, и "NO" в противном случае. 9 | */ 10 | const createBinarySearchIndexFn = (sortedNums, compareFn = (a, b) => a < b) => { 11 | const sortedNumsLength = sortedNums.length; 12 | 13 | return (num) => { 14 | let leftIndex = 0; 15 | let rightIndex = sortedNumsLength; 16 | let foundIndex = null; 17 | 18 | while (leftIndex < rightIndex) { 19 | const middleIndex = Math.floor((leftIndex + rightIndex) / 2); 20 | const middleEl = sortedNums[middleIndex]; 21 | 22 | if (num === middleEl) { 23 | foundIndex = middleIndex; 24 | break; 25 | } 26 | 27 | if (compareFn(num, middleEl)) { 28 | rightIndex = middleIndex; 29 | } else { 30 | leftIndex = middleIndex + 1; 31 | } 32 | } 33 | 34 | return foundIndex; 35 | }; 36 | }; 37 | 38 | function isHasElementArrayInOther(sortedArrN, arrayK) { 39 | const binarySearchIndex = createBinarySearchIndexFn( 40 | sortedArrN, 41 | (a, b) => a < b 42 | ); 43 | 44 | return arrayK.map((num) => (binarySearchIndex(num) !== null ? 'YES' : 'NO')); 45 | } 46 | 47 | function inputProcessing(lines) { 48 | // const [N, K] = lines[0].split(' ').map(Number); // 0-100_000 49 | const sortedArrN = lines[1].split(' ').map(Number); 50 | const arrayK = lines[2].split(' ').map(Number); 51 | 52 | return isHasElementArrayInOther(sortedArrN, arrayK); 53 | } 54 | 55 | export default inputProcessing; 56 | 57 | // через Set 58 | 59 | // function isHasElementArrayInOther(N, K, sortedArrN, arrayK) { 60 | // const set = new Set(sortedArrN); 61 | 62 | // return arrayK.map((num) => (set.has(num) ? 'YES' : 'NO')); 63 | // } 64 | -------------------------------------------------------------------------------- /september_2021_B/lesson_3/D.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './D.js'; 4 | 5 | describe('september_2021_B/lesson_3/D', () => { 6 | test('1', () => { 7 | assert.strictEqual( 8 | fn(['10', '1 2 3 4 5', 'YES', '2 4 6 8 10', 'NO', 'HELP']), 9 | '1 3 5' 10 | ); 11 | }); 12 | 13 | test('2', () => { 14 | assert.strictEqual( 15 | fn([ 16 | '10', 17 | '1 2 3 4 5 6 7 8 9 10', 18 | 'YES', 19 | '1', 20 | 'NO', 21 | '2', 22 | 'NO', 23 | '3', 24 | 'NO', 25 | '4', 26 | 'NO', 27 | '6', 28 | 'NO', 29 | '7', 30 | 'NO', 31 | '8', 32 | 'NO', 33 | '9', 34 | 'NO', 35 | '10', 36 | 'NO', 37 | 'HELP', 38 | ]), 39 | '5' 40 | ); 41 | }); 42 | 43 | test('3 BOT', () => { 44 | assert.strictEqual( 45 | fn([ 46 | '100', 47 | '3 5 8 10 11 13 14 15 16 20 21 23 25 27 29 31 32 33 35 42 43 46 47 48 51 52 57 58 67 68 72 74 75 76 79 80 81 82 83 84 86 89 90 91 92 93 94 95 96 99', 48 | 'YES', 49 | '1 4 7 9 14 16 17 19 20 23 25 27 28 29 30 31 32 33 41 42 45 46 48 50 52 54 59 60 61 63 66 67 68 69 70 71 73 74 79 81 82 83 89 90 91 92 93 94 95 100', 50 | 'YES', 51 | '3 5 6 15 16 18 19 20 21 22 23 24 26 28 29 35 37 38 39 40 41 43 44 45 46 47 53 55 56 60 61 63 64 65 68 70 71 73 76 79 80 81 82 83 86 90 91 95 96 99', 52 | 'YES', 53 | '1 2 3 5 11 16 17 23 25 31 32 33 34 35 38 39 41 43 44 46 47 49 51 53 58 59 62 63 68 69 70 72 73 74 76 77 78 79 80 81 82 83 85 86 93 94 95 97 99 100', 54 | 'YES', 55 | '3 7 8 9 10 14 17 20 22 23 24 25 26 27 28 30 34 40 42 43 45 47 48 49 50 51 52 53 54 55 59 62 63 66 67 72 73 75 77 81 83 84 86 89 92 93 94 96 98 100', 56 | 'YES', 57 | 'HELP', 58 | ]), 59 | '23 81 83' 60 | ); 61 | }); 62 | 63 | test('4 BOT~analog', () => { 64 | assert.strictEqual(fn(['10', '1 2 3 4 5 6 7 8', 'NO', 'HELP']), '9 10'); 65 | }); 66 | }); 67 | -------------------------------------------------------------------------------- /february_2023_B/lesson_1/6.js: -------------------------------------------------------------------------------- 1 | const calcWorkingOsCount = (segmentsCount, segments) => { 2 | let existedOS = []; 3 | 4 | for (const segment of segments) { 5 | const [beginNew, endNew] = segment; 6 | 7 | existedOS = existedOS.filter( 8 | ([begin, end]) => !(beginNew <= end && begin <= endNew) 9 | ); 10 | 11 | existedOS.push(segment); 12 | } 13 | 14 | return existedOS.length; 15 | }; 16 | 17 | /** 18 | * "6. Операционные системы lite" {@link "https://contest.yandex.ru/contest/45468/problems/6} 19 | * 20 | * Васин жесткий диск состоит из M секторов. Вася последовательно устанавливал на него различные 21 | * операционные системы следующим методом: он создавал новый раздел диска из последовательных 22 | * секторов, начиная с сектора номер ai и до сектора bi включительно, и устанавливал на него 23 | * очередную систему. При этом, если очередной раздел хотя бы по одному сектору пересекается с 24 | * каким-то ранее созданным разделом, то ранее созданный раздел «затирается», и операционная 25 | * система, которая на него была установлена, больше не может быть загружена. 26 | * Напишите программу, которая по информации о том, какие разделы на диске создавал Вася, 27 | * определит, сколько в итоге работоспособных операционных систем установлено и работает в 28 | * настоящий момент на Васином компьютере. 29 | * 30 | * @param { string[] } lines Сначала вводятся натуральное число M — количество секторов на жестком 31 | * диске (1 ≤ M ≤ 10^9) и целое число N — количество разделов, которое последовательно создавал Вася 32 | * (0 ≤ N ≤ 1000). Далее идут N пар чисел ai и bi, задающих номера начального и конечного секторов 33 | * раздела (1 ≤ ai ≤ bi ≤ M). 34 | * 35 | * @return { number } Выведите одно число — количество работающих операционных систем на Васином 36 | * компьютере. 37 | */ 38 | function inputProcessing(lines) { 39 | // const maxNumber = Number(lines[0]); 40 | const segmentsCount = Number(lines[1]); 41 | const segments = lines.slice(2).map((pair) => pair.split(' ').map(Number)); 42 | 43 | return calcWorkingOsCount(segmentsCount, segments); 44 | } 45 | 46 | export default inputProcessing; 47 | -------------------------------------------------------------------------------- /june_2021/lesson_5/B.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27794/problems/B 2 | 3 | // Вася очень любит везде искать своё счастливое число K . Каждый день он ходит в школу по улице, 4 | // вдоль которой припарковано N машин. Он заинтересовался вопросом, сколько существует наборов 5 | // машин, стоящих подряд на местах с L до R, что сумма их номеров равна K . Помогите Васе узнать 6 | // ответ на его вопрос. 7 | 8 | // Например, если число N = 5, K = 17, а номера машин равны 17, 7, 10, 7, 10, 9 | // то существует 4 набора машин: 10 | // 17 (L = 1, R = 1), 11 | // 7, 10 (L = 2, R = 3), 12 | // 10, 7 (L = 3, R = 4), 13 | // 7, 10 (L = 4, R = 5) 14 | 15 | // Формат ввода 16 | // В первой строке входных данных задаются числа N и K (1 ≤ N ≤ 100000, 1 ≤ K ≤ 10^9). 17 | // Во второй строке содержится N чисел, задающих номера машин. Номера машин могут принимать 18 | // значения от 1 до 999 включительно. 19 | 20 | // Формат вывода 21 | // Необходимо вывести одно число — количество наборов. 22 | 23 | // import fs from 'fs'; 24 | 25 | function inputProcessing(lines) { 26 | // сколько существует наборов машин, СТОЯЩИХ ПОДРЯД! номера которых составляют K 27 | const [N, K] = lines[0].split(' ').map(Number); // N и K (1 ≤ N ≤ 100000, 1 ≤ K ≤ 10^9) 28 | const nums = lines[1].split(' ').map(Number); 29 | 30 | let setsCount = 0; 31 | let leftIndex = 0; 32 | let sum = 0; 33 | 34 | for (let rightIndex = 0; rightIndex < N; rightIndex++) { 35 | sum += nums[rightIndex]; 36 | 37 | while (sum > K && leftIndex <= rightIndex) { 38 | sum -= nums[leftIndex]; 39 | leftIndex += 1; 40 | } 41 | 42 | if (sum === K) { 43 | setsCount += 1; 44 | } 45 | } 46 | 47 | return setsCount; 48 | } 49 | 50 | // (async () => { 51 | // // const inputLines = await input(1); 52 | // const inputLines = fs.readFileSync('input.txt', 'utf8').split('\r\n'); 53 | // // const inputLines = ['3', 'Hello Hi', 'Bye Goodbye', 'List Array', 'Goodbye']; 54 | // // const inputLines = input; 55 | // console.log({ inputLines }); 56 | // const outputLines = inputProcessing(inputLines); 57 | // console.log({ outputLines }); 58 | // // output(outputLines); 59 | // })(); 60 | 61 | export default inputProcessing; 62 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | .vscode 107 | input.txt 108 | output.txt 109 | /input.txt -------------------------------------------------------------------------------- /february_2023_B/lesson_1/9.js: -------------------------------------------------------------------------------- 1 | const calcMatrixSum = (matrix, queriesRectangleSum, N, M) => { 2 | const prefixSum = new Array(N).fill(null).map(() => new Array(M)); 3 | 4 | for (let x = 0; x < N; ++x) { 5 | for (let y = 0; y < M; ++y) { 6 | prefixSum[x][y] = 7 | matrix[x][y] + 8 | (prefixSum[x - 1]?.[y] ?? 0) + 9 | (prefixSum[x][y - 1] ?? 0) - // 10 | (prefixSum[x - 1]?.[y - 1] ?? 0); 11 | } 12 | } 13 | 14 | const res = []; 15 | let sum = 0; 16 | 17 | for (const rectangle of queriesRectangleSum) { 18 | const [x1, y1, x2, y2] = rectangle.map((n) => n - 1); 19 | 20 | sum = 21 | prefixSum[x2][y2] - 22 | (prefixSum[x1 - 1]?.[y2] ?? 0) - 23 | (prefixSum[x2][y1 - 1] ?? 0) + // 24 | (prefixSum[x1 - 1]?.[y1 - 1] ?? 0); 25 | 26 | res.push(sum); 27 | } 28 | 29 | return res; 30 | }; 31 | 32 | /** 33 | * "9. Сумма в прямоугольнике" {@link "https://contest.yandex.ru/contest/45468/problems/9} 34 | * 35 | * Вам необходимо ответить на запросы узнать сумму всех элементов числовой матрицы N×M в 36 | * прямоугольнике с левым верхним углом (x1, y1) и правым нижним (x2, y2) 37 | * 38 | * @param { string[] } lines В первой строке находится числа N, M размеры матрицы (1 ≤ N, M ≤ 1000) 39 | * и K — количество запросов (1 ≤ K ≤ 100000). Каждая из следующих N строк содержит по M чисел`— 40 | * элементы соответствующей строки матрицы (по модулю не превосходят 1000). Последующие K строк 41 | * содержат по 4 целых числа, разделенных пробелом x1 y1 x2 y2 — запрос на сумму элементов матрице 42 | * в прямоугольнике (1 ≤ x1 ≤ x2 ≤ N, 1 ≤ y1 ≤ y2 ≤ M) 43 | * 44 | * @return { string } Для каждого запроса на отдельной строке выведите его результат — сумму всех 45 | * чисел в элементов матрице в прямоугольнике (x1, y1), (x2, y2) 46 | */ 47 | function inputProcessing(lines) { 48 | // eslint-disable-next-line no-unused-vars 49 | const [N, M, K] = lines[0].split(' ').map(Number); 50 | const matrix = lines.slice(1, 1 + N).map((xy) => xy.split(' ').map(Number)); 51 | const queriesRectangleSum = lines 52 | .slice(1 + N) 53 | .map((xy) => xy.split(' ').map(Number)); 54 | 55 | return calcMatrixSum(matrix, queriesRectangleSum, N, M); 56 | } 57 | 58 | export default inputProcessing; 59 | -------------------------------------------------------------------------------- /september_2021_B/lesson_4/E.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict'; 2 | import { describe, test } from 'node:test'; 3 | import fn from './E.js'; 4 | 5 | describe('september_2021_B/lesson_4/E', () => { 6 | test('1', () => { 7 | assert.strictEqual( 8 | fn([ 9 | '7', 10 | '0', 11 | 'Олимпиада по информатике', 12 | 'Скоро третья командная олимпиада?', 13 | '0', 14 | 'Новая компьютерная игра', 15 | 'Вышла новая крутая игра!', 16 | '1', 17 | 'Она пройдет 24 ноября', 18 | '1', 19 | 'В Санкт-Петербурге и Барнауле', 20 | '2', 21 | 'Где найти?', 22 | '4', 23 | 'Примет участие более 50 команд', 24 | '6', 25 | 'Интересно, какие будут задачи', 26 | ]), 27 | 'Олимпиада по информатике' 28 | ); 29 | }); 30 | 31 | test('2', () => { 32 | assert.strictEqual(fn(['1', '0', 'topic 1', 'body 1']), 'topic 1'); 33 | }); 34 | 35 | test('My - cЕсли таких тем несколько, то выведите первую в хронологическом порядкеc', () => { 36 | assert.strictEqual( 37 | fn([ 38 | '4', 39 | '0', 40 | 'Олимпиада по информатике', 41 | 'Скоро третья командная олимпиада?', 42 | '0', 43 | 'Новая компьютерная игра', 44 | 'Вышла новая крутая игра!', 45 | '1', 46 | 'Она пройдет 24 ноября', 47 | '2', 48 | 'Где найти?', 49 | ]), 50 | 'Олимпиада по информатике' 51 | ); 52 | }); 53 | 54 | test('6 from bot ~ similar', () => { 55 | assert.strictEqual( 56 | fn([ 57 | '25', 58 | '0', 59 | 'topic 1', 60 | 'message_text', 61 | '1', 62 | 'message_text', 63 | '1', 64 | 'message_text', 65 | '2', 66 | 'message_text', 67 | '0', 68 | 'topic 2', 69 | 'message_text', 70 | '5', 71 | 'message_text', 72 | '0', 73 | 'topic 3', 74 | 'message_text', 75 | '4', 76 | 'message_text', 77 | '4', 78 | 'message_text', 79 | '2', 80 | 'message_text', 81 | '0', 82 | 'topic 4', 83 | ]), 84 | 'topic 1' 85 | ); 86 | }); 87 | }); 88 | -------------------------------------------------------------------------------- /february_2023_B/lesson_1/1.js: -------------------------------------------------------------------------------- 1 | const calcCharsOccurrence = (str) => { 2 | const mapCharToCounts = {}; 3 | 4 | for (const char of str) { 5 | if (!/\s/.test(char)) { 6 | mapCharToCounts[char] = (mapCharToCounts[char] ?? 0) + 1; 7 | } 8 | } 9 | return mapCharToCounts; 10 | }; 11 | 12 | const rotateArr270Degree = (input) => { 13 | const output = []; 14 | 15 | input.forEach((row, i) => { 16 | row.forEach((cell, j) => { 17 | output[row.length - j - 1] = output[row.length - j - 1] ?? []; 18 | output[row.length - j - 1][i] = cell; 19 | }); 20 | }); 21 | return output; 22 | }; 23 | 24 | /** 25 | * "1. Гистограмма" {@link "https://contest.yandex.ru/contest/45468/problems/1} 26 | * 27 | * @param { string } inputStr Ввод содержит строчные и прописные латинские буквы, цифры, знаки 28 | * препинания («.», «!», «?», «:», «-», «,», «;», «(», «)»), пробелы и переводы строк. Текст 29 | * содержит хотя бы один непробельный символ 30 | * 31 | * @return { string } Для каждого символа c кроме пробелов и переводов строк выведите столбик из символов «#», 32 | * количество которых должно быть равно количеству символов c в данном тексте. Под каждым 33 | * столбиком напишите символ, соответствующий ему. Отформатируйте гистограмму так, чтобы нижние 34 | * концы столбиков были на одной строке, первая строка и первый столбец были непустыми. 35 | * Отсортируйте столбики в порядке увеличения кодов символов. 36 | */ 37 | function inputProcessing(inputStr) { 38 | const mapCharToCounts = calcCharsOccurrence( 39 | Array.isArray(inputStr) ? inputStr.join('\n') : inputStr 40 | ); 41 | 42 | const charsWithCounts = Object.entries(mapCharToCounts).sort( 43 | (prev, next) => prev[0].charCodeAt() - next[0].charCodeAt() 44 | ); 45 | 46 | const maxCount = Math.max(...charsWithCounts.map(([, count]) => count)); 47 | 48 | const histogramArr = charsWithCounts.map(([char, count]) => [ 49 | ...`${char}${'#'.repeat(count)}`.padEnd(maxCount + 1, ' '), 50 | ]); 51 | 52 | const rotatedHistogramArr = rotateArr270Degree(histogramArr); 53 | 54 | const histogramTextDraw = rotatedHistogramArr 55 | .map((line) => line.join('')) 56 | .join('\n'); 57 | 58 | return histogramTextDraw; 59 | } 60 | 61 | export default inputProcessing; 62 | -------------------------------------------------------------------------------- /september_2021_B/lesson_3/D.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "D. Угадай число" {@link "https://contest.yandex.ru/contest/28964/problems/D} 3 | * 4 | * Август загадал натуральное число от 1 до maxPossibleNumber. 5 | * 6 | * @param { number } maxPossibleNumber наибольшее число,которое мог загадать Август 7 | * @param { Array } questionsAndAnswers идут строки, содержащие вопросы Беатрисы. 8 | * Каждая строка представляет собой набор чисел, разделенных пробелами. После каждой строки с 9 | * вопросом идет ответ Августа: YES или NO 10 | * 11 | * @return { string } вывести (через пробел, в порядке возрастания) все числа, которые мог задумать Август 12 | */ 13 | function guessPossibleNumber(maxPossibleNumber, questionsAndAnswers) { 14 | const possibleNumberByQuestions = new Map(); 15 | const unPossibleNumber = new Set(); 16 | let questionsYesCount = 0; 17 | 18 | for (let i = 0; i < questionsAndAnswers.length; i += 2) { 19 | const question = questionsAndAnswers[i].split(' ').map(Number); 20 | const answer = questionsAndAnswers[i + 1]; 21 | 22 | if (answer === 'YES') { 23 | question.forEach((num) => { 24 | if (num <= maxPossibleNumber) { 25 | possibleNumberByQuestions.set( 26 | num, 27 | (possibleNumberByQuestions.get(num) || 0) + 1 28 | ); 29 | } 30 | }); 31 | questionsYesCount += 1; 32 | } else { 33 | question.forEach((num) => { 34 | unPossibleNumber.add(num); 35 | }); 36 | } 37 | } 38 | 39 | const possibleNumber = new Set(); 40 | 41 | if (questionsYesCount > 0) { 42 | for (const [num, count] of possibleNumberByQuestions) { 43 | if (count >= questionsYesCount && !unPossibleNumber.has(num)) { 44 | possibleNumber.add(num); 45 | } 46 | } 47 | } else { 48 | for (let num = 1; num <= maxPossibleNumber; num++) { 49 | if (!unPossibleNumber.has(num)) { 50 | possibleNumber.add(num); 51 | } 52 | } 53 | } 54 | 55 | return [...possibleNumber].sort((a, b) => a - b).join(' '); 56 | } 57 | 58 | function inputProcessing(lines) { 59 | const maxPossibleNumber = Number(lines[0]); 60 | const questionsAndAnswersLines = lines.slice(1, lines.length - 1); 61 | 62 | return guessPossibleNumber(maxPossibleNumber, questionsAndAnswersLines); 63 | } 64 | export default inputProcessing; 65 | -------------------------------------------------------------------------------- /february_2023_B/lesson_1/3.js: -------------------------------------------------------------------------------- 1 | const intDivision = (a, b) => Math.floor(a / b); 2 | 3 | const binarySearch = (leftInit = 0, rightInit, checkFn) => { 4 | let left = leftInit; 5 | let right = rightInit; 6 | 7 | while (left < right) { 8 | const middle = intDivision(left + right, 2); 9 | 10 | if (checkFn(middle)) { 11 | right = middle; 12 | } else { 13 | left = middle + 1; 14 | } 15 | } 16 | 17 | return left; 18 | }; 19 | 20 | const fn = (diegoStickers, collectorsMinQueryNums) => { 21 | const setDiegoStickers = [...new Set(diegoStickers)].sort((a, b) => b - a); 22 | const { length: setLength } = setDiegoStickers; 23 | 24 | return collectorsMinQueryNums.map( 25 | (minQuery) => 26 | setLength - 27 | binarySearch( 28 | 0, 29 | setLength, 30 | (middleIndex) => minQuery > setDiegoStickers[middleIndex] 31 | ) 32 | ); 33 | }; 34 | 35 | /** 36 | * "3. Коллекционер Диего" {@link "https://contest.yandex.ru/contest/45468/problems/3} 37 | * 38 | * Красотой строки назовем максимальное число идущих подряд одинаковых букв. (красота строки 39 | * abcaabdddettq равна 3). Сделайте данную вам строку как можно более красивой, если вы можете 40 | * сделать не более k операций замены символа. 41 | * 42 | * @param { string[] } lines В 1-ой строке содержится единственное число N (0 ≤ N ≤ 100 000) — 43 | * количество наклеек у Диего. 44 | * Во 2-ой строке содержатся N целых неотрицательных чисел (не обязательно различных) — номера 45 | * наклеек Диего. Все номера наклеек не превосходят 10^9. 46 | * В 3-ей строке содержится число K (0 ≤ K ≤ 100 000) — количество коллекционеров, пришедших к 47 | * Диего. 48 | * В 4-ой строке содержатся K целых чисел pi (0 ≤ pi ≤ 10^9), где pi — наименьший номер 49 | * наклейки, не интересующий i-го коллекционера. 50 | * 51 | * @return { number } Для каждого коллекционера в отдельной строке выведите количество различных 52 | * чисел на наклейках, которые есть у Диего, но нет у этого коллекционера. 53 | */ 54 | function inputProcessing(lines) { 55 | // const N = Number(lines[0]); 56 | const diegoStickers = lines[1].split(' ').map(Number); 57 | // const K = Number(lines[2]); 58 | const collectorsMinQueryNums = lines[3].split(' ').map(Number); 59 | 60 | return fn(diegoStickers, collectorsMinQueryNums); 61 | } 62 | 63 | export default inputProcessing; 64 | -------------------------------------------------------------------------------- /june_2021/lesson_2/H.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27472/problems/G/ 2 | 3 | // Дан список, заполненный произвольными целыми числами. 4 | // Найдите в этом списке два числа, произведение которых максимально. 5 | // Выведите эти числа в порядке неубывания. 6 | 7 | // Список содержит не менее двух элементов. Числа подобраны так, что ответ однозначен. 8 | 9 | // Решение должно иметь сложность O(n), где n - размер списка. 10 | 11 | // Пример 12 | // -4 3 -5 2 5 // ввод 13 | // -5 -4 // вывод 14 | 15 | function inputProcessing(lines) { 16 | const list = lines[0] 17 | .split(' ') 18 | .map(Number) 19 | .sort((a, b) => b - a); 20 | 21 | // const seq = [list[0], list[1], list[2]].sort((a, b) => b - a); 22 | const { length } = list; 23 | const seq = [ 24 | list[0], 25 | list[1], 26 | list[2], 27 | list[length >= 4 ? length - 1 - 0 : length] ?? null, 28 | list[length >= 5 ? length - 1 - 1 : length] ?? null, 29 | list[length >= 6 ? length - 1 - 2 : length] ?? null, 30 | ]; 31 | 32 | const nums = seq; 33 | // console.log(nums); 34 | // console.log({ max1, max2, max3, min1, min2, min3 }); 35 | let maxProduct = Number.NEGATIVE_INFINITY; 36 | let queryNums = []; 37 | 38 | for (let x = 0; x < nums.length; x++) { 39 | for (let y = 0; y < nums.length; y++) { 40 | if (x !== y) { 41 | for (let z = 0; z < nums.length; z++) { 42 | if ( 43 | y !== z && 44 | x !== z && 45 | nums[x] !== null && 46 | nums[y] !== null && 47 | nums[z] !== null 48 | ) { 49 | const product = nums[x] * nums[y] * nums[z]; 50 | // console.log([nums[x], nums[y], nums[z]], { product }); 51 | if (product > maxProduct) { 52 | maxProduct = product; 53 | queryNums = [nums[x], nums[y], nums[z]]; 54 | } 55 | } 56 | } 57 | } 58 | } 59 | } 60 | // console.log({ max1, max2, max3, min1, min2, min3 }); 61 | // console.log(maxProduct, queryNums); 62 | return queryNums.sort((a, b) => a - b).join(' '); 63 | } 64 | 65 | (async () => { 66 | const inputLines = ['-5 -30000 -12 0 1']; 67 | console.log({ inputLines }); 68 | 69 | const outputLines = inputProcessing(inputLines); 70 | console.log({ outputLines }); 71 | })(); 72 | 73 | export default inputProcessing; 74 | -------------------------------------------------------------------------------- /september_2021_A/lesson_1/B.js: -------------------------------------------------------------------------------- 1 | const getDist = (a, b) => Math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2); 2 | const getVector = (a, b) => ({ x: a.x - b.x, y: a.y - b.y }); 3 | 4 | const isParallelogram = (a, b, c, d) => { 5 | const length = { 6 | ab: getDist(b, a), 7 | cd: getDist(d, c), 8 | bc: getDist(c, b), 9 | da: getDist(a, d), 10 | }; 11 | const vector = { 12 | ab: getVector(b, a), 13 | cd: getVector(d, c), 14 | bc: getVector(c, b), 15 | da: getVector(a, d), 16 | }; 17 | 18 | return ( 19 | length.ab === length.cd && 20 | length.bc === length.da && 21 | vector.ab.x * vector.cd.y === vector.ab.y * vector.cd.x && 22 | vector.bc.x * vector.da.y === vector.bc.y * vector.da.x 23 | ); 24 | }; 25 | 26 | /** 27 | * "B. Параллелограмм" {@link "https://contest.yandex.ru/contest/28724/problems/B/} 28 | * 29 | * Гарантируется, что четыре точки, о которых идет речь в одном вопросе, не лежат на одной прямой. 30 | * 31 | * @param { Array<{ x:number, y:number }> } coords (a,b,c,d) четыре точки - два целых числа X и Y 32 | * (−100 ≤ X ≤ 100, −100 ≤ Y ≤ 100), обозначающих координаты точки. 33 | * 34 | * @return { Array<"YES"|"NO"> } Для каждого из вопросов выведите "YES", если четыре заданные точки 35 | * могут образовать параллелограмм, и "NO" в противном случае. Ответ на каждый из запросов должен 36 | * быть в отдельной строке без кавычек. 37 | */ 38 | function isParallelogramExistByCoords(coords) { 39 | for (let i = 0; i < 4; i++) { 40 | for (let j = i; j < 4; j++) { 41 | const newCoords = coords.slice(); 42 | const temp = newCoords[i]; 43 | newCoords[i] = newCoords[j]; 44 | newCoords[j] = temp; 45 | 46 | if (isParallelogram(...newCoords)) { 47 | return 'YES'; 48 | } 49 | } 50 | } 51 | 52 | return 'NO'; 53 | } 54 | 55 | function inputProcessing(lines) { 56 | const count = lines[0]; 57 | const result = []; 58 | 59 | for (let i = 1; i <= count; i++) { 60 | const pointsRaw = lines[i].split(/\s+/).map(Number); 61 | const points = []; 62 | 63 | for (let n = 0; n < pointsRaw.length; n += 2) { 64 | const point = { x: pointsRaw[n], y: pointsRaw[n + 1] }; 65 | points.push(point); 66 | } 67 | 68 | result.push(isParallelogramExistByCoords(points)); 69 | } 70 | 71 | return result; 72 | } 73 | 74 | export default inputProcessing; 75 | -------------------------------------------------------------------------------- /september_2021_B/lesson_3/E.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "E. Автомобильные номера" {@link "https://contest.yandex.ru/contest/28964/problems/E} 3 | * 4 | * Номер согласуется с показанием свидетеля, если все символы, которые назвал свидетель, 5 | * присутствуют в этом номере (не важно, сколько раз). 6 | * 7 | * @param { number } countWitnesses количество свидетелей (<= 100) 8 | * @param { Array } numbersFromWitnessTestimony показания очередного свидетеля. Строки 9 | * непустые и состоят из не более чем 20 символов, символы могут повторяться 10 | * @param { number } countCarNumbers количество номеров (<= 100) 11 | * @param { Array } numbersOfSuspected номера подозреваемых машин (имеют такой же формат, 12 | * как и показания свидетелей) 13 | * 14 | * @return { Array } Выпишите номера автомобилей, согласующиеся с максимальным количеством 15 | * свидетелей. Если таких номеров несколько, то выведите их в том же порядке, в котором они были 16 | * заданы на входе 17 | */ 18 | function guessPossibleNumber( 19 | countWitnesses, 20 | numbersFromWitnessTestimony, 21 | countCarNumbers, 22 | numbersOfSuspected 23 | ) { 24 | const witnessTestimonySets = numbersFromWitnessTestimony.map((numbers) => [ 25 | ...new Set(numbers), 26 | ]); 27 | const suspectedNumberCountWitness = new Array(countCarNumbers).fill(0); 28 | 29 | let max = 0; 30 | 31 | for (let m = 0; m < countWitnesses; m++) { 32 | for (let n = 0; n < countCarNumbers; n++) { 33 | if ( 34 | witnessTestimonySets[m].every((char) => 35 | numbersOfSuspected[n].includes(char) 36 | ) 37 | ) { 38 | suspectedNumberCountWitness[n] += 1; 39 | 40 | if (suspectedNumberCountWitness[n] > max) { 41 | max = suspectedNumberCountWitness[n]; 42 | } 43 | } 44 | } 45 | } 46 | 47 | return numbersOfSuspected.filter( 48 | (carNumber, i) => suspectedNumberCountWitness[i] === max 49 | ); 50 | } 51 | 52 | function inputProcessing(lines) { 53 | const countWitnesses = Number(lines[0]); 54 | const numbersFromWitnessTestimony = lines.slice(1, countWitnesses + 1); 55 | 56 | const countCarNumbers = Number(lines[countWitnesses + 1]); 57 | const numbersOfSuspected = lines.slice(1 + countWitnesses + 1); 58 | 59 | return guessPossibleNumber( 60 | countWitnesses, 61 | numbersFromWitnessTestimony, 62 | countCarNumbers, 63 | numbersOfSuspected 64 | ); 65 | } 66 | 67 | export default inputProcessing; 68 | -------------------------------------------------------------------------------- /june_2021/lesson_3/I.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27663/problems/I/ 2 | 3 | // Каждый из N школьников некоторой школы знает M языков. Определите, какие языки знают все 4 | // школьники и языки, которые знает хотя бы один из школьников. 5 | 6 | // Формат ввода Первая строка входных данных содержит количество школьников N. Далее идет N чисел M, 7 | // после каждого из чисел идет Mi строк, содержащих названия языков, которые знает i-й 8 | // школьник. Длина названий языков не превышает 1000 символов, количество различных языков не более 9 | // 1000. 1 ≤ N ≤ 1000, 1 ≤ Mi ≤ 500. 10 | 11 | // Формат вывода В первой строке выведите количество языков, которые знают все школьники. Начиная 12 | // со второй строки - список таких языков. Затем - количество языков, которые знает хотя бы один 13 | // школьник, на следующих строках - список таких языков. 14 | 15 | function inputProcessing(lines) { 16 | const N = Number(lines[0]); // школьники 17 | 18 | const studentsLanguages = []; 19 | 20 | for (let i = 1; i < lines.length; i++) { 21 | const M = Number(lines[i]); 22 | 23 | if (Number.isInteger(M)) { 24 | studentsLanguages.push(lines.slice(i + 1, i + 1 + M)); 25 | } 26 | } 27 | 28 | const mapLanguageToCount = {}; 29 | const atLeastOneStudentLang = []; 30 | const everyStudentLang = []; 31 | 32 | for (const studentLangs of studentsLanguages) { 33 | for (const lang of studentLangs) { 34 | if (!mapLanguageToCount[lang]) { 35 | mapLanguageToCount[lang] = 0; 36 | } 37 | mapLanguageToCount[lang] += 1; 38 | 39 | if (mapLanguageToCount[lang] === 1) { 40 | atLeastOneStudentLang.push(lang); 41 | } 42 | if (mapLanguageToCount[lang] === N) { 43 | everyStudentLang.push(lang); 44 | } 45 | } 46 | } 47 | 48 | // console.log({ mapLanguageToCount, atLeastOneStudentLang, everyStudentLang }); 49 | 50 | return [ 51 | everyStudentLang.length, 52 | ...everyStudentLang, 53 | atLeastOneStudentLang.length, 54 | ...atLeastOneStudentLang, 55 | ]; 56 | } 57 | 58 | (async () => { 59 | const inputLines = [ 60 | '3', 61 | '3', 62 | 'Russian', 63 | 'English', 64 | 'Japanese', 65 | '2', 66 | 'Russian', 67 | 'English', 68 | '1', 69 | 'English', 70 | ]; 71 | console.log({ inputLines }); 72 | 73 | const outputLines = inputProcessing(inputLines); 74 | console.log({ outputLines }); 75 | })(); 76 | 77 | export default inputProcessing; 78 | -------------------------------------------------------------------------------- /september_2021_B/lesson_4/E.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "E. Форум" {@link "https://contest.yandex.ru/contest/28970/problems/E/} 3 | * 4 | * Форум имеет следующую структуру: каждое сообщение либо начинает новую тему, либо является 5 | * ответом на какое-либо предыдущее сообщение и принадлежит той же теме. 6 | * 7 | * @param { string[] } text строки содержат описание сообщений в хронологическом порядке. Описание 8 | * сообщения, которое представляет собой начало новой темы, состоит из трех строк. Первая строка 9 | * содержит число 0. Вторая строка содержит название темы. Длина названия не превышает 30 символов. 10 | * Третья строка содержит текст сообщения. 11 | * 12 | * @return { string } Выведите название темы, к которой относится наибольшее количество 13 | * сообщений. Если таких тем несколько, то выведите первую в хронологическом порядке 14 | */ 15 | function calcMostPopularTopic(text) { 16 | const mapTopicIdToTitle = new Map(); 17 | const mapTopicIdToMessageCount = new Map(); 18 | const mapMessageIndexToRelatedTopicId = new Map(); 19 | let messageIndex = 0; 20 | let topicId = 0; 21 | 22 | for (let i = 0; i < text.length; i += 1) { 23 | const line = Number(text[i]); 24 | 25 | if (Number.isNaN(line)) { 26 | continue; 27 | } 28 | messageIndex += 1; 29 | 30 | if (line === 0) { 31 | topicId += 1; 32 | const topic = text[i + 1]; 33 | mapMessageIndexToRelatedTopicId.set(messageIndex, topicId); 34 | mapTopicIdToTitle.set(topicId, topic); 35 | 36 | mapTopicIdToMessageCount.set(topicId, 0); 37 | } else { 38 | const topicIdAssociatedWithThisMessage = 39 | mapMessageIndexToRelatedTopicId.get(line); 40 | mapMessageIndexToRelatedTopicId.set( 41 | messageIndex, 42 | topicIdAssociatedWithThisMessage 43 | ); 44 | 45 | mapTopicIdToMessageCount.set( 46 | topicIdAssociatedWithThisMessage, 47 | mapTopicIdToMessageCount.get(topicIdAssociatedWithThisMessage) + 1 48 | ); 49 | } 50 | } 51 | 52 | const maxAnswerToTopic = Math.max(...[...mapTopicIdToMessageCount.values()]); 53 | const [mostPopularTopicId] = [...mapTopicIdToMessageCount].find( 54 | ([, count]) => count === maxAnswerToTopic 55 | ); 56 | 57 | return mapTopicIdToTitle.get(mostPopularTopicId); 58 | } 59 | 60 | function inputProcessing(lines) { 61 | const messages = lines.slice(1); 62 | 63 | return calcMostPopularTopic(messages); 64 | } 65 | 66 | export default inputProcessing; 67 | -------------------------------------------------------------------------------- /june_2021/lesson_3/C.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27663/problems/C 2 | 3 | // Аня и Боря любят играть в разноцветные кубики, причем у каждого из них свой набор и в каждом наборе все кубики различны по цвету. 4 | // Однажды дети заинтересовались, сколько существуют цветов таких, что кубики каждого цвета присутствуют в обоих наборах. 5 | // Для этого они занумеровали все цвета случайными числами. 6 | // На этом их энтузиазм иссяк, поэтому вам предлагается помочь им в оставшейся части. 7 | // Номер любого цвета — это целое число в пределах от 0 до 10^9. 8 | 9 | // Формат ввода 10 | // В первой строке входного файла записаны числа N и M — количество кубиков у Ани и Бори соответственно. 11 | // В следующих N строках заданы номера цветов кубиков Ани. 12 | // В последних M строках номера цветов кубиков Бори. 13 | 14 | // Формат вывода 15 | // Выведите сначала количество, 16 | // а затем отсортированные по возрастанию номера цветов таких, что кубики каждого цвета есть в обоих наборах, 17 | 18 | // затем количество 19 | // и отсортированные по возрастанию номера остальных цветов у Ани, 20 | // потом количество 21 | // и отсортированные по возрастанию номера остальных цветов у Бори. 22 | 23 | function inputProcessing(lines) { 24 | // eslint-disable-next-line no-unused-vars 25 | const [N, M] = lines[0].split(' ').map(Number); 26 | const set1 = new Set(lines.slice(1, N + 1).map(Number)); 27 | const set2 = new Set(lines.slice(1 + N).map(Number)); 28 | 29 | const intersection = []; 30 | const tail1 = []; 31 | const tail2 = []; 32 | 33 | for (const num of set1) { 34 | if (set2.has(num)) { 35 | intersection.push(num); 36 | } else { 37 | tail1.push(num); 38 | } 39 | } 40 | for (const num of set2) { 41 | if (!set1.has(num)) { 42 | tail2.push(num); 43 | } 44 | } 45 | 46 | return [ 47 | intersection.length, 48 | intersection.sort((a, b) => a - b).join(' '), 49 | tail1.length, 50 | tail1.sort((a, b) => a - b).join(' '), 51 | tail2.length, 52 | tail2.sort((a, b) => a - b).join(' '), 53 | ]; 54 | } 55 | 56 | (async () => { 57 | // const inputLines = await input(1); 58 | // const inputLines = ['4 3', '0', '1', '10', '9', '1', '3', '0']; 59 | // const inputLines = ['2 2', '1', '2', '2', '3']; 60 | const inputLines = ['0 0']; 61 | 62 | console.log({ inputLines }); 63 | const outputLines = inputProcessing(inputLines); 64 | console.log({ outputLines }); 65 | // output(outputLines); 66 | })(); 67 | 68 | export default inputProcessing; 69 | -------------------------------------------------------------------------------- /june_2021/lesson_1/A.js: -------------------------------------------------------------------------------- 1 | // В офисе, где работает программист Петр, установили кондиционер нового типа. 2 | // Этот кондиционер отличается особой простотой в управлении. 3 | // У кондиционера есть всего лишь два управляемых параметра: желаемая температура и режим работы. 4 | 5 | // Кондиционер может работать в следующих четырех режимах: 6 | 7 | // «freeze» — охлаждение.В этом режиме кондиционер может только уменьшать температуру. Если температура в комнате и так не больше желаемой, то он выключается. 8 | // «heat» — нагрев.В этом режиме кондиционер может только увеличивать температуру .Если температура в комнате и так не меньше желаемой, то он выключается. 9 | // «auto» — автоматический режим.В этом режиме кондиционер может как увеличивать, так и уменьшать температуру в комнате до желаемой. 10 | // «fan» — вентиляция.В этом режиме кондиционер осуществляет только вентиляцию воздуха и не изменяет температуру в комнате. 11 | 12 | // Кондиционер достаточно мощный, поэтому при настройке на правильный режим работы он за час доводит температуру в комнате до желаемой. 13 | 14 | // Требуется написать программу, которая по заданной температуре в комнате troom, 15 | // установленным на кондиционере желаемой температуре tcond и режиму работы определяет температуру, которая установится в комнате через час. 16 | 17 | // Формат ввода 18 | // Первая строка входного файла содержит два целых числа troom, и tcond, разделенных ровно одним пробелом(–50 ≤ troom ≤ 50, –50 ≤ tcond ≤ 50). 19 | // Вторая строка содержит одно слово, записанное строчными буквами латинского алфавита — режим работы кондиционера. 20 | 21 | // Формат вывода 22 | // Выходной файл должен содержать одно целое число — температуру, которая установится в комнате через час. 23 | 24 | import { input, output } from '../../input-output_dev.js'; 25 | 26 | function inputProcessing(lines) { 27 | const [temp, mode] = lines; 28 | const [tRoomInput, tCondInput] = temp.split(' '); 29 | 30 | const mapModeToFn = { 31 | freeze: (tRoom, tCond) => (tRoom > tCond ? tCond : tRoom), 32 | heat: (tRoom, tCond) => (tRoom < tCond ? tCond : tRoom), 33 | auto: (tRoom, tCond) => tCond, 34 | fan: (tRoom, tCond) => tRoom, 35 | }; 36 | 37 | const tempAfter = mapModeToFn[mode](Number(tRoomInput), Number(tCondInput)); 38 | 39 | return [tempAfter]; 40 | } 41 | 42 | (async () => { 43 | const inputLines = await input(2); 44 | console.log({ inputLines }); 45 | const outputLines = [inputProcessing(inputLines)]; 46 | console.log({ outputLines }); 47 | output(outputLines); 48 | })(); 49 | -------------------------------------------------------------------------------- /june_2021/lesson_6/B.js: -------------------------------------------------------------------------------- 1 | const createBinarySearchIndexFn = (sortedNums, compareFn = (a, b) => a < b) => { 2 | const sortedNumsLength = sortedNums.length; 3 | 4 | return (num) => { 5 | let leftIndex = 0; 6 | let rightIndex = sortedNumsLength; 7 | let foundIndex = null; 8 | 9 | while (leftIndex < rightIndex) { 10 | const middleIndex = Math.floor((leftIndex + rightIndex) / 2); 11 | const middleEl = sortedNums[middleIndex]; 12 | 13 | if (num === middleEl) { 14 | foundIndex = middleIndex; 15 | break; 16 | } 17 | 18 | if (compareFn(num, middleEl)) { 19 | rightIndex = middleIndex; 20 | } else { 21 | leftIndex = middleIndex + 1; 22 | } 23 | } 24 | 25 | return foundIndex !== null ? foundIndex : [leftIndex, leftIndex - 1]; // возвращаем еще и предыдущий индекс 26 | }; 27 | }; 28 | 29 | /** 30 | * "B. Приближенный двоичный поиск" {@link "https://contest.yandex.ru/contest/27844/problems/B/} 31 | * 32 | * @param { Array } sortedArrN целые числа, отсортированные по неубыванию 33 | * @param { Array } arrayK целые числа, каждое из которых по модулю не превосходит 10^9 34 | * 35 | * @return { Array } для каждого из K чисел выведите в отдельную строку число из первого 36 | * массива, наиболее близкое к данному. Если таких несколько, выведите меньшее из них. 37 | */ 38 | function searchNearestNumber(sortedArrN, arrayK) { 39 | const binarySearchIndex = createBinarySearchIndexFn( 40 | sortedArrN, 41 | (a, b) => a < b 42 | ); 43 | const getDelta = (primaryNum, num) => Math.abs(num - primaryNum); 44 | 45 | return arrayK.map((num) => { 46 | const foundIndex = binarySearchIndex(num); 47 | 48 | if (Number.isInteger(foundIndex)) { 49 | return sortedArrN[foundIndex]; 50 | } 51 | 52 | const [indexRight, indexLeft] = foundIndex; 53 | const [valueRight, valueLeft] = [ 54 | sortedArrN[indexRight], 55 | sortedArrN[indexLeft], 56 | ]; 57 | 58 | if (indexLeft < 0) { 59 | return valueRight; 60 | } 61 | if (indexRight >= sortedArrN.length) { 62 | return valueLeft; 63 | } 64 | 65 | return getDelta(valueRight, num) < getDelta(valueLeft, num) 66 | ? valueRight 67 | : valueLeft; 68 | }); 69 | } 70 | 71 | function inputProcessing(lines) { 72 | // const [N, K] = lines[0].split(' ').map(Number); // 0-100_001 73 | 74 | const sortedArrN = lines[1].split(' ').map(Number); 75 | const arrayK = lines[2].split(' ').map(Number); 76 | 77 | return searchNearestNumber(sortedArrN, arrayK); 78 | } 79 | 80 | export default inputProcessing; 81 | -------------------------------------------------------------------------------- /february_2023_B/lesson_1/2.js: -------------------------------------------------------------------------------- 1 | const ALPHABET_LOWERCASE = 'abcdefghijklmnopqrstuvwxyz'; 2 | 3 | /** complexity - O(n^2) */ 4 | const twoPointerAlgorithm = (availableReplaceCount, string, pivotChar) => { 5 | let replaceCount = 0; 6 | let maxBeauty = 0; 7 | const textLength = string.length; 8 | 9 | for ( 10 | let leftIndex = 0, rightIndex = 0; 11 | leftIndex < textLength; 12 | leftIndex += 1 13 | ) { 14 | while (rightIndex < textLength) { 15 | if (string[rightIndex] !== pivotChar) { 16 | if (replaceCount >= availableReplaceCount) { 17 | break; 18 | } 19 | 20 | replaceCount += 1; 21 | } 22 | 23 | rightIndex += 1; 24 | } 25 | 26 | if (string[leftIndex] !== pivotChar) { 27 | replaceCount -= 1; 28 | } 29 | 30 | const currentBeauty = rightIndex - leftIndex; 31 | if (currentBeauty > maxBeauty) { 32 | maxBeauty = currentBeauty; 33 | } 34 | 35 | if (rightIndex === textLength - 1) { 36 | break; 37 | } 38 | } 39 | return maxBeauty; 40 | }; 41 | 42 | const maxLengthConsecutiveCharactersAfterXReplace = ( 43 | availableReplaceCount, 44 | string, 45 | alphabet = ALPHABET_LOWERCASE 46 | ) => { 47 | let maxBeauty = 0; 48 | 49 | for ( 50 | let alphabetIndex = 0; 51 | alphabetIndex < alphabet.length; 52 | alphabetIndex += 1 53 | ) { 54 | const pivotChar = alphabet[alphabetIndex]; 55 | 56 | const maxBeautyByChar = twoPointerAlgorithm( 57 | availableReplaceCount, 58 | string, 59 | pivotChar 60 | ); 61 | if (maxBeautyByChar > maxBeauty) { 62 | maxBeauty = maxBeautyByChar; 63 | } 64 | } 65 | 66 | return maxBeauty; 67 | }; 68 | 69 | /** 70 | * "2. Красивая строка" {@link "https://contest.yandex.ru/contest/45468/problems/2} 71 | * 72 | * Красотой строки назовем максимальное число идущих подряд одинаковых букв. (красота строки 73 | * abcaabdddettq равна 3). Сделайте данную вам строку как можно более красивой, если вы можете 74 | * сделать не более k операций замены символа. 75 | * 76 | * @param { string[] } lines В первой строке записано одно целое число k (0 ≤ k ≤ 10^9). Во второй 77 | * строке дана непустая строчка S (|S| ≤ 2*10^5). Строчка S состоит только из маленьких латинских 78 | * букв. 79 | * 80 | * @return { number } Выведите одно число — максимально возможную красоту строчки, которую можно 81 | * получить. 82 | */ 83 | function inputProcessing(lines) { 84 | const k = Number(lines[0]); 85 | const string = lines[1]; 86 | 87 | return maxLengthConsecutiveCharactersAfterXReplace(k, string); 88 | } 89 | 90 | export default inputProcessing; 91 | -------------------------------------------------------------------------------- /june_2021/lesson_4/D.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27665/problems/D 2 | 3 | // На региональном этапе Всероссийской олимпиады школьников по информатике в 2009 году предлагалась 4 | // следующая задача. 5 | 6 | // Всем известно, что со временем клавиатура изнашивается,и клавиши на ней начинают залипать. 7 | // Конечно, некоторое время такую клавиатуру еще можно использовать, но для нажатий клавиш 8 | // приходиться использовать большую силу. 9 | 10 | // При изготовлении клавиатуры изначально для каждой клавиши задается количество нажатий,которое 11 | // она должна выдерживать. Если знать эти величины для используемой клавиатуры,то для определенной 12 | // последовательности нажатых клавиш можно определить,какие клавиши в процессе их использования 13 | // сломаются, а какие — нет. 14 | 15 | // Требуется написать программу, определяющую, какие клавиши сломаются в процессе заданного 16 | // варианта эксплуатации клавиатуры. 17 | 18 | // Формат ввода 19 | // Первая строка входных данных содержит целое число n (1 ≤ n ≤ 1000) —количество клавиш на 20 | // клавиатуре. Вторая строка содержит n целых чисел —с1, с2, … , сn, где сi (1 ≤ ci ≤ 100000) — 21 | // количество нажатий,выдерживаемых i-ой клавишей. Третья строка содержит целое число k (1 ≤ k ≤ 22 | // 100000) — общее количество нажатий клавиш, и последняя строка содержит k целых чисел pj (1 ≤ pj 23 | // ≤ n) — последовательность нажатых клавиш. 24 | 25 | // Формат вывода 26 | // Программа должна вывести n строк, содержащих информацию об исправности клавиш.Если i-я клавиша 27 | // сломалась, то i-ая строка должна содержать слово YES,если же клавиша работоспособна — слово NO. 28 | 29 | function inputProcessing(lines) { 30 | // const keysCount = Number(lines[0]); 31 | const keysResource = lines[1].split(' ').map(Number); 32 | const clicks = lines[3].split(' ').map(Number); 33 | const mapKeyIndexToResource = Object.fromEntries( 34 | keysResource.map((resource, i) => [i, resource]) 35 | ); 36 | 37 | for (const keyIndex of clicks) { 38 | mapKeyIndexToResource[keyIndex - 1] -= 1; 39 | } 40 | 41 | const keysBroken = Object.values(mapKeyIndexToResource).map((resource) => 42 | resource < 0 ? 'YES' : 'NO' 43 | ); 44 | return keysBroken; 45 | } 46 | 47 | (async () => { 48 | // const inputLines = await input(1); 49 | const inputLines = [ 50 | '5', 51 | '1 50 3 4 3', 52 | '16', 53 | '1 2 3 4 5 1 3 3 4 5 5 5 5 5 4 5', 54 | ]; 55 | // const inputLines = input; 56 | console.log({ inputLines }); 57 | const outputLines = inputProcessing(inputLines); 58 | console.log({ outputLines }); 59 | // output(outputLines); 60 | })(); 61 | 62 | export default inputProcessing; 63 | -------------------------------------------------------------------------------- /june_2021/lesson_3/F.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27663/problems/F 2 | 3 | // Геном жителей системы Тау Кита содержит 26 видов оснований, для обозначения которых будем 4 | // использовать буквы латинского алфавита от A до Z, а сам геном записывается строкой из латинских 5 | // букв.Важную роль в геноме играют пары соседних оснований, например, в геноме «ABBACAB» можно 6 | // выделить следующие пары оснований: AB, BB, BA, AC, CA, AB. 7 | 8 | // Степенью близости одного генома другому геному называется количество пар соседних оснований 9 | // первого генома, которые встречаются во втором геноме. 10 | 11 | // Вам даны два генома, определите степень близости первого генома второму геному.Программа 12 | // получает на вход две строки, состоящие из заглавных латинских букв.Каждая строка непустая, и её 13 | // длина не превосходит 105. 14 | 15 | // Программа должна вывести одно целое число – степень близости генома, записанного в первой 16 | // строке, геному, записанному во второй строке. 17 | 18 | // Пример 19 | // Ввод Вывод 20 | // ABBACAB 21 | // BCABB 22 | // 4 23 | // Примечания 24 | // Следующие пары оснований первого генома встречаются во втором геноме: AB, BB, CA, AB.Обратите 25 | // внимание на то, что пара AB в первом геноме встречается два раза, поэтому и подсчитана в ответе 26 | // два раза. 27 | 28 | // // with Regexp 29 | // function inputProcessing(lines) { 30 | // const set2 = new Set(); 31 | // for (const [, group] of lines[1].matchAll(/(?=([A-Z]{2}))/g)) { 32 | // set2.add(group); 33 | // } 34 | 35 | // const intersection = []; 36 | // for (const [, group] of lines[0].matchAll(/(?=([A-Z]{2}))/g)) { 37 | // if (set2.has(group)) { 38 | // intersection.push(group); 39 | // } 40 | // } 41 | // // console.log({ set1, set2, intersection }); 42 | // return intersection.length; 43 | // } 44 | 45 | function inputProcessing(lines) { 46 | const genome1 = lines[0]; 47 | const genome2 = lines[1]; 48 | 49 | const set2 = new Set(); 50 | 51 | for (let i = 1; i < genome2.length; i++) { 52 | const group = `${genome2[i - 1]}${genome2[i]}`; 53 | set2.add(group); 54 | } 55 | 56 | const intersection = []; 57 | 58 | for (let i = 1; i < genome1.length; i++) { 59 | const group = `${genome1[i - 1]}${genome1[i]}`; 60 | 61 | if (set2.has(group)) { 62 | intersection.push(group); 63 | } 64 | } 65 | 66 | return intersection.length; 67 | } 68 | 69 | (async () => { 70 | const inputLines = ['ABBACAB', 'BCABB']; 71 | 72 | console.log({ inputLines }); 73 | const outputLines = inputProcessing(inputLines); 74 | console.log({ outputLines }); 75 | })(); 76 | 77 | export default inputProcessing; 78 | -------------------------------------------------------------------------------- /september_2021_B/lesson_7/D.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "D. Наполненность котятами" {@link "https://contest.yandex.ru/contest/29396/problems/D/} 3 | * 4 | * На прямой в точках a1,a2,…,an (возможно, совпадающих) сидят n котят. На той же прямой лежат m 5 | * отрезков [l1,r1],[l2,r2],…,[lm,rm]. Нужно для каждого отрезка узнать его наполненность котятами 6 | * — сколько котят сидит на отрезке. 7 | * 8 | * @param { number } catsCount - n (1 ≤ n ≤ 10^5) 9 | * @param { number } segmentsCount - m (1 ≤ m ≤ 10^5) 10 | * @param { Array } catsPoints n целых чисел ai (0 ≤ ai ≤ 10^9) 11 | * @param { Array<[number, number]> } segments m пар целых чисел li,ri (0 ≤ li ≤ ri ≤ 10^9) 12 | * 13 | * @return { Array } Выведите m целых чисел. i-е число — наполненность котятами i-го отрезка 14 | */ 15 | function getCountPointByEverySegments( 16 | catsCount, 17 | segmentsCount, 18 | catsPoints, 19 | segments 20 | ) { 21 | const EVENT_TYPE = { begin: 'BEGIN', end: 'END', cat: 'CAT' }; 22 | const EVENT_TYPE_ORDER = { 23 | [EVENT_TYPE.begin]: -1, 24 | [EVENT_TYPE.cat]: 0, 25 | [EVENT_TYPE.end]: 1, 26 | }; 27 | const events = []; 28 | const linesCatCounts = new Array(segmentsCount).fill(0); 29 | 30 | for (let i = 0; i < catsCount; i++) { 31 | events.push({ time: catsPoints[i], type: EVENT_TYPE.cat }); 32 | } 33 | for (let i = 0; i < segmentsCount; i++) { 34 | const [begin, end] = segments[i]; 35 | events.push({ time: begin, type: EVENT_TYPE.begin, lineIndex: i }); 36 | events.push({ time: end, type: EVENT_TYPE.end, lineIndex: i }); 37 | } 38 | 39 | events.sort( 40 | (prev, next) => 41 | prev.time - next.time || 42 | EVENT_TYPE_ORDER[prev.type] - EVENT_TYPE_ORDER[next.type] 43 | ); 44 | 45 | let nowCountCat = 0; 46 | 47 | for (let i = 0; i < events.length; i++) { 48 | switch (events[i].type) { 49 | case EVENT_TYPE.begin: 50 | linesCatCounts[events[i].lineIndex] = nowCountCat; 51 | break; 52 | case EVENT_TYPE.end: 53 | linesCatCounts[events[i].lineIndex] = 54 | nowCountCat - linesCatCounts[events[i].lineIndex]; 55 | break; 56 | case EVENT_TYPE.cat: 57 | nowCountCat += 1; 58 | break; 59 | } 60 | } 61 | 62 | return linesCatCounts; 63 | } 64 | 65 | function inputProcessing(lines) { 66 | const [catsCount, segmentsCount] = lines[0].split(' ').map(Number); 67 | const catsPoints = lines[1].split(' ').map(Number); 68 | const segmentsLR = lines.slice(2).map((lr) => lr.split(' ').map(Number)); 69 | 70 | return getCountPointByEverySegments( 71 | catsCount, 72 | segmentsCount, 73 | catsPoints, 74 | segmentsLR 75 | ); 76 | } 77 | 78 | export default inputProcessing; 79 | -------------------------------------------------------------------------------- /june_2021/lesson_5/A.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27794/problems/A 2 | 3 | // Глеб обожает шоппинг. Как-то раз он загорелся идеей подобрать себе майку и штаны так, чтобы 4 | // выглядеть в них максимально стильно. В понимании Глеба стильность одежды тем больше, чем меньше 5 | // разница в цвете элементов его одежды. 6 | 7 | // В наличии имеется N (1 ≤ N ≤ 100 000) маек и M (1 ≤ M ≤ 100 000) штанов, про каждый элемент 8 | // известен его цвет (целое число от 1 до 10 000 000). Помогите Глебу выбрать одну майку и одни 9 | // штаны так, чтобы разница в их цвете была как можно меньше. 10 | 11 | // Формат ввода 12 | // Сначала вводится информация о майках: в первой строке целое число N (1 ≤ N ≤ 100 000) и во 13 | // второй N целых чисел от 1 до 10 000 000 — цвета имеющихся в наличии маек. Гарантируется, что 14 | // номера цветов идут в возрастающем порядке (в частности, цвета никаких двух маек не совпадают). 15 | 16 | // Далее в том же формате идёт описание штанов: их количество M (1 ≤ M ≤ 100 000) и в следующей 17 | // строке M целых чисел от 1 до 10 000 000 в возрастающем порядке — цвета штанов. 18 | 19 | // Формат вывода 20 | // Выведите пару неотрицательных чисел — цвет майки и цвет штанов, которые следует выбрать Глебу. 21 | // Если вариантов выбора несколько, выведите любой из них. 22 | 23 | // import fs from 'fs'; 24 | 25 | function inputProcessing(lines) { 26 | const N = Number(lines[0]); 27 | const M = Number(lines[2]); 28 | const listN = lines[1].split(' ').map(Number); 29 | const listM = lines[3].split(' ').map(Number); 30 | 31 | let indexN = 0; 32 | let indexM = 0; 33 | 34 | let minIndexN = 0; 35 | let minIndexM = 0; 36 | let minDiff = Infinity; 37 | 38 | while (indexN < N && indexM < M) { 39 | const [elemN, elemM] = [listN[indexN], listM[indexM]]; 40 | 41 | if (elemN === elemM) { 42 | [minIndexN, minIndexM] = [indexN, indexM]; 43 | break; 44 | } 45 | 46 | const diff = Math.abs(elemN - elemM); 47 | 48 | if (diff < minDiff) { 49 | minDiff = diff; 50 | [minIndexN, minIndexM] = [indexN, indexM]; 51 | } 52 | 53 | if (elemN < elemM) indexN += 1; 54 | else indexM += 1; 55 | } 56 | 57 | return [listN[minIndexN], listM[minIndexM]].join(' '); 58 | } 59 | 60 | // (async () => { 61 | // // const inputLines = await input(1); 62 | // const inputLines = fs.readFileSync('input.txt', 'utf8').split('\r\n'); 63 | // // const inputLines = ['3', 'Hello Hi', 'Bye Goodbye', 'List Array', 'Goodbye']; 64 | // // const inputLines = input; 65 | // console.log({ inputLines }); 66 | // const outputLines = inputProcessing(inputLines); 67 | // console.log({ outputLines }); 68 | // // output(outputLines); 69 | // })(); 70 | 71 | export default inputProcessing; 72 | -------------------------------------------------------------------------------- /june_2021/lesson_2/G.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27472/problems/G/ 2 | 3 | // Дан список, заполненный произвольными целыми числами. 4 | // Найдите в этом списке два числа, произведение которых максимально. 5 | // Выведите эти числа в порядке неубывания. 6 | 7 | // Список содержит не менее двух элементов. Числа подобраны так, что ответ однозначен. 8 | 9 | // Решение должно иметь сложность O(n), где n - размер списка. 10 | 11 | // Пример 12 | // -4 3 -5 2 5 // ввод 13 | // -5 -4 // вывод 14 | 15 | function inputProcessing(lines) { 16 | const list = lines[0].split(' ').map(Number); 17 | 18 | let max1 = Math.min(list[0], list[1]); 19 | let max2 = Math.max(list[0], list[1]); 20 | let min1 = Math.max(list[0], list[1]); 21 | let min2 = Math.min(list[0], list[1]); 22 | 23 | for (let i = 2; i < list.length; i++) { 24 | const num = list[i]; 25 | // console.log({ i, num, max1, max2, min1, min2 }); 26 | 27 | if (num > max2) { 28 | max1 = max2; 29 | max2 = num; 30 | } else if (num > max1) { 31 | max1 = num; 32 | } else if (num < min2) { 33 | min1 = min2; 34 | min2 = num; 35 | } else if (num < min1) { 36 | min1 = num; 37 | } 38 | } 39 | 40 | // console.log({ max1, max2, min1, min2 }); 41 | const queryNums = max1 * max2 > min1 * min2 ? [max1, max2] : [min1, min2]; 42 | 43 | return queryNums.sort((a, b) => a - b).join(' '); 44 | } 45 | 46 | (async () => { 47 | const inputLines = [ 48 | '12288 -10075 29710 15686 -18900 -17715 15992 24431 6220 28403 -23148 18480 -22905 5411 -7602 15560 -26674 11109 -4323 6146 -1523 4312 10666 -15343 -17679 7284 20709 -7103 24305 14334 -12281 17314 26061 25616 17453 16618 -24230 -19788 21172 11339 2202 -22442 -20997 1879 -8773 -8736 5310 -23372 12621 -25596 -28609 -13309 -13 10336 15812 -21193 21576 -1897 -12311 -6988 -25143 -3501 23231 26610 12618 25834 -29140 21011 23427 1494 15215 23013 -15739 8325 5359 -12932 18111 -72 -12509 20116 24390 1920 17487 25536 24934 -6784 -16417 -2222 -16569 -25594 4491 14249 -28927 27281 3297 5998 6259 4577 12415 3779 -8856 3994 19941 11047 2866 -24443 -17299 -9556 12244 6376 -13694 -14647 -22225 21872 7543 -6935 17736 -2464 9390 1133 18202 -9733 -26011 13474 29793 -26628 -26124 27776 970 14277 -23213 775 -9318 29014 -5645 -27027 -21822 -17450 -5 -655 22807 -20981 16310 27605 -18393 914 7323 599 -12503 -28684 5835 -5627 25891 -11801 21243 -21506 22542 -5097 8115 178 10427 25808 10836 -11213 18488 21293 14652 12260 42 21034 8396 -27956 13670 -296 -757 18076 -15597 4135 -25222 -19603 8007 6012 2704 28935 16188 -20848 13502 -11950 -24466 5440 26348 27378 7990 -11523 -26393', 49 | ]; 50 | console.log({ inputLines }); 51 | 52 | const outputLines = inputProcessing(inputLines); 53 | console.log({ outputLines }); 54 | })(); 55 | 56 | export default inputProcessing; 57 | -------------------------------------------------------------------------------- /march_2024/lesson_1/B.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "strings" 7 | ) 8 | 9 | func calculateGoalsNeeded( 10 | goalsFirstMatchTeam1, 11 | goalsFirstMatchTeam2, 12 | goalsSecondMatchTeam1, 13 | goalsSecondMatchTeam2 int, 14 | isFirstTeamPlayingAsVisitorInFirstMatch bool, 15 | ) int { 16 | isPlayingAsVisitor := map[string]map[string]bool{ 17 | "firstMatch": { 18 | "team1": isFirstTeamPlayingAsVisitorInFirstMatch, 19 | "team2": !isFirstTeamPlayingAsVisitorInFirstMatch, 20 | }, 21 | "secondMatch": { 22 | "team1": !isFirstTeamPlayingAsVisitorInFirstMatch, 23 | "team2": isFirstTeamPlayingAsVisitorInFirstMatch, 24 | }, 25 | } 26 | 27 | totalGoalsTeam1 := goalsFirstMatchTeam1 + goalsSecondMatchTeam1 28 | totalGoalsTeam2 := goalsFirstMatchTeam2 + goalsSecondMatchTeam2 29 | 30 | totalDiffGoals := totalGoalsTeam2 - totalGoalsTeam1 31 | 32 | if totalDiffGoals < 0 { 33 | return 0 // первая команда и так побеждает 34 | } 35 | // добавляем мин.необходимое количество голов для уравнивания 36 | queryGoals := totalDiffGoals 37 | 38 | team1GoalsAllMatchOnOpponentPitch := 0 39 | if isPlayingAsVisitor["firstMatch"]["team1"] { 40 | team1GoalsAllMatchOnOpponentPitch += goalsFirstMatchTeam1 41 | } 42 | if isPlayingAsVisitor["secondMatch"]["team1"] { 43 | // учитываем добавление мин.необходимого количества голов для уравнивания 44 | team1GoalsAllMatchOnOpponentPitch += goalsSecondMatchTeam1 + queryGoals 45 | } 46 | 47 | team2GoalsAllMatchOnOpponentPitch := 0 48 | if isPlayingAsVisitor["firstMatch"]["team2"] { 49 | team2GoalsAllMatchOnOpponentPitch += goalsFirstMatchTeam2 50 | } 51 | if isPlayingAsVisitor["secondMatch"]["team2"] { 52 | team2GoalsAllMatchOnOpponentPitch += goalsSecondMatchTeam2 53 | } 54 | 55 | // чтобы не проиграть, накидываем гол 56 | if team1GoalsAllMatchOnOpponentPitch < team2GoalsAllMatchOnOpponentPitch { 57 | return queryGoals + 1 58 | } 59 | // чтобы не допустим ничью, накидываем гол 60 | if team1GoalsAllMatchOnOpponentPitch == team2GoalsAllMatchOnOpponentPitch { 61 | return queryGoals + 1 62 | } 63 | 64 | return queryGoals 65 | } 66 | 67 | func mainB() { 68 | var match1, match2, isFirstTeamPlayingAsVisitorInFirstMatchStr string 69 | 70 | fmt.Scan(&match1, &match2, &isFirstTeamPlayingAsVisitorInFirstMatchStr) 71 | 72 | goalsFirstMatch := strings.Split(match1, ":") 73 | goalsFirstMatchTeam1, _ := strconv.Atoi(goalsFirstMatch[0]) 74 | goalsFirstMatchTeam2, _ := strconv.Atoi(goalsFirstMatch[1]) 75 | 76 | goalsSecondMatch := strings.Split(match2, ":") 77 | goalsSecondMatchTeam1, _ := strconv.Atoi(goalsSecondMatch[0]) 78 | goalsSecondMatchTeam2, _ := strconv.Atoi(goalsSecondMatch[1]) 79 | 80 | isFirstTeamAway := isFirstTeamPlayingAsVisitorInFirstMatchStr == "2" 81 | 82 | fmt.Print(calculateGoalsNeeded( 83 | goalsFirstMatchTeam1, 84 | goalsFirstMatchTeam2, 85 | goalsSecondMatchTeam1, 86 | goalsSecondMatchTeam2, 87 | isFirstTeamAway, 88 | )) 89 | } 90 | -------------------------------------------------------------------------------- /february_2023_B/lesson_1/7.js: -------------------------------------------------------------------------------- 1 | const timeToSec = (timeStr) => { 2 | const [h, m, s] = timeStr.split(':'); 3 | 4 | return parseInt(h, 10) * 60 * 60 + parseInt(m, 10) * 60 + parseInt(s, 10); 5 | }; 6 | 7 | const secToTime = (totalSeconds) => { 8 | const hour = Math.floor(totalSeconds / 3600) % 24; 9 | const minute = Math.floor(totalSeconds / 60) % 60; 10 | const sec = totalSeconds % 60; 11 | 12 | const f = (num) => String(num).padStart(2, '0'); 13 | 14 | return `${f(hour)}:${f(minute)}:${f(sec)}`; 15 | }; 16 | 17 | const getClientTime = (reqSentTimeStr, serverTimeStr, reqReceivedTimeStr) => { 18 | const [reqSentTime, serverTime, reqReceivedTimeRaw] = [ 19 | reqSentTimeStr, 20 | serverTimeStr, 21 | reqReceivedTimeStr, 22 | ].map(timeToSec); 23 | 24 | const reqReceivedTime = 25 | reqReceivedTimeRaw < reqSentTime 26 | ? reqReceivedTimeRaw + 24 * 3600 27 | : reqReceivedTimeRaw; 28 | 29 | const clientTime = 30 | serverTime + Math.round((reqReceivedTime - reqSentTime) / 2); 31 | 32 | return secToTime(clientTime); 33 | }; 34 | 35 | /** 36 | * "7. SNTP" {@link "https://contest.yandex.ru/contest/45468/problems/7} 37 | * 38 | * 1. Клиент отправляет запрос на сервер и запоминает время отправления A (по клиентскому времени) 39 | * 2. Сервер получает запрос в момент времени B (по точному серверному времени) и отправляет клиенту 40 | * сообщение, содержащее время B. 41 | * 3. =Клиент получает ответ на свой запрос в момент времени C (по клиентскому времени) и запоминает 42 | * его. Теперь клиент, из предположения, что сетевые задержки при передаче сообщений от клиента 43 | * серверу и от сервера клиенту одинаковы, может определить и установить себе точное время, 44 | * используя известные значения A, B, C.Вам предстоит реализовать алгоритм, с точностью до 45 | * секунды определяющий точное время для установки на клиенте по известным A, B и C. При 46 | * необходимости округлите результат до целого числа секунд по правилам арифметики (в меньшую 47 | * сторону, если дробная часть числа меньше 1/2, иначе в большую сторону). 48 | * 49 | * @param { string[] } lines Программа получает на вход три временные метки A, B, C, по одной в 50 | * каждой строке. Все временные метки представлены в формате «hh:mm:ss», где «hh» – это часы, «mm» 51 | * – минуты, «ss» – секунды. Часы, минуты и секунды записываются ровно двумя цифрами каждое 52 | * (возможно, с дополнительными нулями в начале числа). 53 | * 54 | * @return { string } Программа должна вывести одну временную метку в формате, описанном во входных 55 | * данных, – вычисленное точное время для установки на клиенте. В выводе не должно быть пробелов, 56 | * пустых строк в начале вывода. 57 | */ 58 | function inputProcessing(lines) { 59 | const reqSentTime = lines[0]; 60 | const serverTime = lines[1]; 61 | const reqReceivedTime = lines[2]; 62 | 63 | return getClientTime(reqSentTime, serverTime, reqReceivedTime); 64 | } 65 | 66 | export default inputProcessing; 67 | -------------------------------------------------------------------------------- /june_2021/lesson_2/B.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27472/problems/B/ 2 | 3 | // По последовательности чисел во входных данных определите ее вид: 4 | 5 | // CONSTANT – последовательность состоит из одинаковых значений 6 | // ASCENDING – последовательность является строго возрастающей 7 | // WEAKLY ASCENDING – последовательность является нестрого возрастающей 8 | // DESCENDING – последовательность является строго убывающей 9 | // WEAKLY DESCENDING – последовательность является нестрого убывающей 10 | // RANDOM – последовательность не принадлежит ни к одному из вышеупомянутых типов 11 | // Формат ввода 12 | // По одному на строке поступают числа последовательности ai, |ai| ≤ 109. 13 | 14 | // Признаком окончания последовательности является число -2× 109. Оно в последовательность не входит. 15 | 16 | // Формат вывода 17 | // В единственной строке выведите тип последовательности. 18 | 19 | function inputProcessing(lines) { 20 | const mapDefinitionToFnCheck = { 21 | CONSTANT: (sequence) => new Set(sequence).size === 1, // последовательность состоит из одинаковых значений 22 | ASCENDING: (sequence) => { 23 | // последовательность является строго возрастающей 24 | for (let i = 1; i < sequence.length; i++) { 25 | if (sequence[i] <= sequence[i - 1]) { 26 | return false; 27 | } 28 | } 29 | return true; 30 | }, 31 | DESCENDING: (sequence) => { 32 | // последовательность является строго убывающей 33 | for (let i = 1; i < sequence.length; i++) { 34 | if (sequence[i] >= sequence[i - 1]) { 35 | return false; 36 | } 37 | } 38 | return true; 39 | }, 40 | 'WEAKLY ASCENDING': (sequence) => { 41 | // последовательность является нестрого возрастающей 42 | 43 | for (let i = 1; i < sequence.length; i++) { 44 | if (sequence[i] < sequence[i - 1]) { 45 | return false; 46 | } 47 | } 48 | return true; 49 | }, 50 | 'WEAKLY DESCENDING': (sequence) => { 51 | // последовательность является нестрого убывающей 52 | for (let i = 1; i < sequence.length; i++) { 53 | if (sequence[i] > sequence[i - 1]) { 54 | return false; 55 | } 56 | } 57 | return true; 58 | }, 59 | }; 60 | const DEFAULT_DEFINITION = 'RANDOM'; 61 | 62 | const list = lines.map(Number); 63 | const FINISH_NUM = -2e9; 64 | const sequence = list.slice(0, list.indexOf(FINISH_NUM) || -list.length); 65 | // const sequence = list.slice(0, -1); 66 | // 67 | for (const [definition, fnCheck] of Object.entries(mapDefinitionToFnCheck)) { 68 | if (fnCheck(sequence)) { 69 | return definition; 70 | } 71 | } 72 | return DEFAULT_DEFINITION; 73 | } 74 | 75 | (async () => { 76 | // const inputLines = await input(1); 77 | const inputLines = [-530, -530, -530, -530, -530, -530, -2000000000]; 78 | console.log({ inputLines }); 79 | const outputLines = inputProcessing(inputLines); 80 | console.log({ outputLines }); 81 | // output(outputLines); 82 | })(); 83 | export default inputProcessing; 84 | -------------------------------------------------------------------------------- /june_2021/lesson_2/F.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27472/problems/F/ 2 | 3 | // Последовательность чисел назовем симметричной, если она одинаково читается как слева направо, так и справа налево. 4 | // Например, следующие последовательности являются симметричными: 5 | // 1 2 3 4 5 4 3 2 1 6 | // 1 2 1 2 2 1 2 1 7 | 8 | // Вашей программе будет дана последовательность чисел. 9 | // Требуется определить, какое минимальное количество и каких чисел надо приписать в конец этой последовательности, 10 | // чтобы она стала симметричной. 11 | 12 | // Формат ввода 13 | // Сначала вводится число N — количество элементов исходной последовательности (1 ≤ N ≤ 100). 14 | // Далее идут N чисел — элементы этой последовательности, натуральные числа от 1 до 9. 15 | // !! Тут в вводе пробел лишний в конце последовательности. 16 | // Из-за этого тест 8 не проходил. Надо или в формате ввода указать или убрать его. 17 | 18 | // Формат вывода 19 | // Выведите сначала число M — минимальное количество элементов, которое надо дописать к последовательности, 20 | // а потом M чисел(каждое — от 1 до 9) — числа, которые надо дописать к последовательности. 21 | 22 | // 32 23 | // 1 3 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 24 | 25 | // function isPalindromeCheck(str) { 26 | // for (let i = 0; i < str.length / 2; i++) { 27 | // if (str[i] !== str[str.length - i - 1]) { 28 | // return false; 29 | // } 30 | // } 31 | // return true; 32 | // } 33 | // (async () => { 34 | // const inputLines = [ 35 | // '', 36 | // '1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 3 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 ', 37 | // ]; // 1 2 1 38 | // // const inputLines = ['', '1 2 3']; // 1 2 1 39 | // // console.log({ inputLines }); 40 | // console.log(inputLines[1].split(' ').join('')); 41 | 42 | // const outputLines = inputProcessing(inputLines); 43 | // console.log({ outputLines }); 44 | // const str = [...inputLines[1].split(' '), ...outputLines[1].split(' ')].join(''); 45 | // console.log({ str }); 46 | // console.log(isPalindromeCheck(str)); 47 | // })(); 48 | 49 | function inputProcessing(lines) { 50 | // const n = Number(lines[0]); // (1 ≤ N ≤ 100) 51 | const list = lines[1].split(' ').map(Number); // (от 1 до 9) 52 | const listReverse = [...list].reverse(); 53 | 54 | const stack = []; 55 | let index = 0; 56 | 57 | for (let i = 0; i < list.length; i++) { 58 | if (list[i] === listReverse[index]) { 59 | let isPalindrome = true; 60 | 61 | for (let j = i; j < list.length; j++) { 62 | if (list[j] !== listReverse[j - i]) { 63 | isPalindrome = false; 64 | break; 65 | } 66 | } 67 | 68 | if (!isPalindrome) { 69 | index = 0; 70 | stack.push(list[i]); 71 | } else { 72 | break; 73 | } 74 | } else { 75 | stack.push(list[i]); 76 | } 77 | } 78 | 79 | return stack.length === 0 80 | ? '0' 81 | : [String(stack.length), [...stack].reverse().join(' ')]; 82 | } 83 | 84 | export default inputProcessing; 85 | -------------------------------------------------------------------------------- /june_2021/lesson_5/C.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27794/problems/C 2 | 3 | // Александр живет в плоском мире. Горная цепь состоит из отрезков, соединяющих точки на плоскости, 4 | // каждая из которых находится строго правее предыдущей (x-координата следующей точки больше, чем у 5 | // предыдущей). Трассой на горной цепи называется её часть между двумя фиксированными концами 6 | // отрезков. 7 | 8 | // Участок, на котором при движении по трассе координата y (высота) всегда возрастает, называется 9 | // подъемом, величиной подъема называется разность высот между начальной и конечной точками 10 | // участка. 11 | 12 | // Туристическая компания предлагает на выбор несколько трасс на одной горной цепи. Александр из-за 13 | // финансовых трудностей может выбрать для поездки только одну из этих трасс. Вы решили помочь ему 14 | // с выбором. Александру важно для каждой трассы определить суммарную высоту подъемов на ней. 15 | // Обратите внимание, что трасса может идти как слева-направо, так и справа-налево. 16 | 17 | // Формат ввода 18 | // В первой строке входного файла содержится единственное число N — количество точек ломаной, 19 | // задающей горную цепь (1 ≤ N ≤ 30 000). Далее в N строках содержатся описания точек, каждое из 20 | // которых состоит из двух целых чисел, xi и yi (1 ≤ xi, yi ≤ 30 000). 21 | 22 | // В следующей строке находится число M — количество трасс (1 ≤ M ≤ 30 000). 23 | 24 | // Далее в M строках содержатся описания трасс. Каждое описание представляет собой два целых числа, 25 | // si и fi, они обозначают номера вершин начала и конца трассы, соответственно (1 ≤ si ≤ N, 26 | // 1 ≤ fi ≤ N). Начало и конец трассы могут совпадать. 27 | 28 | // Гарантируется, что во входном файле задана именно горная цепь. 29 | 30 | // Формат вывода 31 | // Для каждой трассы выведите одно число — суммарную высоту подъемов на данной трассе. 32 | 33 | import fs from 'fs'; 34 | 35 | function inputProcessing(lines) { 36 | const N = Number(lines[0]); 37 | const waysCount = Number(lines[N + 1]); 38 | 39 | const segments = lines.slice(1, N).map((xy) => xy.split(' ').map(Number)); 40 | 41 | const ways = new Array(waysCount) 42 | .fill(0) 43 | .map((_, i) => lines[N + 1 + 1 * (i + 1)].split(' ').map(Number)); 44 | 45 | console.log({ N, waysCount, segments, ways }); 46 | // let setsCount = 0; 47 | // let leftIndex = 0; 48 | // let sum = 0; 49 | 50 | // for (let rightIndex = 0; rightIndex < N; rightIndex++) { 51 | // sum += nums[rightIndex]; 52 | 53 | // while (sum > K && leftIndex <= rightIndex) { 54 | // sum -= nums[leftIndex]; 55 | // leftIndex += 1; 56 | // } 57 | 58 | // if (sum === K) { 59 | // setsCount += 1; 60 | // } 61 | // } 62 | 63 | // return setsCount; 64 | } 65 | 66 | (async () => { 67 | // const inputLines = await input(1); 68 | const inputLines = fs.readFileSync('input.txt', 'utf8').split('\r\n'); 69 | // const inputLines = ['3', 'Hello Hi', 'Bye Goodbye', 'List Array', 'Goodbye']; 70 | // const inputLines = input; 71 | console.log({ inputLines }); 72 | const outputLines = inputProcessing(inputLines); 73 | console.log({ outputLines }); 74 | // output(outputLines); 75 | })(); 76 | 77 | export default inputProcessing; 78 | -------------------------------------------------------------------------------- /june_2021/lesson_6/C.js: -------------------------------------------------------------------------------- 1 | const intDivision = (a, b) => Math.floor(a / b); 2 | 3 | const binarySearch = (leftInit = 0, rightInit, checkFn) => { 4 | let left = leftInit; 5 | let right = rightInit; 6 | 7 | while (left < right) { 8 | const middle = intDivision(left + right, 2); 9 | 10 | if (checkFn(middle)) { 11 | right = middle; 12 | } else { 13 | left = middle + 1; 14 | } 15 | } 16 | 17 | return left; 18 | }; 19 | 20 | /** 21 | * "C. Дипломы" {@link "https://contest.yandex.ru/contest/27844/problems/C/} 22 | * 23 | * @param { number } width ширина рамки, целое (1 ≤ X ≤ 10^9) 24 | * @param { number } height высота рамки, целое (1 ≤ X ≤ 10^9) 25 | * @param { number } count количество рамок, целое (1 ≤ X ≤ 10^9) 26 | * 27 | * @return { number } минимальный размер стороны квадратной доски, которая потребуется для размещения всех своих рамок 28 | */ 29 | function calcMinBoardSize(width, height, count) { 30 | const left = Math.max(width, height); 31 | const right = Math.max(width * count, height * count); 32 | 33 | const isCountBoardCellEnough = (maxSideCount) => 34 | intDivision(maxSideCount, width) * intDivision(maxSideCount, height) >= 35 | count; 36 | 37 | return binarySearch(left, right, isCountBoardCellEnough); 38 | } 39 | 40 | function inputProcessing(lines) { 41 | const [width, height, count] = lines[0].split(' ').map(Number); 42 | 43 | return calcMinBoardSize(width, height, count); 44 | } 45 | 46 | export default inputProcessing; 47 | 48 | // eslint-disable-next-line no-unused-vars 49 | function calcMinBoardSizeByFormula(width, height, count) { 50 | // time complexity ~~ O(log(N/3)), less then binary search 51 | 52 | const maxSide = Math.max(width, height); 53 | const minSide = Math.min(width, height); 54 | 55 | const aspectRatio = maxSide / minSide; 56 | const aspectRatioSqrt = Math.sqrt(aspectRatio); 57 | const sqrtCount = Math.sqrt(count); 58 | 59 | let maxCountByMaxSide = Math.ceil(sqrtCount / aspectRatioSqrt); 60 | while ( 61 | intDivision(maxCountByMaxSide * maxSide, minSide) * maxCountByMaxSide < 62 | count 63 | ) { 64 | maxCountByMaxSide += 1; 65 | } 66 | let maxCountByMinSide = Math.ceil(sqrtCount * aspectRatioSqrt); 67 | 68 | while ( 69 | intDivision(maxCountByMinSide * minSide, maxSide) * maxCountByMinSide < 70 | count 71 | ) { 72 | maxCountByMinSide += 1; 73 | } 74 | 75 | return Math.min(maxCountByMaxSide * maxSide, maxCountByMinSide * minSide); 76 | } 77 | 78 | // ### perfomance testing ### 79 | 80 | // const [width, height, count] = [17, 37, 10_000_000_000_000]; 81 | // if (BigInt(Math.max(width, height)) * BigInt(count) > BigInt(Number.MAX_SAFE_INTEGER)) { 82 | // throw new Error('More then MAX_SAFE_INTEGER'); 83 | // } 84 | 85 | // let sumMy = 0; 86 | // let sumBin = 0; 87 | // for (let index = 0; index < 10_000_000; index++) { 88 | // const startMy = Date.now(); 89 | // calcMinBoardSizeByFormula(width, height, count); 90 | // const my = Date.now() - startMy; 91 | // sumMy += my; 92 | 93 | // const startBin = Date.now(); 94 | // calcMinBoardSize(width, height, count); 95 | // const bin = Date.now() - startBin; 96 | // sumBin += bin; 97 | // } 98 | // console.log({ sumMy, sumBin }); 99 | -------------------------------------------------------------------------------- /june_2021/lesson_4/F.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable guard-for-in */ 2 | // https://contest.yandex.ru/contest/27665/problems/F 3 | 4 | // Дана база данных о продажах некоторого интернет-магазина. Каждая строка входного файла 5 | // представляет собой запись вида Покупатель товар количество, где Покупатель — имя покупателя 6 | // (строка без пробелов), товар — название товара (строка без пробелов), количество — количество 7 | // приобретенных единиц товара. Создайте список всех покупателей, а для каждого покупателя 8 | // подсчитайте количество приобретенных им единиц каждого вида товаров. 9 | 10 | // Формат ввода 11 | // Вводятся сведения о покупках в указанном формате. 12 | 13 | // Формат вывода 14 | // Выведите список всех покупателей в лексикографическом порядке, после имени каждого покупателя 15 | // выведите двоеточие, затем выведите список названий всех приобретенных данным покупателем товаров 16 | // в лексикографическом порядке, после названия каждого товара выведите количество единиц товара, 17 | // приобретенных данным покупателем. Информация о каждом товаре выводится в отдельной строке. 18 | import fs from 'fs'; 19 | // const fs = require('fs'); 20 | 21 | import readline from 'readline'; 22 | 23 | // const getRamUsage = () => 24 | // Object.fromEntries( 25 | // Object.entries(process.memoryUsage()).map(([key, used]) => [key, `${Math.round(used / 1024 / 1024)} MB`]) 26 | // ); 27 | 28 | // const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); 29 | const rl = readline.createInterface({ 30 | input: fs.createReadStream('input.txt'), 31 | output: process.stdout, 32 | }); 33 | 34 | const customers = {}; 35 | 36 | rl.on('line', (data) => { 37 | const [customer, item, quantity] = data.split(' '); 38 | 39 | if (!customers[customer]) { 40 | customers[customer] = new Map(); 41 | customers[customer].set(item, +quantity); 42 | } else if (!customers[customer].has(item)) { 43 | customers[customer].set(item, +quantity); 44 | } else { 45 | customers[customer].set(item, customers[customer].get(item) + +quantity); 46 | } 47 | }); 48 | 49 | let outputLines = []; 50 | 51 | rl.on('close', () => { 52 | Object.keys(customers) 53 | .sort() 54 | .forEach((customer) => { 55 | if (outputLines.length > 4000) { 56 | process.stdout.write(`${outputLines.join('\n')}\n`); 57 | 58 | outputLines = []; 59 | } 60 | outputLines.push(`${customer}:`); 61 | 62 | [...customers[customer].keys()].sort().forEach((item) => { 63 | outputLines.push(`${item} ${customers[customer].get(item)}`); 64 | }); 65 | }); 66 | process.stdout.write(`${outputLines.join('\n')}\n`); 67 | // console.log(getRamUsage()); 68 | }); 69 | 70 | // (async () => { 71 | // // const inputLines = await input(1); 72 | // // const inputLines = fs.readFileSync('input.txt', 'utf8').split('\r\n'); 73 | // const inputLines = [ 74 | // 'Ivanov paper 10', 75 | // 'Petrov pens 5', 76 | // 'Ivanov marker 3', 77 | // 'Ivanov paper 7', 78 | // 'Petrov envelope 20', 79 | // 'Ivanov envelope 5', 80 | // ]; 81 | // // console.log({ inputLines }); 82 | // // const outputLines = inputProcessing(inputLines); 83 | // // console.log({ outputLines }); 84 | // // output(outputLines); 85 | // })(); 86 | -------------------------------------------------------------------------------- /june_2021/lesson_2/E.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27472/problems/E/ 2 | 3 | // К сожалению, после чемпионата потерялись записи с фамилиями участников, 4 | // остались только записи о длине броска в том порядке, в котором их совершали участники. 5 | 6 | // Тракторист Василий помнит три факта: 7 | 8 | // 1) Число метров, на которое он метнул лепешку, оканчивалось на 5 9 | // 2) Один из победителей чемпионата метал лепешку до Василия 10 | // 3) Участник, метавший лепешку сразу после Василия, метнул ее на меньшее количество метров 11 | 12 | // Будем считать, что участник соревнования занял k-е место, 13 | // если ровно(k − 1) участников чемпионата метнули лепешку строго дальше, чем он. 14 | 15 | // Какое максимально высокое место мог занять Василий? 16 | 17 | // Формат ввода 18 | // Первая строка входного файла 19 | // содержит целое число n — количество участников чемпионата по метанию лепешек(3 ≤ n ≤ 105). 20 | // Вторая строка входного файла 21 | // содержит n положительных целых чисел, каждое из которых не превышает 1000, 22 | // — дальность броска участников чемпионата, приведенные в том порядке, в котором происходило метание. 23 | 24 | // Формат вывода 25 | // Выведите самое высокое место, которое мог занять тракторист Василий. 26 | // Если не существует ни одного участника чемпионата, который удовлетворяет, описанным выше 27 | // условиям, выведите число 0. 28 | 29 | function inputProcessing(lines) { 30 | // const n = Number(lines[0]); // (3 ≤ n ≤ 105). 31 | const list = lines[1].split(' ').map(Number); 32 | 33 | // Будем считать, что участник соревнования занял k - е место, 34 | // если ровно(k − 1) участников чемпионата метнули лепешку строго дальше, чем он. 35 | // 30 - 1 36 | // 20 - 2 37 | // 15 - 3 38 | // 10 - 4 39 | // 10 - 4 40 | // 5 - 6 41 | // 1 - 7 42 | const scores = [...list].sort((a, b) => b - a); 43 | const mapScoreToPlace = {}; 44 | 45 | for (const [index, score] of Object.entries(scores)) { 46 | if (!(score in mapScoreToPlace)) { 47 | mapScoreToPlace[score] = Number(index); 48 | } 49 | } 50 | 51 | const mapIndexToPlaces = {}; 52 | let winnerIndex = Number.POSITIVE_INFINITY; 53 | 54 | for (const [index, score] of Object.entries(list)) { 55 | const place = mapScoreToPlace[score] + 1; 56 | mapIndexToPlaces[index] = place; 57 | 58 | if (place === 1 && Number(index) < winnerIndex) { 59 | winnerIndex = Number(index); 60 | } 61 | } 62 | let maxPlace = Infinity; 63 | let ixExist = false; 64 | 65 | for (let i = 1; i < list.length - 1; i++) { 66 | const current = list[i]; 67 | const place = Number(mapIndexToPlaces[i]); 68 | if ( 69 | current % 5 === 0 && 70 | current % 2 !== 0 && 71 | i > winnerIndex && 72 | current > list[i + 1] && 73 | place < maxPlace 74 | ) { 75 | ixExist = true; 76 | maxPlace = place; 77 | } 78 | } 79 | 80 | return ixExist ? maxPlace : 0; 81 | } 82 | 83 | (async () => { 84 | // const inputLines = await input(1); 85 | const inputLines = [10, '15 15 10']; // 35 place // 49 index? 86 | // console.log({ inputLines }); 87 | 88 | const outputLines = inputProcessing(inputLines); 89 | console.log({ outputLines }); 90 | // output(outputLines); 91 | })(); 92 | 93 | export default inputProcessing; 94 | -------------------------------------------------------------------------------- /june_2021/lesson_2/J.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27472/problems/J/ 2 | 3 | // Вам Максим показал запись, в которой приведена последовательность частот, выставляемых им на тюнере, и про каждую ноту, 4 | // начиная со второй, записано — ближе или дальше она к звуку треугольника, чем предыдущая нота. 5 | // Заранее известно, что частота звучания треугольника Максима составляет не менее 30 герц и не более 4000 герц. 6 | // 7 | // Требуется написать программу, которая определяет, в каком интервале может находиться частота звучания треугольника. 8 | 9 | // Формат ввода 10 | // Первая строка входного файла содержит целое число n — количество нот, которые воспроизводил Максим с помощью тюнера (2 ≤ n ≤ 1000). 11 | // Последующие n строк содержат записи Максима, причём каждая строка содержит две компоненты: 12 | // вещественное число fi — частоту, 13 | // выставленную на тюнере, в герцах(30 ≤ fi ≤ 4000), и слово «closer» или слово «further» для каждой частоты, кроме первой. 14 | 15 | // Слово «closer» означает, что частота данной ноты ближе к частоте звучания треугольника, чем частота предыдущей ноты, 16 | // что формально описывается соотношением: | fi − ftriangle | < | fi − 1 − ftriangle | . 17 | 18 | // Слово «further» означает, что частота данной ноты дальше, чем предыдущая. 19 | 20 | // Если оказалось, что очередная нота так же близка к звуку треугольника, как и предыдущая нота, 21 | // то Максим мог записать любое из двух указанных выше слов. 22 | 23 | // Гарантируется, что результаты, полученные Максимом, непротиворечивы. 24 | 25 | // Формат вывода 26 | // В выходной файл необходимо вывести через пробел два вещественных числа — 27 | // наименьшее и наибольшее возможное значение частоты звучания треугольника, изготовленного Максимом. 28 | // Числа должны быть выведены с точностью не хуже 10−6. 29 | 30 | function inputProcessing(lines) { 31 | // eslint-disable-next-line no-unused-vars 32 | const [n, firstMeasurementRaw, ...measurement] = lines; 33 | const nums = measurement.map((str) => { 34 | const [num, hotOrCold] = str.split(' '); 35 | return [Number(num), hotOrCold]; 36 | }); // х(30 ≤ fi ≤ 4000) 37 | 38 | let min = 30; 39 | let max = 4000; 40 | let lastMeasure = Number(firstMeasurementRaw); 41 | 42 | // console.log({ n, lastMeasure, min, max }, nums); 43 | 44 | for (const [current, hotOrCold] of nums) { 45 | if (hotOrCold === 'further') { 46 | if (current > lastMeasure) { 47 | max = Math.min(max, (current - lastMeasure) / 2 + lastMeasure); 48 | } else { 49 | min = Math.max(min, (current - lastMeasure) / 2 + lastMeasure); 50 | } 51 | } else if (hotOrCold === 'closer') { 52 | if (current > lastMeasure) { 53 | min = Math.max(min, (current - lastMeasure) / 2 + lastMeasure); 54 | } else { 55 | max = Math.min(max, (current - lastMeasure) / 2 + lastMeasure); 56 | } 57 | } 58 | 59 | lastMeasure = current; 60 | } 61 | // console.log({ n, lastMeasure, min, max }, nums); 62 | return [min, max].join(' '); 63 | } 64 | 65 | (async () => { 66 | // const inputLines = ['3 2 2', '1 1', '2 2']; 67 | const inputLines = ['4', '554', '880 further', '440 closer', '622 closer']; 68 | console.log({ inputLines }); 69 | 70 | const outputLines = inputProcessing(inputLines); 71 | console.log({ outputLines }); 72 | })(); 73 | 74 | export default inputProcessing; 75 | -------------------------------------------------------------------------------- /march_2024/lesson_1/B.js: -------------------------------------------------------------------------------- 1 | function calculateGoalsNeeded( 2 | goalsFirstMatchTeam1, // 3 | goalsFirstMatchTeam2, 4 | goalsSecondMatchTeam1, 5 | goalsSecondMatchTeam2, 6 | isFirstTeamPlayingAsVisitorInFirstMatch 7 | ) { 8 | const isPlayingAsVisitor = { 9 | firstMatch: { 10 | team1: isFirstTeamPlayingAsVisitorInFirstMatch, 11 | team2: !isFirstTeamPlayingAsVisitorInFirstMatch, 12 | }, 13 | secondMatch: { 14 | team1: !isFirstTeamPlayingAsVisitorInFirstMatch, 15 | team2: isFirstTeamPlayingAsVisitorInFirstMatch, 16 | }, 17 | }; 18 | 19 | const totalGoalsTeam1 = goalsFirstMatchTeam1 + goalsSecondMatchTeam1; 20 | const totalGoalsTeam2 = goalsFirstMatchTeam2 + goalsSecondMatchTeam2; 21 | 22 | const totalDiffGoals = totalGoalsTeam2 - totalGoalsTeam1; 23 | 24 | if (totalDiffGoals < 0) { 25 | return 0; // первая команда и так побеждает 26 | } 27 | // добавляем мин.необходимое количество голов для уравнивания 28 | const queryGoals = totalDiffGoals; 29 | 30 | const team1GoalsAllMatchOnOpponentPitch = 31 | (isPlayingAsVisitor.firstMatch.team1 ? goalsFirstMatchTeam1 : 0) + 32 | // учитываем добавление мин.необходимого количества голов для уравнивания 33 | (isPlayingAsVisitor.secondMatch.team1 34 | ? goalsSecondMatchTeam1 + queryGoals 35 | : 0); 36 | 37 | const team2GoalsAllMatchOnOpponentPitch = 38 | (isPlayingAsVisitor.firstMatch.team2 ? goalsFirstMatchTeam2 : 0) + 39 | (isPlayingAsVisitor.secondMatch.team2 ? goalsSecondMatchTeam2 : 0); 40 | 41 | // чтобы не проиграть, накидываем гол 42 | if (team1GoalsAllMatchOnOpponentPitch < team2GoalsAllMatchOnOpponentPitch) { 43 | return queryGoals + 1; 44 | } 45 | // чтобы не допустим ничью, накидываем гол 46 | if (team1GoalsAllMatchOnOpponentPitch === team2GoalsAllMatchOnOpponentPitch) { 47 | return queryGoals + 1; 48 | } 49 | 50 | return queryGoals; 51 | } 52 | 53 | /** 54 | * "B. Футбольный комментатор" {@link "https://contest.yandex.ru/contest/59539/problems/B} 55 | * 56 | * @param { string[] } lines В первой строке записан счёт первого мачта в формате G1:G2, где G1 — 57 | * число мячей, забитых первой командой, а G2 — число мячей, забитых второй командой. 58 | * Во второй строке записан счёт второго (текущего) матча в аналогичном формате. 59 | * Все числа в записи счёта не превышают 5. 60 | * В третьей строке записано число 1, если первую игру первая команда провела «дома», 61 | * или 2, если «в гостях». 62 | * 63 | * @return { number } Выведите единственное целое число — сколько голов МИНИМАЛЬНО необходимо забить первой команде, 64 | * чтобы победить, не переводя игру в дополнительное время. ВТОРАЯ КОМАНДА НЕ ЗАБИВАЕТ ГОЛЫ ПОСЛЕ ТЕКУЩЕГО СЧЁТА. 65 | * Если число забитых мячей совпадает, выигрывает команда, забившая больше мячей «в гостях» ВО ВСЕХ МАТЧАХ. 66 | */ 67 | function inputProcessing(lines) { 68 | const [goalsFirstMatchTeam1, goalsFirstMatchTeam2] = lines[0] 69 | .split(':') 70 | .map(Number); 71 | 72 | const [goalsSecondMatchTeam1, goalsSecondMatchTeam2] = lines[1] 73 | .split(':') 74 | .map(Number); 75 | 76 | const isFirstTeamPlayingAsVisitorInFirstMatch = Number(lines[2]) === 2; 77 | 78 | return calculateGoalsNeeded( 79 | goalsFirstMatchTeam1, 80 | goalsFirstMatchTeam2, 81 | goalsSecondMatchTeam1, 82 | goalsSecondMatchTeam2, 83 | isFirstTeamPlayingAsVisitorInFirstMatch 84 | ); 85 | } 86 | 87 | export default inputProcessing; 88 | -------------------------------------------------------------------------------- /june_2021/lesson_4/G.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27665/problems/G 2 | 3 | // Вам необходимо реализовать такую систему. Клиенты банка идентифицируются именами (уникальная 4 | // строка, не содержащая пробелов). Первоначально у банка нет ни одного клиента. Как только для 5 | // клиента проводится операция пололнения, снятия или перевода денег, ему заводится счет с нулевым 6 | // балансом. Все дальнейшие операции проводятся только с этим счетом. Сумма на счету может быть как 7 | // положительной, так и отрицательной, при этом всегда является целым числом. 8 | 9 | // Формат ввода 10 | // Входной файл содержит последовательность операций. Возможны следующие операции: DEPOSIT name sum 11 | // - зачислить сумму sum на счет клиента name. Если у клиента нет счета, то счет создается. 12 | // WITHDRAW name sum - снять сумму sum со счета клиента name. Если у клиента нет счета, то счет 13 | // создается. BALANCE name - узнать остаток средств на счету клиента name. TRANSFER name1 name2 sum 14 | // - перевести сумму sum со счета клиента name1 на счет клиента name2. Если у какого-либо клиента 15 | // нет счета, то ему создается счет. INCOME p - начислить всем клиентам, у которых открыты счета, 16 | // p% от суммы счета. Проценты начисляются только клиентам с положительным остатком на счету, если 17 | // у клиента остаток отрицательный, то его счет не меняется. После начисления процентов сумма на 18 | // счету остается целой, то есть начисляется только целое число денежных единиц. Дробная часть 19 | // начисленных процентов отбрасывается. 20 | 21 | // Формат вывода 22 | // Для каждого запроса BALANCE программа должна вывести остаток на счету данного клиента. Если же у 23 | // клиента с запрашиваемым именем не открыт счет в банке, выведите ERROR. 24 | 25 | import fs from 'fs'; 26 | import readline from 'readline'; 27 | 28 | const rl = readline.createInterface({ 29 | input: fs.createReadStream('input.txt'), 30 | output: process.stdout, 31 | }); 32 | 33 | const clients = new Map(); 34 | 35 | const createBankCard = (client) => { 36 | clients.set(client, 0); 37 | }; 38 | const IsNoExistCreateBankCard = (client) => { 39 | if (!clients.has(client)) { 40 | createBankCard(client); 41 | } 42 | }; 43 | 44 | const mapOperationToFn = { 45 | DEPOSIT: (client, money) => { 46 | IsNoExistCreateBankCard(client); 47 | 48 | clients.set(client, clients.get(client) + Number(money)); 49 | }, 50 | WITHDRAW: (client, money) => { 51 | IsNoExistCreateBankCard(client); 52 | 53 | clients.set(client, clients.get(client) - Number(money)); 54 | }, 55 | TRANSFER: (clientFrom, clientTo, money) => { 56 | IsNoExistCreateBankCard(clientFrom); 57 | IsNoExistCreateBankCard(clientTo); 58 | 59 | clients.set(clientFrom, clients.get(clientFrom) - Number(money)); 60 | clients.set(clientTo, clients.get(clientTo) + Number(money)); 61 | }, 62 | INCOME: (percent) => { 63 | for (const everyClient of clients.keys()) { 64 | const amount = clients.get(everyClient); 65 | 66 | if (amount > 0) { 67 | const income = Math.floor((Number(percent) / 100) * amount); 68 | clients.set(everyClient, amount + income); 69 | } 70 | } 71 | }, 72 | BALANCE: (client) => { 73 | const res = clients.has(client) ? String(clients.get(client)) : 'ERROR'; 74 | process.stdout.write(`${res}\n`); 75 | }, 76 | }; 77 | 78 | rl.on('line', (input) => { 79 | const [operation, ...data] = input.split(' '); 80 | 81 | mapOperationToFn[operation](...data); 82 | }); 83 | -------------------------------------------------------------------------------- /june_2021/lesson_1/E.js: -------------------------------------------------------------------------------- 1 | // Бригада скорой помощи выехала по вызову в один из отделенных районов. 2 | // К сожалению, когда диспетчер получил вызов, он успел записать только адрес дома и номер квартиры K1, а затем связь прервалась. 3 | // Однако он вспомнил, что по этому же адресу дома некоторое время назад скорая помощь выезжала в квартиру K2, которая расположена в подъезда P2 на этаже N2. 4 | // Известно, что в доме M этажей и количество квартир на каждой лестничной площадке одинаково. 5 | // Напишите программу, которая вычисляет номер подъезда P1 и номер этажа N1 квартиры K1. 6 | 7 | // Формат ввода 8 | // Во входном файле записаны пять положительных целых чисел K1, M, K2, P2, N2. Все числа не превосходят 10^6. 9 | 10 | // Формат вывода 11 | // Выведите два числа P1 и N1. Если входные данные не позволяют однозначно определить P1 или N1, вместо соответствующего числа напечатайте 0. Если входные данные противоречивы, напечатайте два числа –1 (минус один). 12 | 13 | // import { input, output } from '../../input-output_dev.js'; 14 | 15 | function inputProcessing(lines) { 16 | const getPodezd = (floorRaw, floorMax) => Math.ceil(floorRaw / floorMax); 17 | const getFloor = (floorRaw, podezd, floorMax) => 18 | Math.floor(floorRaw - (podezd - 1) * floorMax); 19 | 20 | const [K1, M, K2, P2, N2] = lines[0].split(' ').map(Number); 21 | 22 | const floorMax = M; 23 | const oldAddr = { 24 | room: K2, 25 | floor: N2, 26 | podezd: P2, 27 | }; 28 | const newAddr = { 29 | room: K1, 30 | }; 31 | 32 | if ( 33 | oldAddr.floor > floorMax || 34 | (oldAddr.podezd === 1 && oldAddr.room / oldAddr.floor < 1) 35 | ) { 36 | return [-1, -1].join(' '); 37 | } 38 | 39 | if (floorMax === 1) { 40 | newAddr.floor = floorMax; 41 | } 42 | 43 | const roomByFloorRaw = Math.ceil( 44 | oldAddr.room / ((oldAddr.podezd - 1) * floorMax + oldAddr.floor) 45 | ); 46 | 47 | if (oldAddr.floor === 1 && oldAddr.podezd === 1) { 48 | const floorRaw = Math.ceil(newAddr.room / roomByFloorRaw); 49 | 50 | newAddr.podezd = floorRaw < floorMax ? getPodezd(floorRaw, floorMax) : 0; 51 | newAddr.floor = 52 | (newAddr.floor ?? newAddr.room < oldAddr.room) ? oldAddr.floor : 0; 53 | 54 | return [newAddr.podezd, newAddr.floor].join(' '); 55 | } 56 | 57 | const variantPodezd = new Set(); 58 | const variantFloor = new Set(); 59 | 60 | for ( 61 | let roomByFloorI = roomByFloorRaw; 62 | roomByFloorI <= roomByFloorRaw + 1; 63 | roomByFloorI++ 64 | ) { 65 | const floorInputRaw = Math.ceil(oldAddr.room / roomByFloorI); 66 | const podezdInput = getPodezd(floorInputRaw, floorMax); 67 | const floorInput = getFloor(floorInputRaw, podezdInput, floorMax); 68 | 69 | if (floorInput === oldAddr.floor && podezdInput === oldAddr.podezd) { 70 | const floorRaw = Math.ceil(newAddr.room / roomByFloorI); 71 | const podezd = getPodezd(floorRaw, floorMax); 72 | const floor = newAddr.floor ?? getFloor(floorRaw, podezd, floorMax); 73 | 74 | variantPodezd.add(podezd); 75 | variantFloor.add(floor); 76 | } 77 | } 78 | 79 | const podezdArr = [...variantPodezd]; 80 | const floorArr = [...variantFloor]; 81 | 82 | if (podezdArr.length === 0 || floorArr.length === 0) { 83 | newAddr.podezd = -1; 84 | newAddr.floor = -1; 85 | } else { 86 | newAddr.podezd = podezdArr.length === 1 ? podezdArr[0] : 0; 87 | newAddr.floor = floorArr.length === 1 ? floorArr[0] : 0; 88 | } 89 | 90 | return [newAddr.podezd, newAddr.floor].join(' '); 91 | } 92 | 93 | export default inputProcessing; 94 | -------------------------------------------------------------------------------- /september_2021_B/lesson_4/D.js: -------------------------------------------------------------------------------- 1 | /** 2 | * "D. Выборы Государственной Думы" {@link "https://contest.yandex.ru/contest/28970/problems/D/} 3 | * 4 | * Необходимо распределить 450 мест между партиями, участвовавших в выборах. 5 | * 6 | * @param { string } text список партий, участвовавших в выборах. Каждая строка входного файла 7 | * содержит название партии (строка, возможно, содержащая пробелы), затем, через пробел, количество 8 | * голосов, полученных данной партией – число, не превосходящее 10^8. 9 | * 10 | * @return { string[] } вывести названия всех партий и количество голосов в парламенте, полученных 11 | * данной партией. Названия необходимо выводить в том же порядке, в котором они шли во входных 12 | * данных. 13 | */ 14 | function calcPartyVotes(partyWithVotes) { 15 | const STATE_DUMA_MAX_PLACES = 450; 16 | let placesFree = STATE_DUMA_MAX_PLACES; 17 | let sumVotes = 0; 18 | const votesByParty = new Map(); 19 | 20 | // Сначала подсчитывается сумма голосов избирателей, поданных за каждую партию и подсчитывается 21 | // сумма голосов, поданных за все партии. 22 | for (let index = 0; index < partyWithVotes.length; index++) { 23 | const [party, votesCount] = partyWithVotes[index]; 24 | sumVotes += votesCount; 25 | votesByParty.set(party, (votesByParty.get(party) || 0) + votesCount); 26 | } 27 | 28 | // сумма голосов, поданных за все партии делится на 450, получается величина, называемая “первое избирательное частное” 29 | // (смысл первого избирательного частного - это количество голосов избирателей, которое 30 | // необходимо набрать для получения одного места в парламенте) 31 | const votesToOnePlace = sumVotes / placesFree; 32 | const parties = [...votesByParty.keys()]; 33 | const partiesFractionPartRaw = []; 34 | 35 | for (let index = 0; index < parties.length; index++) { 36 | const party = parties[index]; 37 | const placesRaw = votesByParty.get(party) / votesToOnePlace; 38 | partiesFractionPartRaw[index] = { party, fractPart: placesRaw % 1 }; 39 | 40 | // каждая партия получает столько мест, чему равна целая часть от деления числа голосов за данную партию на первое избирательное частное 41 | const places = Math.floor(placesRaw); 42 | votesByParty.set(party, places); 43 | 44 | placesFree -= places; 45 | } 46 | 47 | // Если после первого раунда распределения мест сумма количества мест, отданных партиям, меньше 48 | // 450, то оставшиеся места передаются по одному партиям, в порядке убывания дробной части частного 49 | // от деления числа голосов за данную партию на первое избирательное частное. 50 | // Если же для двух партий эти дробные части равны, то преимущество отдается той партии, которая 51 | // получила большее число голосов. 52 | const partiesFractionPart = partiesFractionPartRaw.sort( 53 | (prev, next) => 54 | next.fractPart - prev.fractPart || 55 | votesByParty.get(next.party) - votesByParty.get(prev.party) 56 | ); 57 | 58 | let index = 0; 59 | while (placesFree > 0) { 60 | const { party } = partiesFractionPart[index]; 61 | votesByParty.set(party, votesByParty.get(party) + 1); 62 | 63 | index = (index + 1) % partiesFractionPart.length; 64 | placesFree -= 1; 65 | } 66 | 67 | return parties.map((party) => `${party} ${votesByParty.get(party)}`); 68 | } 69 | 70 | function inputProcessing(lines) { 71 | const partyWithVotes = lines.map((line) => { 72 | const party = line.split(' '); 73 | const votes = party.pop(); 74 | 75 | return [party.join(' '), Number(votes)]; 76 | }); 77 | 78 | return calcPartyVotes(partyWithVotes); 79 | } 80 | 81 | export default inputProcessing; 82 | -------------------------------------------------------------------------------- /june_2021/lesson_2/I.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27472/problems/I/ 2 | 3 | // Вам необходимо построить поле для игры "Сапер" по его конфигурации – размерам и координатам расставленных на нем мин. 4 | 5 | // Вкратце напомним правила построения поля для игры "Сапер": 6 | 7 | // Поле состоит из клеток с минами и пустых клеток 8 | // Клетки с миной обозначаются символом * 9 | // Пустые клетки содержат число ki,j, 0≤ ki, j ≤ 8 – количество мин на соседних клетках. 10 | // Соседними клетками являются восемь клеток, имеющих смежный угол или сторону. 11 | 12 | // Формат ввода 13 | // В первой строке содержатся три числа: N, 1 ≤ N ≤ 100 - количество строк на поле, M, 1 ≤ M ≤ 100 14 | // - количество столбцов на поле, K, 0 ≤ K ≤ N ⋅ M - количество мин на поле. 15 | 16 | // В следующих K строках содержатся по два числа с координатами мин: p, 1 ≤ p ≤ N - номер строки 17 | // мины, q, 1 ≤ 1 ≤ M - номер столбца мины. 18 | 19 | // Формат вывода 20 | // Выведите построенное поле, разделяя строки поля переводом строки, а столбцы - пробелом. 21 | 22 | function inputProcessing(lines) { 23 | const [config, ...minesYXRaw] = lines; 24 | const [Y, X, MINES] = config.split(' ').map(Number); 25 | const minesXY = minesYXRaw.map((yx) => yx.split(' ').map(Number)); 26 | // console.log({ X, Y, MINES }); 27 | // console.log({ minesXY }); 28 | const mapDefinitionToSymbol = { MINE: '*', ZERO_MINES_NEARBY: 0 }; 29 | 30 | class Minesweeper { 31 | constructor(x = 9, y = 9, mines = 10) { 32 | if (mines > x * y) { 33 | throw new Error('ERROR: mines more than cell'); 34 | } 35 | this.x = x; 36 | this.y = y; 37 | this.mines = mines; 38 | 39 | this.init(); 40 | } 41 | 42 | _initFieldAndFillValue(value) { 43 | return Array.from({ length: this.y }, () => 44 | new Array(this.x).fill(value) 45 | ); 46 | } 47 | 48 | _getArea8(cellX, cellY) { 49 | const area8 = []; 50 | for (let y = cellY - 1; y <= cellY + 1; y += 1) { 51 | for (let x = cellX - 1; x <= cellX + 1; x += 1) { 52 | if ( 53 | y >= 0 && 54 | y < this.y && 55 | x >= 0 && 56 | x < this.x && 57 | !(cellX === x && cellY === y) 58 | ) { 59 | area8.push({ x, y }); 60 | } 61 | } 62 | } 63 | return area8; 64 | } 65 | 66 | _increaseMineCounterInArea8(mineX, mineY) { 67 | this._getArea8(mineX, mineY).forEach(({ x, y }) => { 68 | const cellValue = this.field[y][x]; 69 | if (cellValue !== mapDefinitionToSymbol.MINE) { 70 | this.field[y][x] = cellValue + 1; 71 | } 72 | }); 73 | } 74 | 75 | _calculateMinesAndSetCounterValues() { 76 | this.field.forEach((row, y) => 77 | row.forEach((cell, x) => { 78 | if (cell === mapDefinitionToSymbol.MINE) { 79 | this._increaseMineCounterInArea8(x, y); 80 | } 81 | }) 82 | ); 83 | } 84 | 85 | _initMines() { 86 | for (const [y, x] of minesXY) { 87 | this.field[y - 1][x - 1] = mapDefinitionToSymbol.MINE; 88 | } 89 | } 90 | 91 | init() { 92 | this.field = this._initFieldAndFillValue( 93 | mapDefinitionToSymbol.ZERO_MINES_NEARBY 94 | ); 95 | this._initMines(); 96 | this._calculateMinesAndSetCounterValues(); 97 | } 98 | } 99 | 100 | const game = new Minesweeper(X, Y, MINES); 101 | 102 | return game.field.map((y) => y.join(' ')); 103 | } 104 | 105 | (async () => { 106 | // const inputLines = ['3 2 2', '1 1', '2 2']; 107 | const inputLines = ['4 4 4', '1 3', '2 1', '4 2', '4 4']; 108 | console.log({ inputLines }); 109 | 110 | const outputLines = inputProcessing(inputLines); 111 | console.log({ outputLines }); 112 | })(); 113 | 114 | export default inputProcessing; 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Тренировки по алгоритмам от Яндекса 2 | 3 | [![wakatime](https://wakatime.com/badge/github/feeedback/yandex-algorithm-training.svg)](https://wakatime.com/badge/github/feeedback/yandex-algorithm-training) 4 | 5 | Каждый поток: 6 | 7 | - 8 лекций с домашними заданиями на платформе Яндекс.Контест и ответы на ваши вопросы; 8 | - 20 задач в неделю (домашних заданий) 9 | - 4 видео-трансляции с проверкой домашних заданий, разбором решений и популярных ошибок. 10 | 11 | ### Содержание 12 | 13 | 1. "Сложность, тестирование, особые случаи" [**(** лекция **)**](https://www.youtube.com/watch?v=QLhqYNsPIVo) 14 | 2. "Линейный поиск" [**(** лекция **)**](https://www.youtube.com/watch?v=SKwB41FrGgU) 15 | 3. "Множества" [**(** лекция **)**](https://www.youtube.com/watch?v=PUpmV2ieIHA) 16 | 4. "Словари и сортировка подсчётом" [**(** лекция **)**](https://www.youtube.com/watch?v=Nb5mW1yWVSs) 17 | 5. "Префиксные суммы и два указателя" [**(** лекция **)**](https://www.youtube.com/watch?v=de28y8Dcvkg) 18 | 6. "Бинарный поиск" [**(** лекция **)**](https://www.youtube.com/watch?v=YENpZexHfuk) 19 | 7. "Сортировка событий" [**(** лекция **)**](https://www.youtube.com/watch?v=hGixDBO-p6Q) 20 | 8. "Деревья" [**(** лекция **)**](https://www.youtube.com/watch?v=lEJzqHgyels) 21 | 22 | ### Июнь 2021 23 | 24 | 1. [контест](https://contest.yandex.ru/contest/27393/problems/) | [решение](june_2021/lesson_1/) 10/11 25 | 2. [контест](https://contest.yandex.ru/contest/27472/problems/) | [решение](june_2021/lesson_2/) 10/10 26 | 3. [контест](https://contest.yandex.ru/contest/27663/problems/) | [решение](june_2021/lesson_3/) 9/10 27 | 4. [контест](https://contest.yandex.ru/contest/27665/problems/) | [решение](june_2021/lesson_4/) 10/10 28 | 5. [контест](https://contest.yandex.ru/contest/27794/problems/) | [решение](june_2021/lesson_5/) 2/8 29 | 6. [контест](https://contest.yandex.ru/contest/27844/problems/) | [решение](june_2021/lesson_6/) 3/11 30 | 7. [контест](https://contest.yandex.ru/contest/27883/problems/) | _решение_ 0/10 31 | 8. [контест](https://contest.yandex.ru/contest/28069/problems/) | _решение_ 0/10 32 | 33 | ### Сентябрь 2021 34 | 35 | _Дивизион ***B***_ 36 | 37 | 1. [контест](https://contest.yandex.ru/contest/28730/problems/) | [решение](september_2021_B/lesson_1/) 5/5 38 | 2. [контест](https://contest.yandex.ru/contest/28738/problems/) | [решение](september_2021_B/lesson_2/) 5/5 39 | 3. [контест](https://contest.yandex.ru/contest/28964/problems/) | [решение](september_2021_B/lesson_3/) 5/5 40 | 4. [контест](https://contest.yandex.ru/contest/28970/problems/) | [решение](september_2021_B/lesson_4/) 5/5 41 | 5. [контест](https://contest.yandex.ru/contest/29075/problems/) | _решение_ 0/5 42 | 6. [контест](https://contest.yandex.ru/contest/29188/problems/) | [решение](september_2021_B/lesson_6/) 2/5 43 | 7. [контест](https://contest.yandex.ru/contest/29396/problems/) | [решение](september_2021_B/lesson_7/) 3/5 44 | 45 | _Дивизион **A**_ 46 | 47 | 1. [контест](https://contest.yandex.ru/contest/28724/problems/) | [решение](september_2021_A/lesson_1/) 2/5 48 | 49 | ### Февраль 2023 50 | 51 | _Дивизион **B**_ 52 | 53 | 1. [контест 1-10](https://contest.yandex.ru/contest/45468/problems/) | [решение](february_2023_B/lesson_1/) 9/10 (_Блок_ "закрепление предыдущих Тренировок" - _лекции 1-8_) 54 | 55 | ### Март 2024 56 | 57 | _также делаю решение на Go_ 58 | 59 | 1. [контест](https://contest.yandex.ru/contest/59539/problems/) | [решение](march_2024/lesson_1/) 2/10 60 | 61 | **Для запуска тестов**: `npm test [filepath]` 62 | 63 | **Как отправляю решение в Я.Контест:** 64 | 65 | - копирую/вставляю функцию с обработки логики `inputProcessing` из файла конкретной задачи, 66 | - копирую/вставляю содержимое файла [`contest-io-template.js`](https://github.com/feeedback/yandex-interview-contest/tree/main/contest-io-template.js), для обработки ввода-вывода 67 | 68 | _(Если решение с выводом понемногу в функции логики (для производительности), то копирую уже цельный код из файла конкретной задачи)_ 69 | -------------------------------------------------------------------------------- /june_2021/lesson_1/H.js: -------------------------------------------------------------------------------- 1 | // На некоторых кросс-платформенных станциях метро (как, например, «Третьяковская») на разные стороны платформы приходят поезда разных направлений. 2 | // Таня договорилась встретиться с подругой на такой станции, 3 | // но поскольку подруга приехала из другого часового пояса, то из - за джетлага сильно проспала, и Тане пришлось долго её ждать. 4 | // Поезда всегда ходят точно по расписанию, и Таня знает, что поезд стоит на платформе ровно одну минуту, 5 | // а интервал между поездами(время, в течение которого поезда у платформы нет) составляет 6 | // a минут для поездов на первом пути и b минут для поездов на втором пути.То есть на первый путь приезжает поезд и стоит одну минуту, 7 | // затем в течение a минут поезда у платформы нет, затем в течение одной минуты у платформы стоит следующий поезд и т.д. 8 | 9 | // Пока Таня стояла на платформе, она насчитала n поездов на первом пути и m поездов на втором пути. 10 | // Определите минимальное и максимальное время, которое Таня могла провести на платформе, или сообщите, что она точно сбилась со счёта. 11 | 12 | // Все поезда, которые видела Таня, она наблюдала в течение всей минуты, 13 | // то есть Таня не приходит и не уходит с платформы посередине той минуты, когда поезд стоит на платформе. 14 | 15 | // Формат ввода 16 | // Первая строка входных данных содержит число a — интервал между поездами на первом пути. 17 | // Вторая строка содержит число b — интервал между поездами на втором пути. 18 | // Третья строка содержит число n — количество поездов на первом пути, которые увидела Таня. 19 | // Четвёртая строка содержит число m — количество поездов на втором пути, которые увидела Таня. 20 | // Все числа — целые, от 1 до 1000. 21 | 22 | // Формат вывода 23 | // Программа должна вывести два числа: минимальное и максимальное время в минутах, 24 | // которое Таня могла стоять на платформе, или одно число - 1, если Таня точно ошиблась. 25 | 26 | // import { input, output } from '../../input-output_dev.js'; 27 | 28 | // https://contest.yandex.ru/contest/27393/problems/H/ 29 | 30 | function inputProcessing(lines) { 31 | const getMinTimeGeneral = (timeOnStation, timeInWay, n) => 32 | timeOnStation * n + timeInWay * (n - 1); 33 | const getMaxTimeGeneral = (timeOnStation, timeInWay, n) => 34 | getMinTimeGeneral(timeOnStation, timeInWay, n) + timeInWay * 2; 35 | // const getMaxTimeGeneral = (timeOnStation, timeInWay, n) => 36 | // timeOnStation * n + timeInWay * (n - 1) + timeInWay * 2; 37 | 38 | const TIME_TRAIN_AT_STATION = 1; 39 | // const getMinTime = (timeInWay, n) => getMinTimeGeneral(timeTrainAtStation, timeInWay, n); 40 | const getMinTime = getMinTimeGeneral.bind(null, TIME_TRAIN_AT_STATION); 41 | const getMaxTime = getMaxTimeGeneral.bind(null, TIME_TRAIN_AT_STATION); 42 | 43 | const [ 44 | interval1, // a — интервал между поездами на первом пути. 45 | interval2, // b — интервал между поездами на втором пути. 46 | n1, // n — количество поездов на первом пути, которые увидела Таня. 47 | n2, // m — количество поездов на втором пути, которые увидела Таня 48 | ] = lines.map(Number); 49 | 50 | // [1, intervalTrainWay1, 1, intervalTrainWay1, ...] 51 | // [1, intervalTrainWay2, 1, intervalTrainWay2, ...] 52 | const [min1, max1] = [getMinTime(interval1, n1), getMaxTime(interval1, n1)]; 53 | const [min2, max2] = [getMinTime(interval2, n2), getMaxTime(interval2, n2)]; 54 | console.log({ 1: [min1, max1], 2: [min2, max2] }); 55 | if (min1 > max2 || min2 > max1) { 56 | return -1; 57 | } 58 | return [Math.max(min1, min2), Math.min(max1, max2)]; 59 | } 60 | 61 | (async () => { 62 | // const inputLines = await input(1); 63 | const inputLines = [3, 2, 7, 11]; 64 | // const inputLines = [1, 5, 1, 2]; -1 65 | console.log({ inputLines }); 66 | const outputLines = inputProcessing(inputLines); 67 | console.log({ outputLines }); 68 | console.log({ EXPECT: ['?'] }); 69 | // output(outputLines); 70 | })(); 71 | export default inputProcessing; 72 | -------------------------------------------------------------------------------- /june_2021/lesson_4/I.js: -------------------------------------------------------------------------------- 1 | // https://contest.yandex.ru/contest/27665/problems/I 2 | 3 | // Учительница задала Пете домашнее задание — в заданном тексте расставить ударения в словах, после 4 | // чего поручила Васе проверить это домашнее задание. Вася очень плохо знаком с данной темой, 5 | // поэтому он нашел словарь, в котором указано, как ставятся ударения в словах. К сожалению, в этом 6 | // словаре присутствуют не все слова. Вася решил, что в словах, которых нет в словаре, он будет 7 | // считать, что Петя поставил ударения правильно, если в этом слове Петей поставлено ровно одно 8 | // ударение. Оказалось, что в некоторых словах ударение может быть поставлено больше, чем одним 9 | // способом. Вася решил, что в этом случае если то, как Петя поставил ударение, соответствует 10 | // одному из приведенных в словаре вариантов, он будет засчитывать это как правильную расстановку 11 | // ударения, а если не соответствует, то как ошибку. Вам дан словарь, которым пользовался Вася и 12 | // домашнее задание, сданное Петей. Ваша задача — определить количество ошибок, которое в этом 13 | // задании насчитает Вася. 14 | 15 | // Формат ввода 16 | // Вводится сначала число N — количество слов в словаре (0≤N≤20000). Далее идет N строк со словами 17 | // из словаря. Каждое слово состоит не более чем из 30 символов. Все слова состоят из маленьких и 18 | // заглавных латинских букв. В каждом слове заглавная ровно одна буква — та, на которую попадает 19 | // ударение. Слова в словаре расположены в алфавитном порядке. Если есть несколько возможностей 20 | // расстановки ударения в одном и том же слове, то эти варианты в словаре идут в произвольном 21 | // порядке. Далее идет упражнение, выполненное Петей. Упражнение представляет собой строку текста, 22 | // суммарным объемом не более 300000 символов. Строка состоит из слов, которые разделяются между 23 | // собой ровно одним пробелом. Длина каждого слова не превышает 30 символов. Все слова состоят из 24 | // маленьких и заглавных латинских букв (заглавными обозначены те буквы, над которыми Петя поставил 25 | // ударение). Петя мог по ошибке в каком-то слове поставить более одного ударения или не поставить 26 | // ударения вовсе. 27 | 28 | // Формат вывода 29 | // Выведите количество ошибок в Петином тексте, которые найдет Вася. 30 | 31 | // import fs from 'fs'; 32 | // import readline from 'readline'; 33 | 34 | // const rl = readline.createInterface({ 35 | // input: fs.createReadStream('input.txt'), 36 | // output: process.stdout, 37 | // }); 38 | // const inputLines = []; 39 | 40 | // rl.on('line', (data) => { 41 | // inputLines.push(data.toString().trim()); 42 | // }); 43 | 44 | // rl.on('close', () => { 45 | // console.log({ inputLines }); 46 | // const outputLines = inputProcessing(inputLines); 47 | // console.log({ outputLines }); 48 | // }); 49 | 50 | function inputProcessing(lines) { 51 | const wordCountInDict = Number(lines[0]); // (0≤N≤20000) 52 | const strWords = lines[lines.length - 1].split(' '); // строка <=300000 символов 53 | if (strWords[0] === '') { 54 | return 0; 55 | } 56 | const dictWithStress = new Set(lines.slice(1, 1 + wordCountInDict)); // слово <= 30 символов 57 | const dict = new Set( 58 | lines.slice(1, 1 + wordCountInDict).map((word) => word.toLowerCase()) 59 | ); // слово <= 30 символов 60 | 61 | let errors = 0; 62 | for (const word of strWords) { 63 | const stressCount = (word.match(/[A-Z]/g) || []).length; 64 | 65 | if ( 66 | !dict.has(word.toLowerCase()) 67 | ? stressCount !== 1 68 | : !dictWithStress.has(word) 69 | ) { 70 | errors += 1; 71 | } 72 | } 73 | return errors; 74 | } 75 | 76 | // (async () => { 77 | // // const inputLines = [4, 'cAnnot', 'cannOt', 'fOund', 'pAge', 'thE pAge cAnnot be found']; 78 | // // const inputLines = [4, 'cAnnot', 'cannOt', 'fOund', 'pAge', 'thE pAge cAnnot be found']; 79 | // console.log({ inputLines }); 80 | // const outputLines = inputProcessing(inputLines); 81 | // console.log({ outputLines }); 82 | // // assert.equal(outputLines, 2); 83 | // })(); 84 | 85 | export default inputProcessing; 86 | -------------------------------------------------------------------------------- /september_2021_B/lesson_7/C_draft.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @todo DRAFT version, solution not ready 3 | * 4 | * "C. Минимальное покрытие" {@link "https://contest.yandex.ru/contest/29396/problems/C/} 5 | * 6 | * На прямой задано некоторое множество отрезков с целочисленными координатами концов [Li, Ri]. 7 | * Выберите среди данного множества подмножество отрезков, целиком покрывающее отрезок [0, M], (M — 8 | * натуральное число), содержащее наименьшее число отрезков. 9 | * 10 | * @param { number } querySize - длина требуемого отрезка [0, M] (1 ≤ M ≤ 5000) 11 | * @param { Array } segments - Li и Ri (Li, Ri ≤ 50000). Список завершается парой нулей. 12 | * Общее число отрезков не превышает 100 000 13 | * 14 | * @return { number } В первой строке выходного файла выведите минимальное число отрезков, 15 | * необходимое для покрытия отрезка [0; M]. 16 | * Далее выведите список покрывающего подмножества, упорядоченный по возрастанию координат левых 17 | * концов отрезков. Список отрезков выводится в том же формате, что и во входе. Завершающие два 18 | * нуля выводить не нужно. 19 | * Если покрытие отрезка [0, M] исходным множеством отрезков [Li, Ri] невозможно, то следует 20 | * вывести единственную фразу “No solution”. 21 | */ 22 | function minCountSegmentsCoverQuerySegment22(querySize, segments) { 23 | const EVENT_TYPE = { begin: 'BEGIN', end: 'END' }; 24 | const EVENT_TYPE_ORDER = { [EVENT_TYPE.end]: 0, [EVENT_TYPE.begin]: 1 }; // сначала завершение 25 | const events = []; 26 | 27 | for (let i = 0; i < segments.length; i++) { 28 | const [begin, end] = segments[i]; 29 | 30 | events.push({ time: begin, type: EVENT_TYPE.begin, size: end - begin + 1 }); 31 | events.push({ time: end, type: EVENT_TYPE.end, size: end - begin + 1 }); 32 | } 33 | 34 | events.sort( 35 | (prev, next) => 36 | prev.time - next.time || 37 | EVENT_TYPE_ORDER[prev.type] - EVENT_TYPE_ORDER[next.type] 38 | ); 39 | 40 | console.log({ querySize, events }); 41 | 42 | let nowCount = 0; 43 | let minCount = segments.length + 1; 44 | 45 | let nowSize = 0; 46 | // В ЭТОЙ ЗАДАЧЕ ВАЖНО ПОЛОЖЕНИЕ, А НЕ ТОЛЬКО ДЛИНА ЗАНИМАЕМОГО ОТРЕЗКА 47 | 48 | for (let i = 0; i < events.length; i++) { 49 | console.log({ i, nowSize, minCount }); 50 | // if (i !== nowCount > 0) { 51 | // atLeastOneLength += events[i].time - events[i - 1].time; 52 | // } 53 | 54 | if (events[i].type === EVENT_TYPE.end) { 55 | nowSize -= events[i].size; 56 | nowCount -= 1; 57 | } else if (events[i].type === EVENT_TYPE.begin) { 58 | nowSize += events[i].size; 59 | nowCount += 1; 60 | } 61 | 62 | if (nowSize === querySize) { 63 | minCount = Math.min(minCount, nowCount); 64 | } 65 | console.log({ i, nowSize, minCount }); 66 | } 67 | 68 | return minCount; 69 | } 70 | 71 | const minCountSegmentsCoverQuerySegment = (querySize, segments = []) => { 72 | let cursorCurrentRight = 0; 73 | let cursorNextRight = 0; 74 | 75 | let currentSegment = segments[0]; 76 | const result = []; 77 | 78 | for (const segment of segments) { 79 | const [left, right] = segment; 80 | 81 | if (left > cursorCurrentRight) { 82 | result.push(currentSegment); 83 | 84 | cursorCurrentRight = cursorNextRight; 85 | 86 | if (cursorCurrentRight >= querySize) { 87 | break; 88 | } 89 | } 90 | 91 | if (left <= cursorCurrentRight && right > cursorNextRight) { 92 | cursorNextRight = right; 93 | currentSegment = segment; 94 | } 95 | } 96 | 97 | if (cursorCurrentRight < querySize) { 98 | cursorCurrentRight = cursorNextRight; 99 | result.push(currentSegment); 100 | } 101 | 102 | if (cursorCurrentRight < querySize) { 103 | return 'No solution'; 104 | } 105 | return [String(result.length), ...result.map((lr) => lr.join(' '))]; 106 | }; 107 | 108 | function inputProcessing(lines) { 109 | const querySize = Number(lines[0]); 110 | const segmentsLR = lines.slice(1, -1).map((lr) => lr.split(' ').map(Number)); 111 | 112 | return minCountSegmentsCoverQuerySegment(querySize, segmentsLR); 113 | } 114 | 115 | export default inputProcessing; 116 | --------------------------------------------------------------------------------