chore(i18n,curriculum): processed translations - new ukrainian (#44447)

This commit is contained in:
camperbot
2021-12-10 11:14:24 +05:30
committed by GitHub
parent 8651ee1797
commit 0473dedf47
1663 changed files with 156692 additions and 1 deletions

View File

@@ -0,0 +1,67 @@
---
id: 594810f028c0303b75339acb
title: 100 дверей
challengeType: 5
forumTopicId: 302217
dashedName: 100-doors
---
# --description--
Перед початком закриті усі 100 дверей у ряді. Ви створюєте 100 проходів біля дверей. При першому проходженні завітайте до кожних дверей та "переключіть" їх (якщо двері зачинені, то відчиніть їх; якщо ж відчинені - зачиніть). Удруге відвідайте кожні другі двері (тобто двері №2, №4, №6,...) і переключіть їх. У третій раз зайдіть до кожної третьої двері (тобто №3, №6, №9,...) тощо, поки ви не відвідаєте сотих дверей.
# --instructions--
Реалізуйте функцію, щоб визначити стан дверей після останнього проходження. Поверніть кінцевий результат в масив тільки з тими номерами дверей, які включені в масив, якщо ті відчинені.
# --hints--
`getFinalOpenedDoors` має бути функцією.
```js
assert(typeof getFinalOpenedDoors === 'function');
```
`getFinalOpenedDoors` має повернути масив.
```js
assert(Array.isArray(getFinalOpenedDoors(100)));
```
`getFinalOpenedDoors` має досягти правильного результату.
```js
assert.deepEqual(getFinalOpenedDoors(100), solution);
```
# --seed--
## --after-user-code--
```js
const solution = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100];
```
## --seed-contents--
```js
function getFinalOpenedDoors(numDoors) {
}
```
# --solutions--
```js
function getFinalOpenedDoors(numDoors) {
// this is the final pattern (always squares).
// thus, the most efficient solution simply returns an array of squares up to numDoors).
const finalState = [];
let i = 1;
while (Math.pow(i, 2) <= numDoors) {
finalState.push(Math.pow(i, 2));
i++;
}
return finalState;
}
```

View File

@@ -0,0 +1,203 @@
---
id: 5951e88f64ebf159166a1176
title: Гра 24
challengeType: 5
forumTopicId: 302218
dashedName: 24-game
---
# --description--
[ Гра 24](https://en.wikipedia.org/wiki/24_Game) тестує можливість людини обчислювати в умі.
Мета гри - впорядкувати чотири числа так, щоб при обчислюванні, результат дорівнював 24
# --instructions--
Реалізуйте функцію, яка бере за аргумент рядок з чотирьох цифр, причому кожна цифра від 1 до 9 (включно) з дозволеними повторами, що повертає арифметичний вираз, що буде дорівнювати 24. Якщо ж такого рішення не існує, то поверніть "рішення не існує".
**Правила:**
<ul>
<li> Дозволені тільки такі оператори/функції: множення, ділення, додавання, віднімання. </li>
<li> Для збереження остачі при діленні, слід використовувати арифметику з плаваючою комою, раціональну арифметику тощо. </li>
<li> Формування багаторозрядних чисел з даних чисел не допускається. (Отже, відповідь 12 + 12 з даними 1, 2, 2 і 1 неправильна). </li>
<li> Порядок цифр, коли він даний, не має зберігатися. </li>
</ul>
| Приклад вхідний | Приклад вихідний |
| ------------------------- | ------------------------- |
| <code>solve24("4878");</code> | <code>(7-8/8)\*4</code> |
| <code>solve24("1234");</code> | <code>3\*1\*4\*2</code> |
| <code>solve24("6789");</code> | <code>(6\*8)/(9-7)</code> |
| <code>solve24("1127");</code> | <code>(1+7)\*(2+1)</code> |
# --hints--
`solve24` має бути функцією.
```js
assert(typeof solve24 === 'function');
```
`solve24("4878")` має повернути `(7-8/8)*4` чи `4*(7-8/8)`
```js
assert(include(answers[0], removeParentheses(solve24(testCases[0]))));
```
`solve24("1234")` повинен повернути будь-яке розташування `1*2*3*4`
```js
assert(include(answers[1], removeParentheses(solve24(testCases[1]))));
```
`solve24("6789")` повинен повернути `(6*8)/(9-7)` чи `(8*6)/(9-7)`
```js
assert(include(answers[2], removeParentheses(solve24(testCases[2]))));
```
`solve24("1127")` має повернути перестановку `(1+7)*(1+2)`
```js
assert(include(answers[3], removeParentheses(solve24(testCases[3]))));
```
# --seed--
## --after-user-code--
```js
const testCases = [
'4878',
'1234',
'6789',
'1127'
];
const answers = [
['(7-8/8)*4', '4*(7-8/8)', '(4-8+7)*8', '(4+7-8)*8', '(7+4-8)*8', '(7-8+4)*8', '8*(4-8+7)', '8*(4+7-8)', '8*(7+4-8)', '8*(7-8+4)'],
['1*2*3*4', '1*2*4*3', '1*3*2*4', '1*3*4*2', '1*4*2*3', '1*4*3*2', '2*1*3*4', '2*1*4*3', '2*3*1*4', '2*3*4*1', '2*4*3*1', '2*4*1*3', '3*1*2*4', '3*1*4*2', '3*2*1*4', '3*2*4*1', '3*4*1*2', '3*4*2*1', '4*1*2*3', '4*1*3*2', '4*2*1*3', '4*2*3*1', '4*3*1*2', '4*3*2*1', '(1+2+3)*4', '(1+3+2)*4', '(2+1+3)*4', '(2+3+1)*4', '(3+1+2)*4', '(3+2+1)*4', '4*(1+2+3)', '4*(2+1+3)', '4*(2+3+1)', '4*(3+1+2)', '4*(3+2+1)'],
['(6*8)/(9-7)', '(8*6)/(9-7)', '6*8/(9-7)', '8*6/(9-7)'],
['(1+7)*(2+1)', '(1+7)*(1+2)', '(1+2)*(1+7)', '(1+2)*(7+1)', '(2+1)*(1+7)', '(7+1)*(2+1)']
];
function include(ansArr, res) {
const index = ansArr.indexOf(res);
return index >= 0;
}
//The main method for detecting single parentheses
function removeParentheses(ans) {
for (let i = 0; i < ans.length; i++) {
if (!isNaN(ans[i])) {
ans = removeParenthesesHelper(ans, i);
}
}
return ans;
}
//Helper to remove left and right parantheses
function removeParenthesesHelper(ans, i) {
while (i > 0 && i < ans.length - 1) {
if (ans[i - 1] === '(' && ans[i + 1] === ')') {
//Paranthesis detected. Remove them.
ans = replaceChar(ans, '', i - 1);
ans = replaceChar(ans, '', i);
i--;
} else {
return ans;
}
}
return ans;
}
//Replace a character at a given index for the provided character
function replaceChar(origString, replaceChar, index) {
let firstPart = origString.substr(0, index);
let lastPart = origString.substr(index + 1);
let newString = firstPart + replaceChar + lastPart;
return newString;
}
```
## --seed-contents--
```js
function solve24 (numStr) {
return true;
}
```
# --solutions--
```js
function solve24(numStr) {
const digitsArr = numStr.split('');
const answers = [];
const digitPermutations = [];
const operatorPermutations = [];
function generateDigitPermutations (digits, permutations = []) {
if (digits.length === 0) {
digitPermutations.push(permutations);
}
else {
for (let i = 0; i < digits.length; i++) {
const curr = digits.slice();
const next = curr.splice(i, 1);
generateDigitPermutations(curr.slice(), permutations.concat(next));
}
}
}
function generateOperatorPermutations (permutations = []) {
const operators = ['+', '-', '*', '/'];
if (permutations.length === 3) {
operatorPermutations.push(permutations);
}
else {
for (let i = 0; i < operators.length; i++) {
const curr = permutations.slice();
curr.push(operators[i]);
generateOperatorPermutations(curr);
}
}
}
generateDigitPermutations(digitsArr);
generateOperatorPermutations();
interleave();
return answers[0];
function interleave () {
for (let i = 0; i < digitPermutations.length; i++) {
for (let j = 0; j < operatorPermutations.length; j++) {
const d = digitPermutations[i];
const o = operatorPermutations[j];
const perm = [
`${d[0]}${o[0]}${d[1]}${o[1]}${d[2]}${o[2]}${d[3]}`,
`(${d[0]}${o[0]}${d[1]})${o[1]}${d[2]}${o[2]}${d[3]}`,
`${d[0]}${o[0]}(${d[1]}${o[1]}${d[2]})${o[2]}${d[3]}`,
`${d[0]}${o[0]}${d[1]}${o[1]}(${d[2]}${o[2]}${d[3]})`,
`${d[0]}${o[0]}(${d[1]}${o[1]}${d[2]}${o[2]}${d[3]})`,
`(${d[0]}${o[0]}${d[1]}${o[1]}${d[2]})${o[2]}${d[3]}`,
`(${d[0]}${o[0]}${d[1]})${o[1]}(${d[2]}${o[2]}${d[3]})`
];
perm.forEach(combination => {
const res = eval(combination);
if (res === 24) {
return answers.push(combination);
}
});
}
}
}
}
```

View File

@@ -0,0 +1,116 @@
---
id: 5949b579404977fbaefcd736
title: Ціле число "9 мільярдів імен Бога"
challengeType: 5
forumTopicId: 302219
dashedName: 9-billion-names-of-god-the-integer
---
# --description--
Це завдання є варіацією [оповідання Артура Кларка](https://en.wikipedia.org/wiki/The Nine Billion Names of God#Plot_summary "wp: The Nine Billion Names of God#Plot_summary").
(Той хто розв'язує завдання, має знати про наслідки виконання даного завдання.)
Детальніше про те, що означає "name"(ім'я):
<ul>
<li>Ціле число 1 має 1 ім'я "1".</li>
<li>Ціле число 2 має 2 ім'я "1+1" і "2".</li>
<li>Ціле число 3 має 3 ім'я "1+1+1", "2+1" і "3".</li>
<li>Ціле число 4 має 5 імен "1+1+1+1", "2+1+1", "2+2", "3+1", "4".</li>
<li>Ціле число 5 має 7 імен "1+1+1+1+1", "2+1+1+1", "2+2+1", "3+1+1", "3+2", "4+1", "5".</li>
</ul>
Це можна візуалізувати наступним чином:
<pre> 1
1 1
1 1 1
1 2 1 1
1 2 2 1 1
1 3 3 2 1 1
</pre>
Де рядки $n$ відповідають цілому числу $n$ і кожна колонка $C$ у рядку $m$ зліва направо відповідає кількості імен, які починаються з $C$.
Зауважте, що сума $n$-го рядку $P(n)$ - це функція розбиття цілого числа.
# --instructions--
Використовуйте функцію, що повертає суму $n$-го рядка.
# --hints--
`numberOfNames` має бути функцією.
```js
assert(typeof numberOfNames === 'function');
```
`numberOfNames(5)` має дорівнювати 7.
```js
assert.equal(numberOfNames(5), 7);
```
`numberOfNames(12)` має дорівнювати 77.
```js
assert.equal(numberOfNames(12), 77);
```
`numberOfNames(18)` має дорівнювати 385.
```js
assert.equal(numberOfNames(18), 385);
```
`numberOfNames(23)` має дорівнювати 1255.
```js
assert.equal(numberOfNames(23), 1255);
```
`numberOfNames(42)` має дорівнювати 53174.
```js
assert.equal(numberOfNames(42), 53174);
```
`numberOfNames(123)` має дорівнювати 2552338241.
```js
assert.equal(numberOfNames(123), 2552338241);
```
# --seed--
## --seed-contents--
```js
function numberOfNames(num) {
return true;
}
```
# --solutions--
```js
function numberOfNames(num) {
const cache = [
[1]
];
for (let l = cache.length; l < num + 1; l++) {
let Aa;
let Mi;
const r = [0];
for (let x = 1; x < l + 1; x++) {
r.push(r[r.length - 1] + (Aa = cache[l - x < 0 ? cache.length - (l - x) : l - x])[(Mi = Math.min(x, l - x)) < 0 ? Aa.length - Mi : Mi]);
}
cache.push(r);
}
return cache[num][cache[num].length - 1];
}
```

View File

@@ -0,0 +1,136 @@
---
id: 594810f028c0303b75339acc
title: Проблема ABC
challengeType: 5
forumTopicId: 302220
dashedName: abc-problem
---
# --description--
Вам дано набір кубиків ABC (наприклад, дитячі кубики з алфавітом). Існує 20 блоків з двома літерами на кожному кубику. Завершений алфавіт гарантовано є на всіх сторонах кубиків. Зразок кубиків:
<pre>(B O)
(X K)
(D Q)
(C P)
(N A)
(G T)
(R E)
(T G)
(Q D)
(F S)
(J W)
(H U)
(V I)
(A N)
(O B)
(E R)
(F S)
(L Y)
(P C)
(Z M)
</pre>
# --instructions--
Реалізуйте функцію, яка бере рядок (слово) та визначає, чи можна написати слово з даного набору кубиків.
Правила, які треба добре запам'ятати:
<ul>
<li>Після використання букви на кубику, цей кубик не можна використати знову.</li>
<li>Функція має бути чутливою до регістру.</li>
</ul>
# --hints--
`canMakeWord` має бути функцією.
```js
assert(typeof canMakeWord === 'function');
```
`canMakeWord` повинен повернути логічний тип даних.
```js
assert(typeof canMakeWord('hi') === 'boolean');
```
`canMakeWord("bark")` має повернути true.
```js
assert(canMakeWord(words[0]));
```
`canMakeWord("BooK")` має повернути false.
```js
assert(!canMakeWord(words[1]));
```
`canMakeWord("TReAT")` має повернути true.
```js
assert(canMakeWord(words[2]));
```
`canMakeWord("COMMON")` має повернути false.
```js
assert(!canMakeWord(words[3]));
```
`canMakeWord("squAD")` має повернути true.
```js
assert(canMakeWord(words[4]));
```
`canMakeWord("conFUSE")` має повернути true.
```js
assert(canMakeWord(words[5]));
```
# --seed--
## --after-user-code--
```js
const words = ['bark', 'BooK', 'TReAT', 'COMMON', 'squAD', 'conFUSE'];
```
## --seed-contents--
```js
function canMakeWord(word) {
}
```
# --solutions--
```js
function canMakeWord(word) {
const characters = 'BO XK DQ CP NA GT RE TG QD FS JW HU VI AN OB ER FS LY PC ZM';
const blocks = characters.split(' ').map(pair => pair.split(''));
const letters = [...word.toUpperCase()];
let length = letters.length;
const copy = new Set(blocks);
letters.forEach(letter => {
for (let block of copy) {
const index = block.indexOf(letter);
if (index !== -1) {
length--;
copy.delete(block);
break;
}
}
});
return !length;
}
```

View File

@@ -0,0 +1,95 @@
---
id: 594810f028c0303b75339acd
title: 'Класифікації надлишкових, недостатніх та досконалих чисел'
challengeType: 5
forumTopicId: 302221
dashedName: abundant-deficient-and-perfect-number-classifications
---
# --description--
Ці три класифікації додатних цілих чисел визначені на основі їхніх власних дільників.
Нехай $P(n)$ буде сумою дільників `n`, де всі власні дільники являються додатними цілими числами `n`, на відміну від `n`.
Якщо `P(n) < n`, то `n` являється `deficient`
Якщо `P(n) === n`, тоді `n` являється `perfect`
Якщо `P(n) > n`, тоді `n` являється `abundant`
**Приклад**: `6` має власний дільник `1`, `2` та `3`. `1 + 2 + 3 = 6`, тому `6` являється досконалим числом.
# --instructions--
Реалізуйте функцію, яка вираховує скільки цілих чисел від `1` до `num` (включно) є в кожному з трьох класів. Виведіть результат як масив у наступному форматі `[deficient, perfect, abundant]`.
# --hints--
`getDPA` має бути функцією.
```js
assert(typeof getDPA === 'function');
```
`getDPA(5000)` має повернути масив.
```js
assert(Array.isArray(getDPA(5000)));
```
`getDPA(5000)` повернений масив має мати довжину `3`.
```js
assert(getDPA(5000).length === 3);
```
`getDPA(5000)` має повернути `[3758, 3, 1239]`.
```js
assert.deepEqual(getDPA(5000), [3758, 3, 1239]);
```
`getDPA(10000)` має повернути `[7508, 4, 2488]`.
```js
assert.deepEqual(getDPA(10000), [7508, 4, 2488]);
```
`getDPA(20000)` має повернути `[15043, 4, 4953]`.
```js
assert.deepEqual(getDPA(20000), [15043, 4, 4953]);
```
# --seed--
## --seed-contents--
```js
function getDPA(num) {
}
```
# --solutions--
```js
function getDPA(num) {
const dpa = [1, 0, 0];
for (let n = 2; n <= num; n += 1) {
let ds = 1;
const e = Math.sqrt(n);
for (let d = 2; d < e; d += 1) {
if (n % d === 0) {
ds += d + (n / d);
}
}
if (n % e === 0) {
ds += e;
}
dpa[ds < n ? 0 : ds === n ? 1 : 2] += 1;
}
return dpa;
}
```

View File

@@ -0,0 +1,79 @@
---
id: 594810f028c0303b75339ace
title: Акумуляторна фабрика
challengeType: 5
forumTopicId: 302222
dashedName: accumulator-factory
---
# --description--
Проблема, спричинена [Paul Graham](https://en.wikipedia.org/wiki/Paul_Graham_(programmer)) полягає у створенні функції, яка приймає один (числовий) аргумент, і яка повертає іншу функцію, тобто акумулятор. Повернена акумуляторна функція в свою чергу також бере один числовий аргумент, і повертає суму усіх числових значень, прийнятих до цього часу до цього акумулятора (включаючи початкове значення, передане при створенні акумулятора).
# --instructions--
Створіть функцію, яка приймає число $n$ і генерує акумуляторні функції, які повертають суму кожного числа, яке до них додадуть.
**Правила:**
Не використовуйте глобальні змінні.
**Підказка:**
Закриття економить зовнішній стан.
# --hints--
`accumulator` має бути функцією.
```js
assert(typeof accumulator === 'function');
```
`accumulator(0)` має відображати функцію.
```js
assert(typeof accumulator(0) === 'function');
```
`accumulator(0)(2)` має відображати число.
```js
assert(typeof accumulator(0)(2) === 'number');
```
Перехід у значеннях 3, -4, 1.5 і 5 має видати 5,5.
```js
assert(testFn(5) === 5.5);
```
# --seed--
## --after-user-code--
```js
const testFn = typeof accumulator(3) === 'function' && accumulator(3);
if (testFn) {
testFn(-4);
testFn(1.5);
}
```
## --seed-contents--
```js
function accumulator(sum) {
}
```
# --solutions--
```js
function accumulator(sum) {
return function(n) {
return sum += n;
};
}
```

View File

@@ -0,0 +1,71 @@
---
id: 594810f028c0303b75339acf
title: Функція Акермана
challengeType: 5
forumTopicId: 302223
dashedName: ackermann-function
---
# --description--
Функція Акермана є класичним прикладом рекурсивної функції, особливо тому, що вона не є примітивною рекурсивною функцією. Вона дуже швидко зростає у значенні, зростає також і дерево викликів.
Функція Акермана зазвичай визначається наступним чином:
$A(m, n) = \\begin{cases} n+1 & \\mbox{if } m = 0 \\\\ A(m-1, 1) & \\mbox{if } m > 0 \\mbox{ and } n = 0 \\\\ A(m-1, A(m, n-1)) & \\mbox{if } m > 0 \\mbox{ and } n > 0. \\end{cases}$
Її аргументи ніколи не є від'ємними, і вона завжди закінчується.
# --instructions--
Напишіть функцію, що повертає значення $A(m, n)$. Довільна точність є бажаною (оскільки функція зростає так швидко), але не є обов'язковою.
# --hints--
`ack` має бути функцією.
```js
assert(typeof ack === 'function');
```
`ack(0, 0)` повинен повернутися як 1.
```js
assert(ack(0, 0) === 1);
```
`ack(1, 1)` має повернутися як 3.
```js
assert(ack(1, 1) === 3);
```
`ack(2, 5)` повинен повернутися як 13.
```js
assert(ack(2, 5) === 13);
```
`ack(3, 3)` повинен повертатися як 61.
```js
assert(ack(3, 3) === 61);
```
# --seed--
## --seed-contents--
```js
function ack(m, n) {
}
```
# --solutions--
```js
function ack(m, n) {
return m === 0 ? n + 1 : ack(m - 1, n === 0 ? 1 : ack(m, n - 1));
}
```

View File

@@ -0,0 +1,189 @@
---
id: 594810f028c0303b75339ad0
title: Вирівнювання стовпців
challengeType: 5
forumTopicId: 302224
dashedName: align-columns
---
# --description--
Дано масив з багатьма рядками, де поля в рядку зображені одним символом `$`, напишіть програму, яка вирівнює кожен стовпець полів, переконавшись, що слова в кожному стовпці розділені принаймні одним пробілом. Крім того, дозвольте кожному слову у стовпці вирівнюватись ліворуч, праворуч або вирівнюватись по центру стовпця.
# --instructions--
Щоб перевірити свої програми, використовуйте наступний текст:
```js
const testText = [
'Given$a$text$file$of$many$lines',
'where$fields$within$a$line$',
'are$delineated$by$a$single$"dollar"$character',
'write$a$program',
'that$aligns$each$column$of$fields',
'by$ensuring$that$words$in$each$',
'column$are$separated$by$at$least$one$space.',
'Further,$allow$for$each$word$in$a$column$to$be$either$left$',
'justified,$right$justified',
'or$center$justified$within$its$column.'
];
```
**Зауважте, що:**
- Приклади рядків текстів для введення можуть у кінці мати символ долара.
- Усі стовпці повинні мати однакове вирівнювання.
- Декілька послідовно розміщених символів пробілу у кінці рядків, є неважливими для цілей завдання.
- Вихідний текст буде відображатися моношироким шрифтом у звичайному текстовому редакторі або базовому терміналі. Рядки в ньому слід з'єднати, використовуючи новий символ рядка (`\n`).
- Мінімальний простір між стовпцями слід обчислювати з даного тексту, а не жорстко його кодувати.
- Не обов'язково додавати розділові символи між стовпцями або навколо них.
Наприклад, один з рядків взятий із `testText`, після вирівнювання праворуч, ліворуч та посередині відповідно:
```js
' column are separated by at least one space.\n'
'column are separated by at least one space.\n'
' column are separated by at least one space.\n'
```
# --hints--
`formatText` має бути функцією.
```js
assert(typeof formatText === 'function');
```
`formatText(testText, 'right')` має створити стовпець із текстом, який буде вирівняний по правій стороні.
```js
assert.strictEqual(formatText(_testText, 'right'), rightAligned);
```
`formatText(testText, 'left')` має створити стовпець із текстом, який буде вирівняний по лівій стороні.
```js
assert.strictEqual(formatText(_testText, 'left'), leftAligned);
```
`formatText(testText, 'center')` має створити стовпець із текстом, який буде вирівняний по центру.
```js
assert.strictEqual(formatText(_testText, 'center'), centerAligned);
```
# --seed--
## --after-user-code--
```js
const _testText = [
'Given$a$text$file$of$many$lines',
'where$fields$within$a$line$',
'are$delineated$by$a$single$"dollar"$character',
'write$a$program',
'that$aligns$each$column$of$fields$',
'by$ensuring$that$words$in$each$',
'column$are$separated$by$at$least$one$space.',
'Further,$allow$for$each$word$in$a$column$to$be$either$left$',
'justified,$right$justified',
'or$center$justified$within$its$column.'
];
const rightAligned = ' Given a text file of many lines\n' +
' where fields within a line \n' +
' are delineated by a single "dollar" character\n' +
' write a program\n' +
' that aligns each column of fields \n' +
' by ensuring that words in each \n' +
' column are separated by at least one space.\n' +
' Further, allow for each word in a column to be either left \n' +
'justified, right justified\n' +
' or center justified within its column.';
const leftAligned = 'Given a text file of many lines \n' +
'where fields within a line \n' +
'are delineated by a single "dollar" character\n' +
'write a program \n' +
'that aligns each column of fields \n' +
'by ensuring that words in each \n' +
'column are separated by at least one space.\n' +
'Further, allow for each word in a column to be either left \n' +
'justified, right justified\n' +
'or center justified within its column. ';
const centerAligned = ' Given a text file of many lines \n' +
' where fields within a line \n' +
' are delineated by a single \"dollar\" character\n' +
' write a program \n' +
' that aligns each column of fields \n' +
' by ensuring that words in each \n' +
' column are separated by at least one space.\n' +
' Further, allow for each word in a column to be either left \n' +
'justified, right justified\n' +
' or center justified within its column. ';
```
## --seed-contents--
```js
function formatText(input, justification) {
}
const testText = [
'Given$a$text$file$of$many$lines',
'where$fields$within$a$line$',
'are$delineated$by$a$single$"dollar"$character',
'write$a$program',
'that$aligns$each$column$of$fields$',
'by$ensuring$that$words$in$each$',
'column$are$separated$by$at$least$one$space.',
'Further,$allow$for$each$word$in$a$column$to$be$either$left$',
'justified,$right$justified',
'or$center$justified$within$its$column.'
];
```
# --solutions--
```js
String.prototype.repeat = function (n) { return new Array(1 + parseInt(n)).join(this); };
function formatText(input, justification) {
let x, y, max, cols = 0, diff, left, right;
for (x = 0; x < input.length; x++) {
input[x] = input[x].split('$');
if (input[x].length > cols) {
cols = input[x].length;
}
}
for (x = 0; x < cols; x++) {
max = 0;
for (y = 0; y < input.length; y++) {
if (input[y][x] && max < input[y][x].length) {
max = input[y][x].length;
}
}
for (y = 0; y < input.length; y++) {
if (input[y][x]) {
diff = (max - input[y][x].length) / 2;
left = ' '.repeat(Math.floor(diff));
right = ' '.repeat(Math.ceil(diff));
if (justification === 'left') {
right += left; left = '';
}
if (justification === 'right') {
left += right; right = '';
}
input[y][x] = left + input[y][x] + right;
}
}
}
for (x = 0; x < input.length; x++) {
input[x] = input[x].join(' ');
}
input = input.join('\n');
return input;
}
```

View File

@@ -0,0 +1,126 @@
---
id: 5949b579404977fbaefcd737
title: Дружні числа
challengeType: 5
forumTopicId: 302225
dashedName: amicable-pairs
---
# --description--
Цілі числа $N$ та $M$ - це [дружні числа](https://en.wikipedia.org/wiki/Amicable numbers "wp: Amicable numbers") if $N \\neq M$ і сума [власних дільників](https://rosettacode.org/wiki/Proper divisors "Proper divisors") of $N$ ($\\mathrm{sum}(\\mathrm{propDivs}(N))$) $= M$, як і $\\mathrm{sum}(\\mathrm{propDivs}(M)) = N$.
**Приклад:**
**1184** та **1210** - це дружні числа з власними дільниками:
<ul>
<li>1, 2, 4, 8, 16, 32, 37, 74, 148, 296, 592 та</li>
<li>1, 2, 5, 10, 11, 22, 55, 110, 121, 242, 605 також.</li>
</ul>
# --instructions--
Порахуйте та покажіть тут дружні числа нижче 20 000 (тут їх вісім).
# --hints--
`amicablePairsUpTo` мають бути функцією.
```js
assert(typeof amicablePairsUpTo === 'function');
```
`amicablePairsUpTo(300)` повинен повертатися як `[[220,284]]`.
```js
assert.deepEqual(amicablePairsUpTo(300), answer300);
```
`amicablePairsUpTo(3000)` повинен повертатися як `[[220,284],[1184,1210],[2620,2924]]`.
```js
assert.deepEqual(amicablePairsUpTo(3000), answer3000);
```
`amicablePairsUpTo(20000)` повинен повертатися як `[[220,284],[1184,1210],[2620,2924],[5020,5564],[6232,6368],[10744,10856],[12285,14595],[17296,18416]]`.
```js
assert.deepEqual(amicablePairsUpTo(20000), answer20000);
```
# --seed--
## --after-user-code--
```js
const answer300 = [[220, 284]];
const answer3000 = [
[220, 284],
[1184, 1210],
[2620, 2924]
];
const answer20000 = [
[220, 284],
[1184, 1210],
[2620, 2924],
[5020, 5564],
[6232, 6368],
[10744, 10856],
[12285, 14595],
[17296, 18416]
];
```
## --seed-contents--
```js
function amicablePairsUpTo(maxNum) {
return true;
}
```
# --solutions--
```js
// amicablePairsUpTo :: Int -> [(Int, Int)]
function amicablePairsUpTo(maxNum) {
return range(1, maxNum)
.map(x => properDivisors(x)
.reduce((a, b) => a + b, 0))
.reduce((a, m, i, lst) => {
const n = i + 1;
return (m > n) && lst[m - 1] === n ?
a.concat([
[n, m]
]) : a;
}, []);
}
// properDivisors :: Int -> [Int]
function properDivisors(n) {
if (n < 2) return [];
const rRoot = Math.sqrt(n);
const intRoot = Math.floor(rRoot);
const blnPerfectSquare = rRoot === intRoot;
const lows = range(1, intRoot)
.filter(x => (n % x) === 0);
return lows.concat(lows.slice(1)
.map(x => n / x)
.reverse()
.slice(blnPerfectSquare | 0));
}
// Int -> Int -> Maybe Int -> [Int]
function range(m, n, step) {
const d = (step || 1) * (n >= m ? 1 : -1);
return Array.from({
length: Math.floor((n - m) / d) + 1
}, (_, i) => m + (i * d));
}
```

View File

@@ -0,0 +1,79 @@
---
id: 594d8d0ab97724821379b1e6
title: Середні значення/Режим
challengeType: 5
forumTopicId: 302226
dashedName: averagesmode
---
# --description--
Напишіть програму для пошуку значення [режиму](https://en.wikipedia.org/wiki/Mode (statistics) "wp: Mode (statistics)") колекції.
Випадок, коли колекція є порожньою, можна ігнорувати. Необхідно бути обережним у випадку, коли режим не є унікальним.
Якщо недоцільно або неможливо підтримувати загальну колекцію, по можливості використовуйте вектор (масив). Якщо недоцільно або неможливо підтримувати невизначений тип значення, то використовуйте цілі числа.
# --hints--
`mode` повинен бути функцією.
```js
assert(typeof mode === 'function');
```
`mode([1, 3, 6, 6, 6, 6, 7, 7, 12, 12, 17])` повинен дорівнювати `[6]`
```js
assert.deepEqual(mode(arr1), [6]);
```
`mode([1, 2, 4, 4, 1])` повинен дорівнювати `[1, 4]`.
```js
assert.deepEqual(mode(arr2).sort(), [1, 4]);
```
# --seed--
## --after-user-code--
```js
const arr1 = [1, 3, 6, 6, 6, 6, 7, 7, 12, 12, 17];
const arr2 = [1, 2, 4, 4, 1];
```
## --seed-contents--
```js
function mode(arr) {
return true;
}
```
# --solutions--
```js
function mode(arr) {
const counter = {};
let result = [];
let max = 0;
// for (const i in arr) {
arr.forEach(el => {
if (!(el in counter)) {
counter[el] = 0;
}
counter[el]++;
if (counter[el] === max) {
result.push(el);
}
else if (counter[el] > max) {
max = counter[el];
result = [el];
}
});
return result;
}
```

View File

@@ -0,0 +1,144 @@
---
id: 594d966a1467eb84194f0086
title: Піфагорові середні
challengeType: 5
forumTopicId: 302227
dashedName: averagespythagorean-means
---
# --description--
Розрахуйте всі три [ Піфагорових середніх ](https://en.wikipedia.org/wiki/Pythagorean means "wp: Pythagorean means") набору цілих чисел від $1$ до $10$ (включно).
Покажіть, що $A(x_1,\\ldots,x_n) \\geq G(x_1,\\ldots,x_n) \\geq H(x_1,\\ldots,x_n)$ для цього набору цілих чисел.
<ul>
<li>Найпоширеніший із трьох середніх — <a class='rosetta__link--rosetta' href='https://rosettacode.org/wiki/Averages/Arithmetic mean' title='Averages/Arithmetic mean' target='_blank'>середнє арифметичне</a> — сума елементів набору, поділена на їх кількість:<br>
<big>$ A(x_1, \ldots, x_n) = \frac{x_1 + \cdots + x_n}{n}$</big></li>
<li><a class='rosetta__link--wiki' href='https://en.wikipedia.org/wiki/Geometric mean' title='wp: Geometric mean' target='_blank'>Середнє геометричне</a> — це $n$-й корінь добутку кількості елементів:<br>
<big>$ G(x_1, \ldots, x_n) = \sqrt[n]{x_1 \cdots x_n} $</big></li>
<li><a class='rosetta__link--wiki' href='https://en.wikipedia.org/wiki/Harmonic mean' title='wp: Harmonic mean' target='_blank'>Середнє гармонійне</a> — $n$, поділене на суму кожного оберненого елемента набору:<br>
<big>$ H(x_1, \ldots, x_n) = \frac{n}{\frac{1}{x_1} + \cdots + \frac{1}{x_n}} $</big></li>
</ul>
# --instructions--
При написанні функції, врахуйте, що вхідні дані — впорядкований масив всіх включених чисел.
Для відповіді, будь ласка, виведіть об'єкт у наступному форматі:
```js
{
values: {
Arithmetic: 5.5,
Geometric: 4.528728688116765,
Harmonic: 3.414171521474055
},
test: 'is A >= G >= H ? yes'
}
```
# --hints--
`pythagoreanMeans` має бути функцією.
```js
assert(typeof pythagoreanMeans === 'function');
```
`pythagoreanMeans([1, 2, ..., 10])` має дорівнювати тому ж результату, що й вище.
```js
assert.deepEqual(pythagoreanMeans(range1), answer1);
```
# --seed--
## --after-user-code--
```js
const range1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const answer1 = {
values: {
Arithmetic: 5.5,
Geometric: 4.528728688116765,
Harmonic: 3.414171521474055
},
test: 'is A >= G >= H ? yes'
};
```
## --seed-contents--
```js
function pythagoreanMeans(rangeArr) {
}
```
# --solutions--
```js
function pythagoreanMeans(rangeArr) {
// arithmeticMean :: [Number] -> Number
const arithmeticMean = xs =>
foldl((sum, n) => sum + n, 0, xs) / length(xs);
// geometricMean :: [Number] -> Number
const geometricMean = xs =>
raise(foldl((product, x) => product * x, 1, xs), 1 / length(xs));
// harmonicMean :: [Number] -> Number
const harmonicMean = xs =>
length(xs) / foldl((invSum, n) => invSum + (1 / n), 0, xs);
// GENERIC FUNCTIONS ------------------------------------------------------
// A list of functions applied to a list of arguments
// <*> :: [(a -> b)] -> [a] -> [b]
const ap = (fs, xs) => //
Array.prototype.concat(...fs.map(f => //
Array.prototype.concat(...xs.map(x => [f(x)]))));
// foldl :: (b -> a -> b) -> b -> [a] -> b
const foldl = (f, a, xs) => xs.reduce(f, a);
// length :: [a] -> Int
const length = xs => xs.length;
// mapFromList :: [(k, v)] -> Dictionary
const mapFromList = kvs =>
foldl((a, [k, v]) =>
(a[(typeof k === 'string' && k)] = v, a), {}, kvs);
// raise :: Num -> Int -> Num
const raise = (n, e) => Math.pow(n, e);
/*
// show :: a -> String
// show :: a -> Int -> String
const show = (...x) =>
JSON.stringify.apply(
null, x.length > 1 ? [x[0], null, x[1]] : x
);
*/
// zip :: [a] -> [b] -> [(a,b)]
const zip = (xs, ys) =>
xs.slice(0, Math.min(xs.length, ys.length))
.map((x, i) => [x, ys[i]]);
// TEST -------------------------------------------------------------------
// mean :: Dictionary
const mean = mapFromList(zip(
['Arithmetic', 'Geometric', 'Harmonic'],
ap([arithmeticMean, geometricMean, harmonicMean], [
rangeArr
])
));
return {
values: mean,
test: `is A >= G >= H ? ${mean.Arithmetic >= mean.Geometric &&
mean.Geometric >= mean.Harmonic ? 'yes' : 'no'}`
};
}
```

View File

@@ -0,0 +1,57 @@
---
id: 594da033de4190850b893874
title: Середнє значення квадратного кореня
challengeType: 5
forumTopicId: 302228
dashedName: averagesroot-mean-square
---
# --description--
Визначте [ середнє квадратне ](https://en.wikipedia.org/wiki/Root mean square "wp: Root mean square") від 1 до 10 включно.
* середнє квадратне * також відоме своїми ініціалами СК (або ск), а також як **quadratic mean**.
СК вираховується як середнє значення квадратів чисел в квадратних коренях:
$$x\_{\\mathrm{rms}} = \\sqrt {{{x_1}^2 + {x_2}^2 + \\cdots + {x_n}^2} \\over n}. $$
# --hints--
`rms` має бути функцією.
```js
assert(typeof rms === 'function');
```
`rms([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])` має дорівнювати `6.2048368229954285`.
```js
assert.equal(rms(arr1), answer1);
```
# --seed--
## --after-user-code--
```js
const arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const answer1 = 6.2048368229954285;
```
## --seed-contents--
```js
function rms(arr) {
}
```
# --solutions--
```js
function rms(arr) {
const sumOfSquares = arr.reduce((s, x) => s + x * x, 0);
return Math.sqrt(sumOfSquares / arr.length);
}
```

View File

@@ -0,0 +1,78 @@
---
id: 594db4d0dedb4c06a2a4cefd
title: Задача Беббіджа
challengeType: 5
forumTopicId: 302229
dashedName: babbage-problem
---
# --description--
[Чарльз Беббідж](https://en.wikipedia.org/wiki/Charles_Babbage "wp: Charles_Babbage"), дивлячись у майбутнє на завдання, які зможе вирішити його аналітична машина, навів такий приклад:
<blockquote>
Яке найменше натуральне число, квадрат якого закінчується цифрами 269,696?
<footer style='margin-left: 2em;'>Беббідж, лист до лорда Боудена, 1837; див. Hollingdale and Tootill, <i>Електронні комп’ютери</i>, друге видання, 1970, стор. 125.</footer>
</blockquote>
Він думав, що відповідь може бути 99,736, квадрат якого становить 9,947,269,696; але він не міг бути певним.
Завдання полягає в тому, щоб з'ясувати, чи відповідь Беббіджа була правильною.
# --instructions--
Реалізуйте функцію, щоб повернути найменше ціле число, що задовольняє задачу Беббіджа. Якщо Беббідж мав рацію, то поверніть число Беббіджа.
# --hints--
`babbage` має бути функцією.
```js
assert(typeof babbage === 'function');
```
`babbage(99736, 269696)` не повинна повертати 99736 (відповідь має бути меншою).
```js
assert.equal(babbage(babbageAns, endDigits), answer);
```
# --seed--
## --after-user-code--
```js
const babbageAns = 99736;
const endDigits = 269696;
const answer = 25264;
```
## --seed-contents--
```js
function babbage(babbageNum, endDigits) {
return true;
}
```
# --solutions--
```js
function babbage(babbageAns, endDigits) {
const babbageNum = Math.pow(babbageAns, 2);
const babbageStartDigits = parseInt(babbageNum.toString().replace('269696', ''));
let answer = 99736;
// count down from this answer and save any sqrt int result. return lowest one
for (let i = babbageStartDigits; i >= 0; i--) {
const num = parseInt(i.toString().concat('269696'));
const result = Math.sqrt(num);
if (result === Math.floor(Math.sqrt(num))) {
answer = result;
}
}
return answer;
}
```

View File

@@ -0,0 +1,188 @@
---
id: 594dc6c729e5700999302b45
title: Збалансовані дужки
challengeType: 5
forumTopicId: 302230
dashedName: balanced-brackets
---
# --description--
Визначте, чи збалансований згенерований рядок дужок; тобто чи він складається повністю з пар відкритих/закритих дужок (у правильному порядку), і кожна розміщена у відповідному місці.
**Приклади:**
| Вихідна інформація | Результат |
| ------------------------- | --------- |
| <code>\[]</code> | true |
| <code>]\[</code> | false |
| <code>[][]</code> | true |
| <code>]\[]</code> | false |
| <code>\[]]\[\[]</code> | false |
| <code>\[\[\[\[]]]]</code> | true |
# --hints--
`isBalanced` має бути функцією.
```js
assert(typeof isBalanced === 'function');
```
Функція `isBalanced("[]")` має повернути true.
```js
assert(isBalanced(testCases[0]));
```
Функція `isBalanced("]][[[][][][]][")` має повернути false.
```js
assert(!isBalanced(testCases[1]));
```
Функція `isBalanced("[][[[[][][[[]]]]]]")` має повернути true.
```js
assert(isBalanced(testCases[2]));
```
Функція `isBalanced("][")` має повернути false.
```js
assert(!isBalanced(testCases[3]));
```
Функція `isBalanced("[[[]]]][[]")` має повернути false.
```js
assert(!isBalanced(testCases[4]));
```
Функція `isBalanced("][[]")` має повернути false.
```js
assert(!isBalanced(testCases[5]));
```
Функція `isBalanced("][[][]][[[]]")` має повернути false.
```js
assert(!isBalanced(testCases[6]));
```
Функція `isBalanced("[[][]]][")` має повернути false.
```js
assert(!isBalanced(testCases[7]));
```
Функція `isBalanced("[[[]]][[]]]][][[")` має повернути false.
```js
assert(!isBalanced(testCases[8]));
```
Функція `isBalanced("[]][[]]][[[[][]]")` має повернути false.
```js
assert(!isBalanced(testCases[9]));
```
Функція `isBalanced("][]][[][")` має повернути false.
```js
assert(!isBalanced(testCases[10]));
```
Функція `isBalanced("[[]][[][]]")` має повернути true.
```js
assert(isBalanced(testCases[11]));
```
Функція `isBalanced("[[]]")` має повернути true.
```js
assert(isBalanced(testCases[12]));
```
Функція `isBalanced("]][]][[]][[[")` має повернути false.
```js
assert(!isBalanced(testCases[13]));
```
Функція `isBalanced("][]][][[")` має повернути false.
```js
assert(!isBalanced(testCases[14]));
```
Функція `isBalanced("][][")` має повернути false.
```js
assert(!isBalanced(testCases[15]));
```
Функція `isBalanced("[]]]")` має повернути false.
```js
assert(!isBalanced(testCases[16]));
```
Функція `isBalanced("")` має повернути true.
```js
assert(isBalanced(testCases[17]));
```
# --seed--
## --after-user-code--
```js
const testCases = [
'[]',
']][[[][][][]][',
'[][[[[][][[[]]]]]]',
'][',
'[[[]]]][[]',
'][[]',
'][[][]][[[]]',
'[[][]]][',
'[[[]]][[]]]][][[',
'[]][[]]][[[[][]]',
'][]][[][',
'[[]][[][]]',
'[[]]',
']][]][[]][[[',
'][]][][[',
'][][',
'[]]]',
''
];
```
## --seed-contents--
```js
function isBalanced(str) {
return true;
}
```
# --solutions--
```js
function isBalanced(str) {
if (str === '') return true;
let a = str;
let b;
do {
b = a;
a = a.replace(/\[\]/g, '');
} while (a !== b);
return !a;
}
```

View File

@@ -0,0 +1,150 @@
---
id: 5951815dd895584b06884620
title: Кола з заданим радіусом через дві точки
challengeType: 5
forumTopicId: 302231
dashedName: circles-of-given-radius-through-two-points
---
# --description--
Якщо відомі дві точки на площині та радіус, зазвичай можна провести два кола заданого радіусу через ці точки.
**Винятки:**
<ul>
<li>Нульовий радіус вважатиметься таким, що ніколи не описує кола (крім випадків, коли точки збігаються).</li>
<li>Якщо точки збігаються, тоді можна описати безкінечне число кіл з точкою їх окружності, якщо радіус кола також не дорівнює нулю, що перетворить коло на точку.</li>
<li>Якщо точки утворюють діаметр, то повернеться одне коло.</li>
<li>Якщо точки розташовані надто далеко, тоді кола намалювати не можна.</li>
</ul>
# --instructions--
Реалізуйте функцію, яка приймає дві точки і радіус і повертається як два кола через ці точки. Для кожного кола, що утвориться, встановіть координати для центру кожного кола округлені до чотирьох десяткових чисел. Поверніть кожну координату як масив і координати як масив масивів.
**Для складних випадків повертається наступне:**
<ul>
<li>Якщо точки розташовані на діаметрі, повернеться одна точка. Якщо ж радіус також є нульовим, тоді повернеться <code>"Radius Zero"</code>.</li>
<li>Якщо точки збігаються, поверніть <code>"Точку збігу. Безкінечні рішення"</code>.</li>
<li>Якщо точки розташовані далі, ніж діаметр, поверніть <code>"Без перетину. Точки, які віддалені одна від одної, відносно діаметра кола"</code>.</li>
</ul>
**Приклади вхідних даних:**
<pre> p1 p2 r
0.1234, 0.9876 0.8765, 0.2345 2.0
0.0000, 2.0000 0.0000, 0.0000 1.0
0.1234, 0.9876 0.1234, 0.9876 2.0
0.1234, 0.9876 0.8765, 0.2345 0.5
0.1234, 0.9876 0.1234, 0.9876 0.0
</pre>
# --hints--
`getCircles` має бути функцією.
```js
assert(typeof getCircles === 'function');
```
`getCircles([0.1234, 0.9876], [0.8765, 0.2345], 2.0)` повинен повернутися як `[[1.8631, 1.9742], [-0.8632, -0.7521]]`.
```js
assert.deepEqual(getCircles(...testCases[0]), answers[0]);
```
`getCircles([0.0000, 2.0000], [0.0000, 0.0000], 1.0)` повинен повернутися як `[0, 1]`
```js
assert.deepEqual(getCircles(...testCases[1]), answers[1]);
```
`getCircles([0.1234, 0.9876], [0.1234, 0.9876], 2.0)` має повертатися `Точка збігу. Безкінечні рішення"`
```js
assert.deepEqual(getCircles(...testCases[2]), answers[2]);
```
`getCircles([0.1234, 0.9876], [0.8765, 0.2345], 0.5)` має повертатися `Без перетину. Точки, які віддалені одна від одної, відносно діаметра кола"`
```js
assert.deepEqual(getCircles(...testCases[3]), answers[3]);
```
`getCircles([0.1234, 0.9876], [0.1234, 0.9876], 0.0)` має повертатися як `Radius Zero`
```js
assert.deepEqual(getCircles(...testCases[4]), answers[4]);
```
# --seed--
## --after-user-code--
```js
const testCases = [
[[0.1234, 0.9876], [0.8765, 0.2345], 2.0],
[[0.0000, 2.0000], [0.0000, 0.0000], 1.0],
[[0.1234, 0.9876], [0.1234, 0.9876], 2.0],
[[0.1234, 0.9876], [0.8765, 0.2345], 0.5],
[[0.1234, 0.9876], [0.1234, 0.9876], 0.0]
];
const answers = [
[[1.8631, 1.9742], [-0.8632, -0.7521]],
[0, 1],
'Coincident point. Infinite solutions',
'No intersection. Points further apart than circle diameter',
'Radius Zero'
];
```
## --seed-contents--
```js
function getCircles(...args) {
return true;
}
```
# --solutions--
```js
const hDist = (p1, p2) => Math.hypot(...p1.map((e, i) => e - p2[i])) / 2;
const pAng = (p1, p2) => Math.atan(p1.map((e, i) => e - p2[i]).reduce((p, c) => c / p, 1));
const solveF = (p, r) => t => [parseFloat((r * Math.cos(t) + p[0]).toFixed(4)), parseFloat((r * Math.sin(t) + p[1]).toFixed(4))];
const diamPoints = (p1, p2) => p1.map((e, i) => parseFloat((e + (p2[i] - e) / 2).toFixed(4)));
function getCircles(...args) {
const [p1, p2, s] = args;
const solve = solveF(p1, s);
const halfDist = hDist(p1, p2);
let msg = [];
switch (Math.sign(s - halfDist)) {
case 0:
msg = s ? diamPoints(p1, p2) :
'Radius Zero';
break;
case 1:
if (!halfDist) {
msg = 'Coincident point. Infinite solutions';
}
else {
const theta = pAng(p1, p2);
const theta2 = Math.acos(halfDist / s);
[1, -1].map(e => solve(theta + e * theta2)).forEach(
e => msg.push(e));
}
break;
case -1:
msg = 'No intersection. Points further apart than circle diameter';
break;
default:
msg = 'Reached the default';
}
return msg;
}
```

View File

@@ -0,0 +1,414 @@
---
id: 5951a53863c8a34f02bf1bdc
title: Задача про найближчу пару
challengeType: 5
forumTopicId: 302232
dashedName: closest-pair-problem
---
# --description--
Надайте функцію для пошуку двох найближчих точок серед поданого набору точок у двох вимірах.
Найпростіше рішення це $O(n^2)$ алгоритм (який ми можемо назвати *brute-force algorithm*); цей псевдо-код (з використанням індексів) може бути простим:
<pre><strong>bruteForceClosestPair</strong> of P(1), P(2), ... P(N)
<strong>if</strong> N &#x3C; 2 <strong>then</strong>
<strong>return</strong>
<strong>else</strong>
minDistance ← |P(1) - P(2)|
minPoints ← { P(1), P(2) }
<strong>foreach</strong> i ∈ [1, N-1]
<strong>foreach</strong> j ∈ [i+1, N]
<strong>if</strong> |P(i) - P(j)| &#x3C; minDistance <strong>then</strong>
minDistance ← |P(i) - P(j)|
minPoints ← { P(i), P(j) }
<strong>endif</strong>
<strong>endfor</strong>
<strong>endfor</strong>
<strong>return</strong> minDistance, minPoints
<strong>endif</strong>
</pre>
Кращий алгоритм базується на рекурсивному розподілі та підхопленні, який є псевдо-кодом $O(n\log n)$:
<pre><strong>closestPair</strong> of (xP, yP)
where xP is P(1) .. P(N) sorted by x coordinate, and
yP is P(1) .. P(N) sorted by y coordinate (ascending order)
<strong>if</strong> N ≤ 3 <strong>then</strong>
<strong>return</strong> closest points of xP using brute-force algorithm
<strong>else</strong>
xL ← points of xP from 1 to ⌈N/2⌉
xR ← points of xP from ⌈N/2⌉+1 to N
xm ← xP(⌈N/2⌉)<sub>x</sub>
yL ← { p ∈ yP : p<sub>x</sub> ≤ xm }
yR ← { p ∈ yP : p<sub>x</sub> > xm }
(dL, pairL) ← closestPair of (xL, yL)
(dR, pairR) ← closestPair of (xR, yR)
(dmin, pairMin) ← (dR, pairR)
<strong>if</strong> dL &#x3C; dR <strong>then</strong>
(dmin, pairMin) ← (dL, pairL)
<strong>endif</strong>
yS ← { p ∈ yP : |xm - p<sub>x</sub>| &#x3C; dmin }
nS ← number of points in yS
(closest, closestPair) ← (dmin, pairMin)
<strong>for</strong> i <strong>from</strong> 1 <strong>to</strong> nS - 1
k ← i + 1
<strong>while</strong> k ≤ nS <strong>and</strong> yS(k)<sub>y</sub> - yS(i)<sub>y</sub> &#x3C; dmin
<strong>if</strong> |yS(k) - yS(i)| &#x3C; closest <strong>then</strong>
(closest, closestPair) ← (|yS(k) - yS(i)|, {yS(k), yS(i)})
<strong>endif</strong>
k ← k + 1
<strong>endwhile</strong>
<strong>endfor</strong>
<strong>return</strong> closest, closestPair
<strong>endif</strong>
</pre>
Для вхідних даних, слід очікувати, що аргумент буде масивом з `Point` об'єктами, і `x` та `y` заданими числами. Поверніть об'єкт, що містить ключові пари значень для `distance` та `pair` (пара двох найближчих точок).
Наприклад, `getClosestPair` з вхідним масивом `points`:
```js
const points = [
new Point(1, 2),
new Point(3, 3),
new Point(2, 2)
];
```
Має повернути:
```js
{
distance: 1,
pair: [
{
x: 1,
y: 2
},
{
x: 2,
y: 2
}
]
}
```
**Note:** Сортуйте `pair` масиви за їхніми `x` значеннями у зростаючому порядку.
# --hints--
`getClosestPair` має бути функцією.
```js
assert(typeof getClosestPair === 'function');
```
`getClosestPair(points1).distance` має бути `0.0894096443343775`.
```js
assert.equal(getClosestPair(points1).distance, answer1.distance);
```
`getClosestPair(points1).pair` має бути `[ { x: 7.46489, y: 4.6268 }, { x: 7.46911, y: 4.71611 } ]`.
```js
assert.deepEqual(
JSON.parse(JSON.stringify(getClosestPair(points1))).pair,
answer1.pair
);
```
`getClosestPair(points2).distance` має бути `65.06919393998976`.
```js
assert.equal(getClosestPair(points2).distance, answer2.distance);
```
`getClosestPair(points2).pair` має бути `[ { x: 37134, y: 1963 }, { x: 37181, y: 2008 } ]`.
```js
assert.deepEqual(
JSON.parse(JSON.stringify(getClosestPair(points2))).pair,
answer2.pair
);
```
`getClosestPair(points3).distance` має бути `6754.625082119658`.
```js
assert.equal(getClosestPair(points3).distance, answer3.distance);
```
`getClosestPair(points3).pair` має бути `[ { x: 46817, y: 64975 }, { x: 48953, y: 58567 } ]`.
```js
assert.deepEqual(
JSON.parse(JSON.stringify(getClosestPair(points3))).pair,
answer3.pair
);
```
# --seed--
## --after-user-code--
```js
const points1 = [
new Point(0.748501, 4.09624),
new Point(3.00302, 5.26164),
new Point(3.61878, 9.52232),
new Point(7.46911, 4.71611),
new Point(5.7819, 2.69367),
new Point(2.34709, 8.74782),
new Point(2.87169, 5.97774),
new Point(6.33101, 0.463131),
new Point(7.46489, 4.6268),
new Point(1.45428, 0.087596)
];
const answer1 = {
distance: 0.0894096443343775,
pair: [
{
x: 7.46489,
y: 4.6268
},
{
x: 7.46911,
y: 4.71611
}
]
};
const points2 = [
new Point(37100, 13118),
new Point(37134, 1963),
new Point(37181, 2008),
new Point(37276, 21611),
new Point(37307, 9320)
];
const answer2 = {
distance: 65.06919393998976,
pair: [
{
x: 37134,
y: 1963
},
{
x: 37181,
y: 2008
}
]
};
const points3 = [
new Point(16910, 54699),
new Point(14773, 61107),
new Point(95547, 45344),
new Point(95951, 17573),
new Point(5824, 41072),
new Point(8769, 52562),
new Point(21182, 41881),
new Point(53226, 45749),
new Point(68180, 887),
new Point(29322, 44017),
new Point(46817, 64975),
new Point(10501, 483),
new Point(57094, 60703),
new Point(23318, 35472),
new Point(72452, 88070),
new Point(67775, 28659),
new Point(19450, 20518),
new Point(17314, 26927),
new Point(98088, 11164),
new Point(25050, 56835),
new Point(8364, 6892),
new Point(37868, 18382),
new Point(23723, 7701),
new Point(55767, 11569),
new Point(70721, 66707),
new Point(31863, 9837),
new Point(49358, 30795),
new Point(13041, 39744),
new Point(59635, 26523),
new Point(25859, 1292),
new Point(1551, 53890),
new Point(70316, 94479),
new Point(48549, 86338),
new Point(46413, 92747),
new Point(27186, 50426),
new Point(27591, 22655),
new Point(10905, 46153),
new Point(40408, 84202),
new Point(52821, 73520),
new Point(84865, 77388),
new Point(99819, 32527),
new Point(34404, 75657),
new Point(78457, 96615),
new Point(42140, 5564),
new Point(62175, 92342),
new Point(54958, 67112),
new Point(4092, 19709),
new Point(99415, 60298),
new Point(51090, 52158),
new Point(48953, 58567)
];
const answer3 = {
distance: 6754.625082119658,
pair: [
{
x: 46817,
y: 64975
},
{
x: 48953,
y: 58567
}
]
}
```
## --seed-contents--
```js
const Point = function(x, y) {
this.x = x;
this.y = y;
};
Point.prototype.getX = function() {
return this.x;
};
Point.prototype.getY = function() {
return this.y;
};
function getClosestPair(pointsArr) {
return true;
}
```
# --solutions--
```js
const Point = function(x, y) {
this.x = x;
this.y = y;
};
Point.prototype.getX = function() {
return this.x;
};
Point.prototype.getY = function() {
return this.y;
};
const mergeSort = function mergeSort(points, comp) {
if(points.length < 2) return points;
var n = points.length,
i = 0,
j = 0,
leftN = Math.floor(n / 2),
rightN = leftN;
var leftPart = mergeSort( points.slice(0, leftN), comp),
rightPart = mergeSort( points.slice(rightN), comp );
var sortedPart = [];
while((i < leftPart.length) && (j < rightPart.length)) {
if(comp(leftPart[i], rightPart[j]) < 0) {
sortedPart.push(leftPart[i]);
i += 1;
}
else {
sortedPart.push(rightPart[j]);
j += 1;
}
}
while(i < leftPart.length) {
sortedPart.push(leftPart[i]);
i += 1;
}
while(j < rightPart.length) {
sortedPart.push(rightPart[j]);
j += 1;
}
return sortedPart;
};
const closestPair = function _closestPair(Px, Py) {
if(Px.length < 2) return { distance: Infinity, pair: [ new Point(0, 0), new Point(0, 0) ] };
if(Px.length < 3) {
//find euclid distance
var d = Math.sqrt( Math.pow(Math.abs(Px[1].x - Px[0].x), 2) + Math.pow(Math.abs(Px[1].y - Px[0].y), 2) );
return {
distance: d,
pair: [ Px[0], Px[1] ]
};
}
var n = Px.length,
leftN = Math.floor(n / 2),
rightN = leftN;
var Xl = Px.slice(0, leftN),
Xr = Px.slice(rightN),
Xm = Xl[leftN - 1],
Yl = [],
Yr = [];
//separate Py
for(var i = 0; i < Py.length; i += 1) {
if(Py[i].x <= Xm.x)
Yl.push(Py[i]);
else
Yr.push(Py[i]);
}
var dLeft = _closestPair(Xl, Yl),
dRight = _closestPair(Xr, Yr);
var minDelta = dLeft.distance,
closestPair = dLeft.pair;
if(dLeft.distance > dRight.distance) {
minDelta = dRight.distance;
closestPair = dRight.pair;
}
//filter points around Xm within delta (minDelta)
var closeY = [];
for(i = 0; i < Py.length; i += 1) {
if(Math.abs(Py[i].x - Xm.x) < minDelta) closeY.push(Py[i]);
}
//find min within delta. 8 steps max
for(i = 0; i < closeY.length; i += 1) {
for(var j = i + 1; j < Math.min( (i + 8), closeY.length ); j += 1) {
var d = Math.sqrt( Math.pow(Math.abs(closeY[j].x - closeY[i].x), 2) + Math.pow(Math.abs(closeY[j].y - closeY[i].y), 2) );
if(d < minDelta) {
minDelta = d;
closestPair = [ closeY[i], closeY[j] ]
}
}
}
return {
distance: minDelta,
pair: closestPair.sort((pointA, pointB) => pointA.x - pointB.x)
};
};
function getClosestPair(points) {
const sortX = function(a, b) { return (a.x < b.x) ? -1 : ((a.x > b.x) ? 1 : 0); }
const sortY = function(a, b) { return (a.y < b.y) ? -1 : ((a.y > b.y) ? 1 : 0); }
const Px = mergeSort(points, sortX);
const Py = mergeSort(points, sortY);
return closestPair(Px, Py);
}
```

View File

@@ -0,0 +1,95 @@
---
id: 5958469238c0d8d2632f46db
title: Комбінації
challengeType: 5
forumTopicId: 302233
dashedName: combinations
---
# --description--
Маючи невід'ємні цілі числа `m` і `n`, створіть усі розміри `m` комбінацій цілих чисел від `0` (нуля) до `n-1` у сортованому порядку (кожна комбінація сортується і вся таблиця сортується).
**Наприклад:**
`3` комб. `5` дає:
<pre>0 1 2
0 1 3
0 1 4
0 2 3
0 2 4
0 3 4
1 2 3
1 2 4
1 3 4
2 3 4
</pre>
# --hints--
`combinations` мають бути функцією.
```js
assert(typeof combinations === 'function');
```
Функція `combinations(3, 5)` повинна вертати `[[0, 1, 2], [0, 1, 3], [0, 1, 4], [0, 2, 3], [0, 2, 4], [0, 3, 4], [1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]`.
```js
assert.deepEqual(combinations(testInput1[0], testInput1[1]), testOutput1);
```
Функція `combinations(4, 6)` повинна вертати `[[0,1,2,3], [0,1,2,4], [0,1,2,5], [0,1,3,4], [0,1,3,5], [0,1,4,5], [0,2,3,4], [0,2,3,5], [0,2,4,5], [0,3,4,5], [1,2,3,4], [1,2,3,5], [1,2,4,5], [1,3,4,5], [2,3,4,5]]`
```js
assert.deepEqual(combinations(testInput2[0], testInput2[1]), testOutput2);
```
# --seed--
## --after-user-code--
```js
const testInput1 = [3, 5];
const testOutput1 = [[0, 1, 2], [0, 1, 3], [0, 1, 4], [0, 2, 3], [0, 2, 4], [0, 3, 4], [1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]];
const testInput2 = [4, 6];
const testOutput2 = [[0, 1, 2, 3], [0, 1, 2, 4], [0, 1, 2, 5], [0, 1, 3, 4], [0, 1, 3, 5], [0, 1, 4, 5], [0, 2, 3, 4], [0, 2, 3, 5], [0, 2, 4, 5], [0, 3, 4, 5], [1, 2, 3, 4], [1, 2, 3, 5], [1, 2, 4, 5], [1, 3, 4, 5], [2, 3, 4, 5]];
```
## --seed-contents--
```js
function combinations(m, n) {
return true;
}
```
# --solutions--
```js
function combinations(m, n) {
const nArr = [...Array(n).keys()];
return (function generateCombinations (size, numArr) {
const ret = [];
for (let i = 0; i < numArr.length; i++) {
if (size === 1) {
ret.push([numArr[i]]);
}
else {
const sub = generateCombinations(size - 1, numArr.slice(i + 1, numArr.length));
for (let subI = 0; subI < sub.length; subI++) {
const next = sub[subI];
next.unshift(numArr[i]);
ret.push(next);
}
}
}
return ret;
}(m, nArr));
}
```

View File

@@ -0,0 +1,101 @@
---
id: 596e414344c3b2872167f0fe
title: Comma quibbling (створення рядків значень розділених комою)
challengeType: 5
forumTopicId: 302234
dashedName: comma-quibbling
---
# --description--
Comma quibbling це завдання вперше встановлене Еріком Ліппертом в його блозі [blog](https://blogs.msdn.com/b/ericlippert/archive/2009/04/15/comma-quibbling.aspx).
# --instructions--
Напишіть функцію для генерації вихідного рядка, який є об'єднанням вхідних слів з списку/послідовності, де:
<ol>
<li>Введення без слів повертає вихідний рядок лише з двох дужок (<code>"{}"</code>)</li>
<li>Введення лише одного слова, наприклад <code>["ABC"]</code>, повертає вихідний рядок з слова всередині двох дужок, наприклад <code>"{ABC}"</code></li>
<li>Введення двох слів, наприклад <code>["ABC", "DEF"]</code>, повертає вихідний рядок з двох слів всередині двох дужок з розділяючим словом <code>" and "</code>, наприклад <code>"{ABC and DEF}"</code></li>
<li>Введення трьох і більше слів, наприклад <code>["ABC", "DEF", "G", "H"]</code>, повертає вихідний рядок з усіх слів, крім останнього, розділеного на <code>", "</code>, а останнє слово розділене допоможіним <code>" and "</code> і всіма дужками; наприклад <code>"{ABC, DEF, G and H}"</code></li>
</ol>
Перевірте вашу функцію з наступною серією вхідних даних, показуючи ваш вихідний результат тут на сторінці:
<ul>
<li>[] # (Без вхідних слів).</li>
<li>["ABC"]</li>
<li>["ABC", "DEF"]</li>
<li>["ABC", "DEF", "G", "H"]</li>
</ul>
**Зверніть увагу:** Припустіть, що слова не є порожніми рядками у верхньому регістрі для цього завдання.
# --hints--
`quibble` має бути функцією.
```js
assert(typeof quibble === 'function');
```
Функція `quibble(["ABC"])` має повернути рядок.
```js
assert(typeof quibble(['ABC']) === 'string');
```
Функція `quibble([])` має повернути "{}".
```js
assert.equal(quibble(testCases[0]), results[0]);
```
Функція `quibble(["ABC"])` має повернути "{ABC}".
```js
assert.equal(quibble(testCases[1]), results[1]);
```
Функція `quibble(["ABC", "DEF"])` має повернути "{ABC and DEF}".
```js
assert.equal(quibble(testCases[2]), results[2]);
```
Функція `quibble(["ABC", "DEF", "G", "H"])` має повернути "{ABC,DEF,G and H}".
```js
assert.equal(quibble(testCases[3]), results[3]);
```
# --seed--
## --after-user-code--
```js
const testCases = [[], ["ABC"], ["ABC", "DEF"], ["ABC", "DEF", "G", "H"]];
const results = ["{}", "{ABC}", "{ABC and DEF}", "{ABC,DEF,G and H}"];
```
## --seed-contents--
```js
function quibble(words) {
return true;
}
```
# --solutions--
```js
function quibble(words) {
return "{" +
words.slice(0, words.length - 1).join(",") +
(words.length > 1 ? " and " : "") +
(words[words.length - 1] || '') +
"}";
}
```

View File

@@ -0,0 +1,132 @@
---
id: 596e457071c35c882915b3e4
title: Порівняйте список рядків
challengeType: 5
forumTopicId: 302235
dashedName: compare-a-list-of-strings
---
# --description--
Маючи список [list](https://en.wikipedia.org/wiki/List_(abstract_data_type) "wp: List\_(abstract_data_type)") з довільної кількості рядків, реалізуйте функцію для кожної з наступних умов:
<ul>
<li>перевірте, чи всі вони лексично рівні</li>
<li>перевірте, чи кожен рядок лексично менший за той, що після нього (тобто чи список у порядку зростання)</li>
</ul>
# --hints--
`allEqual` має бути функцією.
```js
assert(typeof allEqual === 'function');
```
`azSorted` має бути функцією.
```js
assert(typeof azSorted === 'function');
```
Функція `allEqual(["AA", "AA", "AA", "AA"])` має повернути true.
```js
assert(allEqual(testCases[0]));
```
Функція `azSorted(["AA", "AA", "AA", "AA"])` має повернути false.
```js
assert(!azSorted(testCases[0]));
```
Функція `allEqual(["AA", "ACB", "BB", "CC"])` має повернути false.
```js
assert(!allEqual(testCases[1]));
```
Функція `azSorted(["AA", "ACB", "BB", "CC"])` має повернути true.
```js
assert(azSorted(testCases[1]));
```
Функція `allEqual([])` має повернути true.
```js
assert(allEqual(testCases[2]));
```
Функція `azSorted([])` має повернути true.
```js
assert(azSorted(testCases[2]));
```
Функція `allEqual(["AA"])` має повернути true.
```js
assert(allEqual(testCases[3]));
```
Функція `azSorted(["AA"])` має повернути true.
```js
assert(azSorted(testCases[3]));
```
Функція `allEqual(["BB", "AA"])` має повернути false.
```js
assert(!allEqual(testCases[4]));
```
Функція `azSorted(["BB", "AA"])` має повернути false.
```js
assert(!azSorted(testCases[4]));
```
# --seed--
## --after-user-code--
```js
const testCases = [['AA', 'AA', 'AA', 'AA'], ['AA', 'ACB', 'BB', 'CC'], [], ['AA'], ['BB', 'AA']];
```
## --seed-contents--
```js
function allEqual(arr) {
return true;
}
function azSorted(arr) {
return true;
}
```
# --solutions--
```js
function allEqual(a) {
let out = true;
let i = 0;
while (++i < a.length) {
out = out && (a[i - 1] === a[i]);
} return out;
}
function azSorted(a) {
let out = true;
let i = 0;
while (++i < a.length) {
out = out && (a[i - 1] < a[i]);
} return out;
}
```

View File

@@ -0,0 +1,128 @@
---
id: 596fd036dc1ab896c5db98b1
title: Конвертувати секунди в одиниці часу
challengeType: 5
forumTopicId: 302236
dashedName: convert-seconds-to-compound-duration
---
# --description--
Запустити функцію яка:
<ul>
<li>бере додатнє ціле число, що представляє тривалість в секундах як вхідні дані (наприклад <code>100</code>), і</li>
<li>повертає рядок, котрий показує таку ж тривалість перетворену в тижні, дні, години, хвилини і секунди, як детально описано нижче ( наприклад <code>1 min, 40 sec</code>).</li>
</ul>
Демонстрація того, що вона передає наступні три тестові випадки:
<div style='font-size:115%; font-weight: bold;'>Тестові випадки</div>
| Вхідне число | Вихідне число |
| ------------ | ------------------------- |
| 7259 | <code>2 hr, 59 sec</code> |
| 86400 | <code>1 d</code> |
| 6000000 | <code>9 wk, 6 d, 10 hr, 40 min</code> |
<div style="font-size:115%; font-weight: bold;">Деталі</div>
<ul>
<li>
Варто використовувати наступні п'ять одиниць:
| Unit | Suffix used in Output | Conversion |
| ------ | --------------------- | --------------------- |
| week |!!crwdBlockTags_18_sgaTkcolBdwrc!! | 1 week = 7 days |
| day |!!crwdBlockTags_19_sgaTkcolBdwrc!! | 1 day = 24 hours |
| hour |!!crwdBlockTags_20_sgaTkcolBdwrc!! | 1 hour = 60 minutes |
| minute |!!crwdBlockTags_21_sgaTkcolBdwrc!! | 1 minute = 60 seconds |
| second |!!crwdBlockTags_22_sgaTkcolBdwrc!! | --- |
</li>
<li>
Однак <strong>only</strong> містить кількість не нульових значень при виході (наприклад <code>1 d</code> а не <code>0 wk, 1 d, 0 hr, 0 min, 0 sec</code>).
</li>
<li>
Надавати перевагу максимально великим одиницям над меншими одиницями (наприклад повернути <code>2 min, 10 sec</code> а не <code>1 min, 70 sec</code> чи <code>130 sec</code>).
</li>
<li>
Мімікрійне форматування, показане у тестових випадках ( кількість відсортована від найбільшої одиниці до найменшої і відокремлена комою+пробілом; значення і одиниця всіх значень відділена пробілом).
</li>
</ul>
# --hints--
`convertSeconds` має бути функцією.
```js
assert(typeof convertSeconds === 'function');
```
`convertSeconds(7259)` має повернути `2 hr, 59 sec`.
```js
assert.equal(convertSeconds(testCases[0]), results[0]);
```
`convertSeconds(86400)` має повернути `1 d`.
```js
assert.equal(convertSeconds(testCases[1]), results[1]);
```
`convertSeconds(6000000)` має повернути `9 wk, 6 d, 10 hr, 40 min`.
```js
assert.equal(convertSeconds(testCases[2]), results[2]);
```
# --seed--
## --after-user-code--
```js
const testCases = [7259, 86400, 6000000];
const results = ['2 hr, 59 sec', '1 d', '9 wk, 6 d, 10 hr, 40 min'];
```
## --seed-contents--
```js
function convertSeconds(sec) {
return true;
}
```
# --solutions--
```js
function convertSeconds(sec) {
const localNames = ['wk', 'd', 'hr', 'min', 'sec'];
// compoundDuration :: [String] -> Int -> String
const compoundDuration = (labels, intSeconds) =>
weekParts(intSeconds)
.map((v, i) => [v, labels[i]])
.reduce((a, x) =>
a.concat(x[0] ? [`${x[0]} ${x[1] || '?'}`] : []), []
)
.join(', ');
// weekParts :: Int -> [Int]
const weekParts = intSeconds => [0, 7, 24, 60, 60]
.reduceRight((a, x) => {
const r = a.rem;
const mod = x !== 0 ? r % x : r;
return {
rem: (r - mod) / (x || 1),
parts: [mod].concat(a.parts)
};
}, {
rem: intSeconds,
parts: []
})
.parts;
return compoundDuration(localNames, sec);
}
```

View File

@@ -0,0 +1,79 @@
---
id: 596fda99c69f779975a1b67d
title: Кількість входжень підрядка
challengeType: 5
forumTopicId: 302237
dashedName: count-occurrences-of-a-substring
---
# --description--
Створіть функцію або покажіть вбудовану функцію, щоб порахувати кількість входжень підрядка, що не перекриваються всередині рядка.
Функція має приймати два аргументи:
<ul>
<li>перший аргумент, в якому рядок для пошуку, і</li>
<li>другий підрядок, який шукають.</li>
</ul>
Вона має повертати ціле число.
Відповідність повинна дати найбільшу кількість співпадінь, які не перекриваються.
Загалом, це означає співпадіння з ліва на право або з права на ліво.
# --hints--
`countSubstring` має бути функцією.
```js
assert(typeof countSubstring === 'function');
```
`countSubstring("the three truths", "th")` має повертати `3`.
```js
assert.equal(countSubstring(testCases[0], searchString[0]), results[0]);
```
`countSubstring("ababababab", "abab")` має повертати `2`.
```js
assert.equal(countSubstring(testCases[1], searchString[1]), results[1]);
```
`countSubstring("abaabba*bbaba*bbab", "a*b")` має повертати `2`.
```js
assert.equal(countSubstring(testCases[2], searchString[2]), results[2]);
```
# --seed--
## --after-user-code--
```js
const testCases = ['the three truths', 'ababababab', 'abaabba*bbaba*bbab'];
const searchString = ['th', 'abab', 'a*b'];
const results = [3, 2, 2];
```
## --seed-contents--
```js
function countSubstring(str, subStr) {
return true;
}
```
# --solutions--
```js
function countSubstring(str, subStr) {
const escapedSubStr = subStr.replace(/[.+*?^$[\]{}()|/]/g, '\\$&');
const matches = str.match(new RegExp(escapedSubStr, 'g'));
return matches ? matches.length : 0;
}
```

View File

@@ -0,0 +1,93 @@
---
id: 59713bd26bdeb8a594fb9413
title: Підрахунок монет
challengeType: 5
forumTopicId: 302238
dashedName: count-the-coins
---
# --description--
У валюті [США](https://en.wikipedia.org/wiki/United_States) існує чотири типи звичайних монет:
<ul>
<li>четвертаки (25 центів)</li>
<li>дайми (10 центів)</li>
<li>нікелі (5 центів) та</li>
<li>пенні (1 цент)</li>
</ul>
<p>Існує шість способів розміняти 15 центів:</p>
<ul>
<li>1 дайм та 1 нікель</li>
<li>1 дайм та 5 пенні</li>
<li>3 нікелі</li>
<li>2 нікелі та 5 пенні</li>
<li>1 нікель та 10 пенні</li>
<li>15 пенні</li>
</ul>
# --instructions--
Створіть функцію, яка буде визначати, скількома способами можна розміняти введену кількість `cents`, що представляє суму американських пенні, використовуючи ці поширені монети.
# --hints--
`countCoins` має бути функцією.
```js
assert(typeof countCoins === 'function');
```
`countCoins(15)` має повертати `6`.
```js
assert.equal(countCoins(15), 6);
```
`countCoins(85)` має повертати `163`.
```js
assert.equal(countCoins(85), 163);
```
`countCoins(100)` має повертати `242`.
```js
assert.equal(countCoins(100), 242);
```
# --seed--
## --seed-contents--
```js
function countCoins(cents) {
return true;
}
```
# --solutions--
```js
function countCoins(cents) {
const operands = [1, 5, 10, 25];
const targetsLength = cents + 1;
const operandsLength = operands.length;
const t = [1];
for (let a = 0; a < operandsLength; a++) {
for (let b = 1; b < targetsLength; b++) {
// initialise undefined target
t[b] = t[b] ? t[b] : 0;
// accumulate target + operand ways
t[b] += (b < operands[a]) ? 0 : t[b - operands[a]];
}
}
return t[targetsLength - 1];
}
```

View File

@@ -0,0 +1,167 @@
---
id: 59713da0a428c1a62d7db430
title: Метод Крамера
challengeType: 5
forumTopicId: 302239
dashedName: cramers-rule
---
# --description--
В [лінійній алгебрі](https://en.wikipedia.org/wiki/linear algebra "wp: linear algebra"), [методі Кремера](https://en.wikipedia.org/wiki/Cramer's rule "wp: Cramer's rule") є явною формулою для вирішення [ системи лінійних рівнянь](https://en.wikipedia.org/wiki/system of linear equations "wp: system of linear equations") яка має таку ж кількістю невідомих, допустимих рівнянь, коли система має унікальний розв'язок. Вона виражає розв'язок в межах детермінантів коефіцієнтної матриці (квадрата), і матриць, отриманих з неї шляхом заміни одного стовпця вектором правої сторони рівнянь.
Дано
$\\left\\{\\begin{matrix}a_1x + b_1y + c_1z&= {\\color{red}d_1}\\\\a_2x + b_2y + c_2z&= {\\color{red}d_2}\\\\a_3x + b_3y + c_3z&= {\\color{red}d_3}\\end{matrix}\\right.$
яка є у форматі матриці
$\\begin{bmatrix} a_1 & b_1 & c_1 \\\\ a_2 & b_2 & c_2 \\\\ a_3 & b_3 & c_3 \\end{bmatrix}\\begin{bmatrix} x \\\\ y \\\\ z \\end{bmatrix}=\\begin{bmatrix} {\\color{red}d_1} \\\\ {\\color{red}d_2} \\\\ {\\color{red}d_3} \\end{bmatrix}.$
Тоді значення $x, y$ і $z$ можна знайти так:
$x = \\frac{\\begin{vmatrix} {\\color{red}d_1} & b_1 & c_1 \\\\ {\\color{red}d_2} & b_2 & c_2 \\\\ {\\color{red}d_3} & b_3 & c_3 \\end{vmatrix} } { \\begin{vmatrix} a_1 & b_1 & c_1 \\\\ a_2 & b_2 & c_2 \\\\ a_3 & b_3 & c_3 \\end{vmatrix}}, \\quad y = \\frac {\\begin{vmatrix} a_1 & {\\color{red}d_1} & c_1 \\\\ a_2 & {\\color{red}d_2} & c_2 \\\\ a_3 & {\\color{red}d_3} & c_3 \\end{vmatrix}} {\\begin{vmatrix} a_1 & b_1 & c_1 \\\\ a_2 & b_2 & c_2 \\\\ a_3 & b_3 & c_3 \\end{vmatrix}}, \\text{ and }z = \\frac { \\begin{vmatrix} a_1 & b_1 & {\\color{red}d_1} \\\\ a_2 & b_2 & {\\color{red}d_2} \\\\ a_3 & b_3 & {\\color{red}d_3} \\end{vmatrix}} {\\begin{vmatrix} a_1 & b_1 & c_1 \\\\ a_2 & b_2 & c_2 \\\\ a_3 & b_3 & c_3 \\end{vmatrix} }.$
# --instructions--
Враховуючи таку систему рівнянь:
$\\begin{cases} 2w-x+5y+z=-3 \\\\ 3w+2x+2y-6z=-32 \\\\ w+3x+3y-z=-47 \\\\ 5w-2x-3y+3z=49 \\\\ \\end{cases}$
розв'язок для $w$, $x$, $y$ і $z$, використовуючи правило Крамера.
# --hints--
`cramersRule` має бути функцією.
```js
assert(typeof cramersRule === 'function');
```
`cramersRule([[2, -1, 5, 1], [3, 2, 2, -6], [1, 3, 3, -1], [5, -2, -3, 3]], [-3, -32, -47, 49])` має повернути `[2, -12, -4, 1]`.
```js
assert.deepEqual(cramersRule(matrices[0], freeTerms[0]), answers[0]);
```
`cramersRule([[3, 1, 1], [2, 2, 5], [1, -3, -4]], [3, -1, 2])` має повернути `[1, 1, -1]`.
```js
assert.deepEqual(cramersRule(matrices[1], freeTerms[1]), answers[1]);
```
# --seed--
## --after-user-code--
```js
const matrices = [
[
[2, -1, 5, 1],
[3, 2, 2, -6],
[1, 3, 3, -1],
[5, -2, -3, 3]
],
[
[3, 1, 1],
[2, 2, 5],
[1, -3, -4]
]
];
const freeTerms = [[-3, -32, -47, 49], [3, -1, 2]];
const answers = [[2, -12, -4, 1], [1, 1, -1]];
```
## --seed-contents--
```js
function cramersRule(matrix, freeTerms) {
return true;
}
```
# --solutions--
```js
/**
* Compute Cramer's Rule
* @param {array} matrix x,y,z, etc. terms
* @param {array} freeTerms
* @return {array} solution for x,y,z, etc.
*/
function cramersRule(matrix, freeTerms) {
const det = detr(matrix);
const returnArray = [];
let i;
for (i = 0; i < matrix[0].length; i++) {
const tmpMatrix = insertInTerms(matrix, freeTerms, i);
returnArray.push(detr(tmpMatrix) / det);
}
return returnArray;
}
/**
* Inserts single dimensional array into
* @param {array} matrix multidimensional array to have ins inserted into
* @param {array} ins single dimensional array to be inserted vertically into matrix
* @param {array} at zero based offset for ins to be inserted into matrix
* @return {array} New multidimensional array with ins replacing the at column in matrix
*/
function insertInTerms(matrix, ins, at) {
const tmpMatrix = clone(matrix);
let i;
for (i = 0; i < matrix.length; i++) {
tmpMatrix[i][at] = ins[i];
}
return tmpMatrix;
}
/**
* Compute the determinate of a matrix. No protection, assumes square matrix
* function borrowed, and adapted from MIT Licensed numericjs library (www.numericjs.com)
* @param {array} m Input Matrix (multidimensional array)
* @return {number} result rounded to 2 decimal
*/
function detr(m) {
let ret = 1;
let j;
let k;
const A = clone(m);
const n = m[0].length;
let alpha;
for (j = 0; j < n - 1; j++) {
k = j;
for (let i = j + 1; i < n; i++) { if (Math.abs(A[i][j]) > Math.abs(A[k][j])) { k = i; } }
if (k !== j) {
const temp = A[k]; A[k] = A[j]; A[j] = temp;
ret *= -1;
}
const Aj = A[j];
for (let i = j + 1; i < n; i++) {
const Ai = A[i];
alpha = Ai[j] / Aj[j];
for (k = j + 1; k < n - 1; k += 2) {
const k1 = k + 1;
Ai[k] -= Aj[k] * alpha;
Ai[k1] -= Aj[k1] * alpha;
}
if (k !== n) { Ai[k] -= Aj[k] * alpha; }
}
if (Aj[j] === 0) { return 0; }
ret *= Aj[j];
}
return Math.round(ret * A[j][j] * 100) / 100;
}
/**
* Clone two dimensional Array using ECMAScript 5 map function and EcmaScript 3 slice
* @param {array} m Input matrix (multidimensional array) to clone
* @return {array} New matrix copy
*/
function clone(m) {
return m.map(a => a.slice());
}
```

View File

@@ -0,0 +1,101 @@
---
id: 5a23c84252665b21eecc7e03
title: Сукупне стандартне відхилення
challengeType: 5
forumTopicId: 302240
dashedName: cumulative-standard-deviation
---
# --description--
Напишіть функцію, яка враховує масив чисел як параметр та повертає [стандартне відхилення](https://en.wikipedia.org/wiki/Standard Deviation) послідовності.
# --hints--
`standardDeviation` має бути функцією.
```js
assert(typeof standardDeviation == 'function');
```
`standardDeviation([2, 4, 4, 4, 5, 5, 7, 9])` має повернути число.
```js
assert(typeof standardDeviation([2, 4, 4, 4, 5, 5, 7, 9]) == 'number');
```
`standardDeviation([2, 4, 4, 4, 5, 5, 7, 9])` має повернути `2`.
```js
assert.equal(standardDeviation([2, 4, 4, 4, 5, 5, 7, 9]), 2);
```
`standardDeviation([600, 470, 170, 430, 300])` має повернути `147.323`.
```js
assert.equal(standardDeviation([600, 470, 170, 430, 300]), 147.323);
```
`standardDeviation([75, 83, 96, 100, 121, 125])` має повернути `18.239`.
```js
assert.equal(standardDeviation([75, 83, 96, 100, 121, 125]), 18.239);
```
`standardDeviation([23, 37, 45, 49, 56, 63, 63, 70, 72, 82])` має повернути `16.87`.
```js
assert.equal(
standardDeviation([23, 37, 45, 49, 56, 63, 63, 70, 72, 82]),
16.87
);
```
`standardDeviation([271, 354, 296, 301, 333, 326, 285, 298, 327, 316, 287, 314])` має повернути `22.631`.
```js
assert.equal(
standardDeviation([
271,
354,
296,
301,
333,
326,
285,
298,
327,
316,
287,
314
]),
22.631
);
```
# --seed--
## --seed-contents--
```js
function standardDeviation(arr) {
}
```
# --solutions--
```js
function standardDeviation(arr) {
var sum = 0,
sum_sq = 0,
n = arr.length;
arr.forEach(function(e) {
sum += e;
sum_sq += e * e;
});
var std_dev = Math.sqrt(sum_sq / n - Math.pow(sum / n, 2));
return Math.round(std_dev * 1000) / 1000;
}
```

View File

@@ -0,0 +1,118 @@
---
id: 5a23c84252665b21eecc7e05
title: CUSIP
challengeType: 5
forumTopicId: 302241
dashedName: cusip
---
# --description--
**CUSIP** - це дев'ятизначний абетково-цифровий код, який ідентифікує північноамериканську фінансову безпеку з метою сприяння очищення і врегулювання фінансових угод. CUSIP був прийнятий як американський національний стандарт відповідно до акредитованих стандартів X9.6.
# --instructions--
Запишіть функцію, яка приймає рядок в якості параметра і перевіряє, чи дійсний рядок CUSIP.
# --hints--
`isCusip` має бути функцією.
```js
assert(typeof isCusip == 'function');
```
`isCusip("037833100")` має повертати логічний тип даних.
```js
assert(typeof isCusip('037833100') == 'boolean');
```
`isCusip("037833100")` має повертати `true`.
```js
assert.equal(isCusip('037833100'), true);
```
`isCusip("17275R102")` має повертати `true`.
```js
assert.equal(isCusip('17275R102'), true);
```
`isCusip("38259P50a")` має повертати `false`.
```js
assert.equal(isCusip('38259P50a'), false);
```
`isCusip("38259P508")` має повертати `true`.
```js
assert.equal(isCusip('38259P508'), true);
```
`isCusip("38259P50#")` має повертати `false`.
```js
assert.equal(isCusip('38259P50#'), false);
```
`isCusip("68389X105")` має повертати `true`.
```js
assert.equal(isCusip('68389X105'), true);
```
`isCusip("68389X106")` має повертати `false`.
```js
assert.equal(isCusip('68389X106'), false);
```
`isCusip("5949181")` має повертати `false`.
```js
assert.equal(isCusip('5949181'), false);
```
# --seed--
## --seed-contents--
```js
function isCusip(s) {
}
```
# --solutions--
```js
function isCusip(s) {
if (s.length != 9) return false;
var sum = 0;
var ASCII = x => x.charCodeAt(0);
for (var i = 0; i < 7; i++) {
var c = s.charCodeAt(i);
var v;
if (c >= ASCII('0') && c <= ASCII('9')) {
v = c - 48;
} else if (c >= ASCII('A') && c <= ASCII('Z')) {
v = c - 64; // lower case letters apparently invalid
} else if (c == ASCII('*')) {
v = 36;
} else if (c == ASCII('@')) {
v = 37;
} else if (c == ASCII('#')) {
v = 38;
} else {
return false;
}
if (i % 2 == 1) v *= 2; // check if odd as using 0-based indexing
sum += Math.floor(v / 10) + (v % 10);
}
return s.charCodeAt(8) - 48 == (10 - (sum % 10)) % 10;
}
```

View File

@@ -0,0 +1,203 @@
---
id: 5a23c84252665b21eecc7e06
title: Поділіть прямокутник
challengeType: 5
forumTopicId: 302242
dashedName: cut-a-rectangle
---
# --description--
Даний прямокутник складається з *m* × *n* квадратів. Якщо *m* та *n* не парні, тоді можливо поділити прямокутник вздовж квадратних країв так, щоб утворилось дві з'єднаних частини однакової форми (після розвороту однієї з частин на 180°). Усі варіанту поділу для прямокутників 2 × 2 та 4 × 3 наведено нижче.
<div style="width: 100%; text-align: center;">
<svg xmlns="https://www.w3.org/2000/svg" xmlns:xlink="https://www.w3.org/1999/xlink" width="520" height="170" aria-hidden="true" alt="Diagram showing the possible paths for 2 by 2 and 4 by 3 rectangles">
<style>
.diagram-g { fill: none; stroke: #ccc }
.diagram-s, .diagram-s2 { fill: #bff; stroke: black; fill-opacity: .4 }
.diagram-s2 { fill: #fbf }
.diagram-d { stroke:black; fill:none}
</style>
<defs>
<g id="diagram-m">
<g id="diagram-h4">
<g id="diagram-h2">
<path id="diagram-h" d="m0 10h 640" class="diagram-g"/>
<use xlink:href="#diagram-h" transform="translate(0, 20)"/>
</g>
<use xlink:href="#diagram-h2" transform="translate(0, 40)"/>
</g>
<use xlink:href="#diagram-h4" transform="translate(0, 80)"/>
<g id="diagram-v8">
<g id="diagram-v4">
<g id="diagram-v2">
<path id="diagram-v" d="m10 0v160 m 20 0 v-160" class="diagram-g"/>
<use xlink:href="#diagram-v" transform="translate(40, 0)"/>
</g>
<use xlink:href="#diagram-v2" transform="translate(80, 0)"/>
</g>
<use xlink:href="#diagram-v4" transform="translate(160, 0)"/>
</g>
<use xlink:href="#diagram-v8" transform="translate(320, 0)"/>
</g>
<path id="diagram-b" d="m0 0h80v60h-80z" class="diagram-s"/>
</defs>
<g transform="translate(.5, .5)">
<use xlink:href="#diagram-m"/>
<g transform="translate(10, 10)">
<path d="m0 0v40h40v-40z" class="diagram-s2"/>
<path d="m20 0v40" class="diagram-d"/>
<path d="m60 0v40h40v-40z" class="diagram-s2"/>
<path d="m60 20h40" class="diagram-d"/>
<g transform="translate(120, 0)">
<use xlink:href="#diagram-b"/>
<path d="m0 20h40v20h40" class="diagram-d"/>
</g>
<g transform="translate(220, 0)">
<use xlink:href="#diagram-b"/>
<path d="m0 40h40v-20h40" class="diagram-d"/>
</g>
<g transform="translate(320, 0)">
<use xlink:href="#diagram-b"/>
<path d="m20 0v40h20v-20h20v40" class="diagram-d"/>
</g>
<g transform="translate(420, 0)">
<use xlink:href="#diagram-b"/>
<path d="m60 0v40h-20v-20h-20v40" class="diagram-d"/>
</g>
<g transform="translate(20, 80)">
<use xlink:href="#diagram-b"/>
<path d="m40 0v60" class="diagram-d"/>
</g>
<g transform="translate(120, 80)">
<use xlink:href="#diagram-b"/>
<path d="m60 0v20h-20v20h-20v20" class="diagram-d"/>
</g>
<g transform="translate(220, 80)">
<use xlink:href="#diagram-b"/>
<path d="m20 0v20h20v20h20v20" class="diagram-d"/>
</g>
<g transform="translate(320, 80)">
<use xlink:href="#diagram-b"/>
<path d="m0 20h20v20h20v-20h20v20h20" class="diagram-d"/>
</g>
<g transform="translate(420, 80)">
<use xlink:href="#diagram-b"/>
<path d="m0 40h20v-20h20v20h20v-20h20" class="diagram-d"/>
</g>
</g>
</g>
</svg>
</div>
# --instructions--
Запишіть функцію, яка обчислює кількість різних способів поділити прямокутник *m* × *n*.
# --hints--
`cutRectangle` має бути функцією.
```js
assert(typeof cutRectangle == 'function');
```
`cutRectangle(2, 2)` має повернути число.
```js
assert(typeof cutRectangle(2, 2) == 'number');
```
`cutRectangle(2, 2)` має повернути `2`.
```js
assert.equal(cutRectangle(2, 2), 2);
```
`cutRectangle(4, 3)` має повернути `9`.
```js
assert.equal(cutRectangle(4, 3), 9);
```
`cutRectangle(4, 4)` має повернути `22`.
```js
assert.equal(cutRectangle(4, 4), 22);
```
`cutRectangle(8, 3)` має повернути `53`.
```js
assert.equal(cutRectangle(8, 3), 53);
```
`cutRectangle(7, 4)` має повернути `151`.
```js
assert.equal(cutRectangle(7, 4), 151);
```
# --seed--
## --seed-contents--
```js
function cutRectangle(w, h) {
}
```
# --solutions--
```js
function cutRectangle(w, h) {
if (w % 2 == 1 && h % 2 == 1) return;
var dirs = [[0, -1], [-1, 0], [0, 1], [1, 0]];
var grid = new Array(h);
for (var i = 0; i < grid.length; i++) grid[i] = new Array(w);
var stack = [];
var half = Math.floor((w * h) / 2);
var bits = Math.pow(2, half) - 1;
var result = 0;
for (; bits > 0; bits -= 2) {
for (var i = 0; i < half; i++) {
var r = Math.floor(i / w);
var c = i % w;
grid[r][c] = (bits & (1 << i)) != 0 ? 1 : 0;
grid[h - r - 1][w - c - 1] = 1 - grid[r][c];
}
stack.push(0);
grid[0][0] = 2;
var count = 1;
while (stack.length != 0) {
var pos = stack.pop();
var r = Math.floor(pos / w);
var c = pos % w;
for (var dir of dirs) {
var nextR = r + dir[0];
var nextC = c + dir[1];
if (nextR >= 0 && nextR < h && nextC >= 0 && nextC < w) {
if (grid[nextR][nextC] == 1) {
stack.push(nextR * w + nextC);
grid[nextR][nextC] = 2;
count++;
}
}
}
}
if (count == half) {
result++;
}
}
return result;
}
```

View File

@@ -0,0 +1,90 @@
---
id: 59669d08d75b60482359409f
title: Формат дати
challengeType: 5
forumTopicId: 302243
dashedName: date-format
---
# --description--
Поверніть масив з двома рядками поточної дати із нижченаведеними специфікаціями:
- У першому рядку дата повинна бути у порядку: рік, місяць, день, і розділена дефісом (`-`).
- У першому рядку рік має складатися із 4 цифр.
- У першому рядку місяць і день не повинні містити нулів на початку.
- У другому рядку назви днів тижня та місяців не мають бути скороченими.
- У другому рядку день не має містити нулів на початку.
Приклад кінцевого результату:
```js
['2007-11-23', 'Friday, November 23, 2007']
['2021-3-2', 'Tuesday, March 2, 2021']
```
# --hints--
`getDateFormats` має бути функцією.
```js
assert(typeof getDateFormats === 'function');
```
`getDateFormats` має повернути об'єкт.
```js
assert(typeof getDateFormats() === 'object');
```
`getDateFormats` повинен повернути масив з 2 елементами.
```js
assert(getDateFormats().length === 2);
```
`getDateFormats` має повернути правильну дату в правильному форматі
```js
assert.deepEqual(getDateFormats(), dates, equalsMessage);
```
# --seed--
## --after-user-code--
```js
const getDateSolution = () => {
const date = new Date();
const weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
const fmt1 = `${date.getFullYear()}-${(1 + date.getMonth())}-${date.getDate()}`;
const fmt2 = `${weekdays[date.getDay()]}, ${months[date.getMonth()]} ${date.getDate()}, ${date.getFullYear()}`;
return [fmt1, fmt2];
};
const dates = getDateSolution();
const equalsMessage = `message: <code>getDataFormats()</code> should return <code>["${dates[0]}", "${dates[1]}"]</code>.`;
```
## --seed-contents--
```js
function getDateFormats() {
return true;
}
```
# --solutions--
```js
function getDateFormats() {
const date = new Date();
const weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
const fmt1 = `${date.getFullYear()}-${(1 + date.getMonth())}-${date.getDate()}`;
const fmt2 = `${weekdays[date.getDay()]}, ${months[date.getMonth()]} ${date.getDate()}, ${date.getFullYear()}`;
return [fmt1, fmt2];
}
```

View File

@@ -0,0 +1,109 @@
---
id: 5966c21cf732a95f1b67dd28
title: Зміна дати
challengeType: 5
forumTopicId: 302244
dashedName: date-manipulation
---
# --description--
Маючи рядок із датою у форматі EST, виведіть задану дату у новий рядок, додавши 12 годин. Часовий пояс має бути збережений.
Приклад заданого формату: `"March 6 2009 7:30pm EST"`
Приклад вихідного формату: `"March 7 2009 7:30am EST"`
# --hints--
`add12Hours` має бути функцією.
```js
assert(typeof add12Hours === 'function');
```
`add12Hours(dateString)` має повернути рядок.
```js
assert(typeof add12Hours('January 17 2017 11:43am EST') === 'string');
```
`add12Hours("January 17 2017 11:43am EST")` має видати `"January 17 2017 11:43pm EST"`
```js
assert(
add12Hours('January 17 2017 11:43am EST') === 'January 17 2017 11:43pm EST'
);
```
Необхідна зміна дня. `add12Hours("March 6 2009 7:30pm EST")` має видати `"March 7 2009 7:30am EST"`
```js
assert(add12Hours('March 6 2009 7:30pm EST') === 'March 7 2009 7:30am EST');
```
Необхідна зміна місяця у високосний рік. `add12Hours("February 29 2004 9:15pm EST")` має видати `"March 1 2004 9:15am EST"`
```js
assert(add12Hours('February 29 2004 9:15pm EST') === 'March 1 2004 9:15am EST');
```
Необхідна зміна місяця у звичайні роки. `add12Hours("February 28 1999 3:15pm EST")` має видати `"March 1 1999 3:15am EST"`
```js
assert(add12Hours('February 28 1999 3:15pm EST') === 'March 1 1999 3:15am EST');
```
Необхідна зміна року. `add12Hours("December 31 2020 1:45pm EST")` має видати `"January 1 2021 1:45am EST"`
```js
assert(
add12Hours('December 31 2020 1:45pm EST') === 'January 1 2021 1:45am EST'
);
```
# --seed--
## --seed-contents--
```js
function add12Hours(dateString) {
return true;
}
```
# --solutions--
```js
function add12Hours(dateString) {
const months = ['January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'];
// Get the parts of the string
const parts = dateString.split(' ');
const month = months.indexOf(parts[0]);
const day = parseInt(parts[1], 10);
const year = parseInt(parts[2], 10);
const time = parts[3].split(':');
let hours = parseInt(time[0], 10);
if (time[1].slice(-2) === 'pm') {
hours += 12;
}
const minutes = parseInt(time[1].slice(0, -2), 10);
// Create a date with given parts, and updated hours
const date = new Date();
date.setFullYear(year, month, day);
date.setHours(hours + 12); // Add 12 hours
date.setMinutes(minutes);
let hoursOutput = date.getHours();
let abbreviation = 'am';
if (hoursOutput > 12) {
hoursOutput -= 12;
abbreviation = 'pm';
}
return `${months[date.getMonth()]} ${date.getDate()} ${date.getFullYear()} ${hoursOutput}:${date.getMinutes()}${abbreviation} EST`;
}
```

View File

@@ -0,0 +1,74 @@
---
id: 5966f99c45e8976909a85575
title: День тижня
challengeType: 5
forumTopicId: 302245
dashedName: day-of-the-week
---
# --description--
Компанія вирішила, що кожного разу, коли Різдво припадатиме на неділю, вони видаватимуть робітникам додаткові оплачувані відпустки, так, щоб разом з іншими державними святами, їм не доводилось працювати наступного тижня (з 25 грудня по 1 січня).
# --instructions--
Напишіть функцію, яка потребує роки початку і кінця відліку, щоб видати масив з усіма роками, коли 25 грудня припадає на неділю.
# --hints--
`findXmasSunday` має бути функцією.
```js
assert(typeof findXmasSunday === 'function');
```
`findXmasSunday(2000, 2100)` має видати масив.
```js
assert(typeof findXmasSunday(2000, 2100) === 'object');
```
`findXmasSunday(1970, 2017)` має видати `[1977, 1983, 1988, 1994, 2005, 2011, 2016]`
```js
assert.deepEqual(findXmasSunday(1970, 2017), firstSolution);
```
`findXmasSunday(2008, 2121)` має видати `[2011, 2016, 2022, 2033, 2039, 2044, 2050, 2061, 2067, 2072, 2078, 2089, 2095, 2101, 2107, 2112, 2118]`
```js
assert.deepEqual(findXmasSunday(2008, 2121), secondSolution);
```
# --seed--
## --after-user-code--
```js
const firstSolution = [1977, 1983, 1988, 1994, 2005, 2011, 2016];
const secondSolution = [2011, 2016, 2022, 2033, 2039, 2044, 2050, 2061, 2067, 2072, 2078, 2089, 2095, 2101, 2107, 2112, 2118];
```
## --seed-contents--
```js
function findXmasSunday(start, end) {
return true;
}
```
# --solutions--
```js
function findXmasSunday(start, end) {
const xmasSunday = [];
for (let year = start; year <= end; year++) {
const xmas = new Date(year, 11, 25);
if (xmas.getDay() === 0) {
xmasSunday.push(year);
}
}
return xmasSunday;
}
```

View File

@@ -0,0 +1,210 @@
---
id: 59694356a6e7011f7f1c5f4e
title: Роздати карти для FreeCell
challengeType: 5
forumTopicId: 302246
dashedName: deal-cards-for-freecell
---
# --description--
*FreeCell* - це гра в пасьянс, представлена Полем Альфілем для системи PLATO у 1978. Джим Хорн, представник Microsoft, змінив її ім'я на FreeCell та реалізував гру для системи [DOS](https://rosettacode.org/wiki/DOS "DOS"), а згодом і для [Windows](https://rosettacode.org/wiki/Windows "Windows"). Ця версія представила 32000 нумерованих роздач.
Як тільки гра стала популярною, Джим Хорн розкрив її алгоритм, що дало початок реалізації нових версій FreeCell, які відтворювали роздачі Microsoft. Нумерація роздач сягала від 1 до 32000. Нові версії від Microsoft мають близько 1 мільйону роздач, нумерованих від 1 до 1000000; а деякі варіації дозволяють нумерацію і поза межами цього діапазону.
Алгоритм використовує цей [лінійний конгурентний генератор](https://rosettacode.org/wiki/linear congruential generator "linear congruential generator") від Microsoft C:
<ul>
<li>$state_{n + 1} \equiv 214013 \times state_n + 2531011 \pmod{2^{31}}$</li>
<li>$rand_n = state_n \div 2^{16}$</li>
<li>$rand_n$ знаходиться у діапазоні від 0 до 32767.</li>
</ul>
Після алгоритму:
<ol>
<li>Введіть загальну кількість роздач у RNG (random number generator).
</li><li>Створіть <a href='https://rosettacode.org/wiki/array' title='array' target='_blank'>масив</a> з 52 карт: туз трефи, туз бубни, туз чирви, туз піки, двійка трефи, двійка бубни і т.д. по усім рангам: Туз, 2, 3, 4, 5, 6, 7, 8, 9, 10, Валет, Дама, Король. Індекси масивів від 0 до 51, з тузом трефи на 0 та королем піки на 51.</li>
<li>Поки масив не стане пустим:</li>
<li>Оберіть випадкову карту із індексом ≡ наступне випадкове число (довжина масиву модулів).</li>
<ul>
<li>Поміняйте цю випадкову картку на останню карту масиву.</li>
<li>Видаліть цю випадкову карту із масиву. (Довжина масиву зменшується на 1.)</li>
<li>Роздайте цю випадкову карту.</li>
</ul>
<li>Роздайте усі 52 карти, лицем догори, на 8 стовпчиків. Перші 8 карт на 8 стовпчиків, наступні 8 карт на перші 8 карт, і так далі.</li>
</ol>
**Наприклад:**
**Порядок роздачі карт**
<pre> 1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32
33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48
49 50 51 52</pre>
**Гра #1**
```js
[
['JD', '2D', '9H', 'JC', '5D', '7H', '7C', '5H'],
['KD', 'KC', '9S', '5S', 'AD', 'QC', 'KH', '3H'],
['2S', 'KS', '9D', 'QD', 'JS', 'AS', 'AH', '3C'],
['4C', '5C', 'TS', 'QH', '4H', 'AC', '4D', '7S'],
['3S', 'TD', '4S', 'TH', '8H', '2C', 'JH', '7D'],
['6D', '8S', '8D', 'QS', '6C', '3D', '8C', 'TC'],
['6S', '9C', '2H', '6H']
]
```
**Гра #617**
```js
[
['7D', 'AD', '5C', '3S', '5S', '8C', '2D', 'AH'],
['TD', '7S', 'QD', 'AC', '6D', '8H', 'AS', 'KH'],
['TH', 'QC', '3H', '9D', '6S', '8D', '3D', 'TC'],
['KD', '5H', '9S', '3C', '8S', '7H', '4D', 'JS'],
['4C', 'QS', '9C', '9H', '7C', '6H', '2C', '2S'],
['4S', 'TS', '2H', '5D', 'JC', '6C', 'JH', 'QH'],
['JD', 'KS', 'KC', '4H']
]
```
# --instructions--
Напишіть функцію, щоб дізнатись номер роздачі та роздати карти в такому ж порядку, як у алгоритмі. Функція має видати двовимірний масив, що представляє собою дошку FreeCell.
Роздачі також можна перевірити у [ рішеннях до 1000000 FreeCell ігор](https://freecellgamesolutions.com/). (Знайдіть відеорішення, що покаже початкову роздачу.)
# --hints--
`dealFreeCell` має бути функцією.
```js
assert(typeof dealFreeCell === 'function');
```
`dealFreeCell(seed)` має видати об'єкт.
```js
assert(typeof dealFreeCell(1) === 'object');
```
`dealFreeCell(seed)` має видати масив довжиною 7.
```js
assert(dealFreeCell(1).length === 7);
```
`dealFreeCell(1)` має видати масив ідентичний до прикладу "Гра #1"
```js
assert.deepEqual(dealFreeCell(1), game1);
```
`dealFreeCell(617)` має видати масив ідентичний до прикладу "Гра #617"
```js
assert.deepEqual(dealFreeCell(617), game617);
```
# --seed--
## --after-user-code--
```js
const replaceThis = 3;
const game1 = [
['JD', '2D', '9H', 'JC', '5D', '7H', '7C', '5H'],
['KD', 'KC', '9S', '5S', 'AD', 'QC', 'KH', '3H'],
['2S', 'KS', '9D', 'QD', 'JS', 'AS', 'AH', '3C'],
['4C', '5C', 'TS', 'QH', '4H', 'AC', '4D', '7S'],
['3S', 'TD', '4S', 'TH', '8H', '2C', 'JH', '7D'],
['6D', '8S', '8D', 'QS', '6C', '3D', '8C', 'TC'],
['6S', '9C', '2H', '6H']
];
const game617 = [
['7D', 'AD', '5C', '3S', '5S', '8C', '2D', 'AH'],
['TD', '7S', 'QD', 'AC', '6D', '8H', 'AS', 'KH'],
['TH', 'QC', '3H', '9D', '6S', '8D', '3D', 'TC'],
['KD', '5H', '9S', '3C', '8S', '7H', '4D', 'JS'],
['4C', 'QS', '9C', '9H', '7C', '6H', '2C', '2S'],
['4S', 'TS', '2H', '5D', 'JC', '6C', 'JH', 'QH'],
['JD', 'KS', 'KC', '4H']
];
```
## --seed-contents--
```js
function dealFreeCell(seed) {
return true;
}
```
# --solutions--
```js
// RNG
function FreeCellRNG(seed) {
return {
lastNum: seed,
next() {
this.lastNum = ((214013 * this.lastNum) + 2531011) % (Math.pow(2, 31));
return this.lastNum >> 16;
}
};
}
// Get cards
function getDeck() {
const ranks = ['A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K'];
const suits = ['C', 'D', 'H', 'S'];
const cards = [];
for (let i = 0; i < ranks.length; i += 1) {
for (let j = 0; j < suits.length; j += 1) {
cards.push(`${ranks[i]}${suits[j]}`);
}
}
return cards;
}
function dealFreeCell(seed) {
const rng = FreeCellRNG(seed);
const deck = getDeck();
const deltCards = [[], [], [], [], [], [], []];
let currentColumn = 0;
let currentRow = 0;
let rand;
let temp;
let card;
while (deck.length > 0) {
// Choose a random card
rand = rng.next() % deck.length;
// Swap this random card with the last card in the array
temp = deck[deck.length - 1];
deck[deck.length - 1] = deck[rand];
deck[rand] = temp;
// Remove this card from the array
card = deck.pop();
// Deal this card
deltCards[currentRow].push(card);
currentColumn += 1;
if (currentColumn === 8) {
currentColumn = 0;
currentRow += 1;
}
}
return deltCards;
}
```

View File

@@ -0,0 +1,85 @@
---
id: 596a8888ab7c01048de257d5
title: Deepcopy (Глибоке копіювання)
challengeType: 5
forumTopicId: 302247
dashedName: deepcopy
---
# --description--
Напишіть функцію, що повертає глибоку копію заданого об'єкта. Копія не повинна бути такою самою, як заданий об'єкт.
Це завдання не буде перевірятися для:
<ul>
<li>Об'єктів з властивостями, що є функціями</li>
<li>Date об'єкти або об'єкти з властивостями (які є Date об'єктами)</li>
<li>Регулярні вирази або об'єкти з властивостями (які є регулярними виразами)</li>
<li>Прототип копіювання</li>
</ul>
# --hints--
`deepcopy` має бути функцією.
```js
assert(typeof deepcopy === 'function');
```
`deepcopy({test: "test"})` має повертати об'єкт.
```js
assert(typeof deepcopy(obj1) === 'object');
```
`deepcopy` не має повертати той самий об'єкт, який був заданий.
```js
assert(deepcopy(obj2) != obj2);
```
Під час переходу об'єкта, який містить масив, `deepcopy` має повертати глибоку копію об'єкта.
```js
assert.deepEqual(deepcopy(obj2), obj2);
```
Під час переходу об'єкта, який містить інший об'єкт, `deepcopy` має повертати глибоку копію об'єкта.
```js
assert.deepEqual(deepcopy(obj3), obj3);
```
# --seed--
## --after-user-code--
```js
const obj1 = { test: 'test' };
const obj2 = {
t: 'test',
a: ['an', 'array']
};
const obj3 = {
t: 'try',
o: obj2
};
```
## --seed-contents--
```js
function deepcopy(obj) {
return true;
}
```
# --solutions--
```js
function deepcopy(obj) {
return JSON.parse(JSON.stringify(obj));
}
```

View File

@@ -0,0 +1,132 @@
---
id: 597089c87eec450c68aa1643
title: Визначення примітивного типу даних
challengeType: 5
forumTopicId: 302248
dashedName: define-a-primitive-data-type
---
# --description--
Визначте тип, що поводитися як ціле число, але має найменше допустиме значення 1 та найбільше допустиме значення 10.
Обробка помилок:
<ul>
<li>Якщо ви спробуєте створити <code>Num</code> зі значенням поза діапазоном 1 - 10, він повинен видати <code>TypeError</code> з повідомленням про виникнення помилки <code>'Out of range'</code>.</li>
<li>Якщо ви спробуєте створити <code>Num</code> зі значенням, що не є числом, воно має видати <code>TypeError</code> з повідомленням про виникнення помилки <code>'Not a Number'</code>.</li>
</ul>
# --hints--
`Num` має бути функцією.
```js
assert(typeof Num === 'function');
```
`new Num(4)` має повертати об'єкт.
```js
assert(typeof new Num(4) === 'object');
```
`new Num('test')` має видавати помилку TypeError з повідомленням 'Not a Number'.
```js
assert.throws(() => new Num('test'), TypeError);
```
`new Num(0)` має видавати помилку TypeError з повідомленням 'Out of range'.
```js
assert.throws(() => new Num(0), TypeError);
```
`new Num(-5)` має видавати помилку TypeError з повідомленням 'Out of range'.
```js
assert.throws(() => new Num(-5), TypeError);
```
`new Num(10)` має видавати помилку TypeError з повідомленням 'Out of range'.
```js
assert.throws(() => new Num(11), TypeError);
```
`new Num(20)` має видавати помилку TypeError з повідомленням 'Out of range'.
```js
assert.throws(() => new Num(20), TypeError);
```
`new Num(3) + new Num(4)` має дорівнювати 7.
```js
assert.equal(new Num(3) + new Num(4), 7);
```
`new Num(3) - new Num(4)` має дорівнювати -1.
```js
assert.equal(new Num(3) - new Num(4), -1);
```
`new Num(3) * new Num(4)` має дорівнювати 12.
```js
assert.equal(new Num(3) * new Num(4), 12);
```
`new Num(3) / new Num(4)` має дорівнювати 0.75.
```js
assert.equal(new Num(3) / new Num(4), 0.75);
```
`new Num(3) < new Num(4)` має бути правдою.
```js
assert(new Num(3) < new Num(4));
```
`new Num(3) > new Num(4)` має бути помилкою.
```js
assert(!(new Num(3) > new Num(4)));
```
`(new Num(5)).toString()` має повертати '5'
```js
assert.equal(new Num(5).toString(), '5');
```
# --seed--
## --seed-contents--
```js
function Num(n) {
return n;
}
```
# --solutions--
```js
function Num(n) {
if (isNaN(n)) {
throw new TypeError('Not a Number');
}
if (n < 1 || n > 10) {
throw new TypeError('Out of range');
}
this._value = +n;
}
Num.prototype.valueOf = function() { return this._value; };
Num.prototype.toString = function () { return this._value.toString(); };
```

View File

@@ -0,0 +1,126 @@
---
id: 59f40b17e79dbf1ab720ed7a
title: Номери відділів
challengeType: 5
forumTopicId: 302249
dashedName: department-numbers
---
# --description--
Існує добре організоване місто, яке вирішило призначити номер для кожного з їх відділів:
<ul>
<li>Відділ поліції</li>
<li>Санітарний відділ</li>
<li>Пожежний відділ</li>
</ul>
Кожен відділ може мати номер від 1 до 7 (включно).
Номери кожного з відділу мають бути унікальними (тобто бути відмінними одне від одного) та щоб в сумі було до номера 12.
Шеф поліції не любить непарних чисел і хоче мати парне число для свого відділу.
# --instructions--
Напишіть програму, яка виводить всі дійсні комбінації у вигляді масиву.
```js
[2, 3, 7] [2, 4, 6] [2, 6, 4]
[2, 7, 3] [4, 1, 7] [4, 2, 6]
[4, 3, 5] [4, 5, 3] [4, 6, 2]
[4, 7, 1] [6, 1, 5] [6, 2, 4]
[6, 4, 2] [6, 5, 1]
```
# --hints--
`combinations` мають бути функцією.
```js
assert(typeof combinations === 'function');
```
`combinations([1, 2, 3], 6)` повинні повернути масив.
```js
assert(Array.isArray(combinations([1, 2, 3], 6)));
```
`combinations([1, 2, 3, 4, 5, 6, 7], 12)` мають повернутися як рядок довжиною 14.
```js
assert(combinations(nums, total).length === len);
```
`combinations([1, 2, 3, 4, 5, 6, 7], 12)` повинен повертати всі дійсні комбінації.
```js
assert.deepEqual(combinations(nums, total), result);
```
# --seed--
## --after-user-code--
```js
const nums = [1, 2, 3, 4, 5, 6, 7];
const total = 12;
const len = 14;
const result = [
[2, 3, 7],
[2, 4, 6],
[2, 6, 4],
[2, 7, 3],
[4, 1, 7],
[4, 2, 6],
[4, 3, 5],
[4, 5, 3],
[4, 6, 2],
[4, 7, 1],
[6, 1, 5],
[6, 2, 4],
[6, 4, 2],
[6, 5, 1]
];
```
## --seed-contents--
```js
function combinations(possibleNumbers, total) {
return true;
}
```
# --solutions--
```js
function combinations(possibleNumbers, total) {
let firstNumber;
let secondNumber;
let thridNumber;
const allCombinations = [];
for (let i = 0; i < possibleNumbers.length; i += 1) {
firstNumber = possibleNumbers[i];
if (firstNumber % 2 === 0) {
for (let j = 0; j < possibleNumbers.length; j += 1) {
secondNumber = possibleNumbers[j];
if (j !== i && firstNumber + secondNumber <= total) {
thridNumber = total - firstNumber - secondNumber;
if (thridNumber !== firstNumber && thridNumber !== secondNumber && possibleNumbers.includes(thridNumber)) {
allCombinations.push([firstNumber, secondNumber, thridNumber]);
}
}
}
}
}
return allCombinations;
}
```

View File

@@ -0,0 +1,195 @@
---
id: 59f4eafba0343628bb682785
title: Дискордіанський календар
challengeType: 5
forumTopicId: 302250
dashedName: discordian-date
---
# --description--
Перетворіть дану дату з [Григоріанського календаря ](https://en.wikipedia.org/wiki/Gregorian calendar "wp: Gregorian calendar") в [Дискордіанський календар](https://en.wikipedia.org/wiki/Discordian calendar "wp: Discordian calendar").
# --hints--
`discordianDate` має бути функцією.
```js
assert(typeof discordianDate === 'function');
```
`discordianDate(new Date(2010, 6, 22))` повинен повернутися як `"Pungenday, the 57th day of Confusion in the YOLD 3176"`.
```js
assert(
discordianDate(new Date(2010, 6, 22)) ===
'Pungenday, the 57th day of Confusion in the YOLD 3176'
);
```
`discordianDate(new Date(2012, 1, 28))` повинен повертатися як `"Prickle-Prickle, the 59th day of Chaos in the YOLD 3178"`.
```js
assert(
discordianDate(new Date(2012, 1, 28)) ===
'Prickle-Prickle, the 59th day of Chaos in the YOLD 3178'
);
```
`discordianDate(new Date(2012, 1, 29))` повинен повертатися як `"Setting Orange, the 60th day of Chaos in the YOLD 3178. Святкуйте St. Tib\'s Day!"`.
```js
assert(
discordianDate(new Date(2012, 1, 29)) ===
"Setting Orange, the 60th day of Chaos in the YOLD 3178. Celebrate St. Tib's Day!"
);
```
`discordianDate(new Date(2012, 2, 1))` повинен повертатися як `"Setting Orange, the 60th day of Chaos in the YOLD 3178"`.
```js
assert(
discordianDate(new Date(2012, 2, 1)) ===
'Setting Orange, the 60th day of Chaos in the YOLD 3178'
);
```
`discordianDate(new Date(2010, 0, 5))` повинен повертатися як `"Setting Orange, the 5th day of Chaos in the YOLD 3176. Відсвяткуйте Mungday!"`.
```js
assert(
discordianDate(new Date(2010, 0, 5)) ===
'Setting Orange, the 5th day of Chaos in the YOLD 3176. Celebrate Mungday!'
);
```
`discordianDate(new Date(2011, 4, 3))` повинен повертатися як `"Pungenday, the 50th day of Discord in the YOLD 3177. Відсвяткуйте Discoflux!"`.
```js
assert(
discordianDate(new Date(2011, 4, 3)) ===
'Pungenday, the 50th day of Discord in the YOLD 3177. Celebrate Discoflux!'
);
```
`discordianDate(new Date(2015, 9, 19))` повинен повертатися як `"Boomtime, the 73rd day of Bureaucracy in the YOLD 3181"`.
```js
assert(
discordianDate(new Date(2015, 9, 19)) ===
'Boomtime, the 73rd day of Bureaucracy in the YOLD 3181'
);
```
# --seed--
## --seed-contents--
```js
function discordianDate(date) {
return true;
}
```
# --solutions--
```js
/**
* All Hail Discordia! - this script prints Discordian date using system date.
*
* lang: JavaScript
* author: jklu
* contributors: JamesMcGuigan
*
* source: https://rosettacode.org/wiki/Discordian_date#JavaScript
*/
const seasons = [
'Chaos', 'Discord', 'Confusion',
'Bureaucracy', 'The Aftermath'
];
const weekday = [
'Sweetmorn', 'Boomtime', 'Pungenday',
'Prickle-Prickle', 'Setting Orange'
];
const apostle = [
'Mungday', 'Mojoday', 'Syaday',
'Zaraday', 'Maladay'
];
const holiday = [
'Chaoflux', 'Discoflux', 'Confuflux',
'Bureflux', 'Afflux'
];
Date.prototype.isLeapYear = function() {
const year = this.getFullYear();
if ((year & 3) !== 0) { return false; }
return ((year % 100) !== 0 || (year % 400) === 0);
};
// Get Day of Year
Date.prototype.getDOY = function() {
const dayCount = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
const mn = this.getMonth();
const dn = this.getDate();
let dayOfYear = dayCount[mn] + dn;
if (mn > 1 && this.isLeapYear()) { dayOfYear += 1; }
return dayOfYear;
};
Date.prototype.isToday = function() {
const today = new Date();
return this.getDate() === today.getDate()
&& this.getMonth() === today.getMonth()
&& this.getFullYear() === today.getFullYear()
;
};
function discordianDate(date) {
if (!date) { date = new Date(); }
const y = date.getFullYear();
const yold = y + 1166;
let dayOfYear = date.getDOY();
let celebrateHoliday = null;
if (date.isLeapYear()) {
if (dayOfYear === 60) {
celebrateHoliday = 'St. Tib\'s Day';
}
else if (dayOfYear > 60) {
dayOfYear--;
}
}
dayOfYear--;
const divDay = Math.floor(dayOfYear / 73);
const seasonDay = (dayOfYear % 73) + 1;
if (seasonDay === 5) {
celebrateHoliday = apostle[divDay];
}
if (seasonDay === 50) {
celebrateHoliday = holiday[divDay];
}
const season = seasons[divDay];
const dayOfWeek = weekday[dayOfYear % 5];
const nth = (seasonDay % 10 === 1) ? 'st'
: (seasonDay % 10 === 2) ? 'nd'
: (seasonDay % 10 === 3) ? 'rd'
: 'th';
return ''
+ dayOfWeek
+ ', the ' + seasonDay + nth
+ ' day of ' + season
+ ' in the YOLD ' + yold
+ (celebrateHoliday ? '. Celebrate ' + celebrateHoliday + '!' : '')
;
}
```

View File

@@ -0,0 +1,75 @@
---
id: 5a23c84252665b21eecc7e1e
title: Скалярний добуток
challengeType: 5
forumTopicId: 302251
dashedName: dot-product
---
# --description--
Створіть функцію, щоб обчислити **[скалярний добуток](https://en.wikipedia.org/wiki/Dot product)**, також відомий як **скалярний продукт** двох векторів.
# --hints--
`dotProduct` має бути функцією.
```js
assert(typeof dotProduct == 'function');
```
`dotProduct([1, 3, -5], [4, -2, -1])` має повертатись як число.
```js
assert(typeof dotProduct([1, 3, -5], [4, -2, -1]) == 'number');
```
`dotProduct([1, 3, -5], [4, -2, -1])` має повернути `3`.
```js
assert.equal(dotProduct([1, 3, -5], [4, -2, -1]), 3);
```
`dotProduct([1, 2, 3, 4, 5], [6, 7, 8, 9, 10])` має повернути `130`.
```js
assert.equal(dotProduct([1, 2, 3, 4, 5], [6, 7, 8, 9, 10]), 130);
```
`dotProduct([5, 4, 3, 2], [7, 8, 9, 6])` має повернути `106`.
```js
assert.equal(dotProduct([5, 4, 3, 2], [7, 8, 9, 6]), 106);
```
`dotProduct([-5, 4, -3, 2], [-7, -8, 9, -6])` має повернути `-36`.
```js
assert.equal(dotProduct([-5, 4, -3, 2], [-7, -8, 9, -6]), -36);
```
`dotProduct([17, 27, 34, 43, 15], [62, 73, 48, 95, 110])` має повернути `10392`.
```js
assert.equal(dotProduct([17, 27, 34, 43, 15], [62, 73, 48, 95, 110]), 10392);
```
# --seed--
## --seed-contents--
```js
function dotProduct(ary1, ary2) {
}
```
# --solutions--
```js
function dotProduct(ary1, ary2) {
var dotprod = 0;
for (var i = 0; i < ary1.length; i++) dotprod += ary1[i] * ary2[i];
return dotprod;
}
```

View File

@@ -0,0 +1,214 @@
---
id: 599c333915e0ea32d04d4bec
title: Операції Element-wise
challengeType: 5
forumTopicId: 302252
dashedName: element-wise-operations
---
# --description--
Виконайте основні операції element-wise matrix-matrix і scalar-matrix.
**Виконайте:**
<ul>
<li>додавання</li>
<li>віднімання</li>
<li>множення</li>
<li>ділення</li>
<li>піднесення до степеня</li>
</ul>
Перший параметр буде виконувати операцію "m_add" для додавання матриці та "s_add" для скалярного додавання. Другий і третій параметри будуть матрицями, на яких повинні виконуватися дії.
# --hints--
`operation` має бути функцією.
```js
assert(typeof operation === 'function');
```
`operation("m_add",[[1,2],[3,4]],[[1,2],[3,4]])` має повернути `[[2,4],[6,8]]`.
```js
assert.deepEqual(
operation(
'm_add',
[
[1, 2],
[3, 4]
],
[
[1, 2],
[3, 4]
]
),
[
[2, 4],
[6, 8]
]
);
```
`operation("s_add",[[1,2],[3,4]],2)` має повернути `[[3,4],[5,6]]`.
```js
assert.deepEqual(
operation(
's_add',
[
[1, 2],
[3, 4]
],
2
),
[
[3, 4],
[5, 6]
]
);
```
`operation("m_sub",[[1,2],[3,4]],[[1,2],[3,4]])` має повернути `[[0,0],[0,0]]`.
```js
assert.deepEqual(
operation(
'm_sub',
[
[1, 2],
[3, 4]
],
[
[1, 2],
[3, 4]
]
),
[
[0, 0],
[0, 0]
]
);
```
`operation("m_mult",[[1,2],[3,4]],[[1,2],[3,4]])` має повернути `[[1,4],[9,16]]`.
```js
assert.deepEqual(
operation(
'm_mult',
[
[1, 2],
[3, 4]
],
[
[1, 2],
[3, 4]
]
),
[
[1, 4],
[9, 16]
]
);
```
`operation("m_div",[[1,2],[3,4]],[[1,2],[3,4]])` має повернути `[[1,1],[1,1]]`.
```js
assert.deepEqual(
operation(
'm_div',
[
[1, 2],
[3, 4]
],
[
[1, 2],
[3, 4]
]
),
[
[1, 1],
[1, 1]
]
);
```
`operation("m_exp",[[1,2],[3,4]],[[1,2],[3,4]])` має повернути `[[1,4],[27,256]]`.
```js
assert.deepEqual(
operation(
'm_exp',
[
[1, 2],
[3, 4]
],
[
[1, 2],
[3, 4]
]
),
[
[1, 4],
[27, 256]
]
);
```
`operation("m_add",[[1,2,3,4],[5,6,7,8]],[[9,10,11,12],[13,14,15,16]])` має повернути `[[10,12,14,16],[18,20,22,24]]`.
```js
assert.deepEqual(
operation(
'm_add',
[
[1, 2, 3, 4],
[5, 6, 7, 8]
],
[
[9, 10, 11, 12],
[13, 14, 15, 16]
]
),
[
[10, 12, 14, 16],
[18, 20, 22, 24]
]
);
```
# --seed--
## --seed-contents--
```js
function operation(op, arr1, arr2) {
}
```
# --solutions--
```js
function operation(op, arr1, arr2) {
const ops = {
add: ((a, b) => a + b),
sub: ((a, b) => a - b),
mult: ((a, b) => a * b),
div: ((a, b) => a / b),
exp: ((a, b) => Math.pow(a, b))
};
const ifm = op.startsWith('m');
const doOp = ops[op.substring(2)];
for (let i = 0; i < arr1.length; i++) {
for (let j = 0; j < arr1[0].length; j++) {
arr1[i][j] = doOp(arr1[i][j], (ifm) ? (arr2[i][j]) : (arr2));
}
}
return arr1;
}
```

View File

@@ -0,0 +1,138 @@
---
id: 599d0ba974141b0f508b37d5
title: Emirp primes (Прості числа Емірпа)
challengeType: 5
forumTopicId: 302253
dashedName: emirp-primes
---
# --description--
Emirp (**простий** написаний у зворотному порядку) є простими числами, які при зміні (у їх десятковому представленні) є різними простими числами.
# --instructions--
Напишіть функцію, яка:
<ul>
<li>Показує перші <code>n</code> прості числа.</li>
<li>Показує прості числа в діапазоні.</li>
<li>Показує кількість простих чисел у діапазоні.</li>
<li>Показує <code>n<sup>th</sup></code> простого числа.</li>
</ul>
Функція повинна приймати два параметри. Перший отримає `n` або діапазон у вигляді масиву. Другий отримає логічний тип, що вказує, чи повертається функція emirps у вигляді масиву або окремого числа (кількість простих чисел у діапазоні або просте число <code>n<sup>th</sup></code>). Відповідно до параметрів функція повинна повертати масив або число.
# --hints--
`emirps` має бути функцією.
```js
assert(typeof emirps === 'function');
```
`emirps(20,true)` повинен повертатися як `[13,17,31,37,71,73,79,97,107,113,149,157,167,179,199,311,337,347,359,389]`
```js
assert.deepEqual(emirps(20, true), [
13,
17,
31,
37,
71,
73,
79,
97,
107,
113,
149,
157,
167,
179,
199,
311,
337,
347,
359,
389
]);
```
`emirps(1000)` повинен повертатися як `70529`
```js
assert.deepEqual(emirps(1000), 70529);
```
`emirps([7700,8000],true)` повинен повертатися як `[7717,7757,7817,7841,7867,7879,7901,7927,7949,7951,7963]`
```js
assert.deepEqual(emirps([7700, 8000], true), [
7717,
7757,
7817,
7841,
7867,
7879,
7901,
7927,
7949,
7951,
7963
]);
```
`emirps([7700,8000],false)` повинен повертатися як `11`
```js
assert.deepEqual(emirps([7700, 8000], false), 11);
```
# --seed--
## --seed-contents--
```js
function emirps(n) {
}
```
# --solutions--
```js
function emirps(num, showEmirps)
{
const is_prime = function(n)
{
if (!(n % 2) || !(n % 3)) return false;
let p = 1;
while (p * p < n)
{ if (n % (p += 4) == 0 || n % (p += 2) == 0)
{ return false; } }
return true;
};
const is_emirp = function(n) {
const r = parseInt(n.toString().split('').reverse().join(''));
return r != n && is_prime(n) && is_prime(r);
};
let i,
arr = [];
if (typeof num === 'number') {
for (i = 0; arr.length < num; i++) if (is_emirp(i)) arr.push(i);
// first x emirps
if (showEmirps) return arr;
// xth emirp
return arr.pop();
}
if (Array.isArray(num)) {
for (i = num[0]; i <= num[1]; i++) if (is_emirp(i)) arr.push(i);
// emirps between x .. y
if (showEmirps) return arr;
// number of emirps between x .. y
return arr.length;
}
}
```

View File

@@ -0,0 +1,96 @@
---
id: 599d15309e88c813a40baf58
title: Ентропія
challengeType: 5
forumTopicId: 302254
dashedName: entropy
---
# --description--
Обчислити інформаційну ентропію заданого вхідного рядка.
Зважаючи на дискретну випадкову змінну $X$, яка є рядком для $N$ "символів" (всіх символів), що складається з $n$ різних символів (n=2 для бінарних), інформаційна ентропія для X в бітах/символах є:
$H_2(X) = -\\sum\_{i=1}^n \\frac{count_i}{N} \\log_2 \\left(\\frac{count_i}{N}\\right)$
де $count_i$ - це підрахунок символу $n_i$.
# --hints--
`entropy` має бути функцією.
```js
assert(typeof entropy === 'function');
```
`entropy("0")` має повернути `0`
```js
assert.equal(entropy('0'), 0);
```
`entropy("01")` має повернути `1`
```js
assert.equal(entropy('01'), 1);
```
`entropy("0123")` має повернути `2`
```js
assert.equal(entropy('0123'), 2);
```
`entropy("01234567")` має повернути `3`
```js
assert.equal(entropy('01234567'), 3);
```
`entropy("0123456789abcdef")` має повернути `4`
```js
assert.equal(entropy('0123456789abcdef'), 4);
```
`entropy("1223334444")` має повернути `1.8464393446710154`
```js
assert.equal(entropy('1223334444'), 1.8464393446710154);
```
# --seed--
## --seed-contents--
```js
function entropy(s) {
}
```
# --solutions--
```js
function entropy(s) {
// Create a dictionary of character frequencies and iterate over it.
function process(s, evaluator) {
let h = Object.create(null),
k;
s.split('').forEach(c => {
h[c] && h[c]++ || (h[c] = 1); });
if (evaluator) for (k in h) evaluator(k, h[k]);
return h;
}
// Measure the entropy of a string in bits per symbol.
let sum = 0,
len = s.length;
process(s, (k, f) => {
const p = f / len;
sum -= p * Math.log(p) / Math.log(2);
});
return sum;
}
```

View File

@@ -0,0 +1,130 @@
---
id: 5987fd532b954e0f21b5d3f6
title: Індекс рівноваги
challengeType: 5
forumTopicId: 302255
dashedName: equilibrium-index
---
# --description--
Індекс рівноваги послідовності є індексом, де сума елементів у нижчих індексах дорівнює сумі елементів при більш високих індексах.
До прикладу, у послідовності $A$:
<ul style='list-style: none;'>
<li><big>$A_0 = -7$</big></li>
<li><big>$A_1 = 1$</big></li>
<li><big>$A_2 = 5$</big></li>
<li><big>$A_3 = 2$</big></li>
<li><big>$A_4 = -4$</big></li>
<li><big>$A_5 = 3$</big></li>
<li><big>$A_6 = 0$</big></li>
</ul>
`3` є індексом рівноваги, тому що:
<ul style='list-style: none;'>
<li><big>$A_0 + A_1 + A_2 = A_4 + A_5 + A_6$</big></li>
</ul>
`6` є також індексом рівноваги, тому що:
<ul style='list-style: none;'>
<li><big>$A_0 + A_1 + A_2 + A_3 + A_4 + A_5 = 0$</big></li>
</ul>
(сума нульових елементів дорівнює нулю)
`7` не є індексом рівноваги, оскільки це не є дійсним індексом послідовності $A$.
# --instructions--
Напишіть функцію, яка, за умови послідовності, повертає її показники рівноваги (якщо такі є).
Припустимо, що послідовність може бути дуже довгою.
# --hints--
`equilibrium` має бути функцією.
```js
assert(typeof equilibrium === 'function');
```
`equilibrium([-7, 1, 5, 2, -4, 3, 0])` має повертати `[3,6]`.
```js
assert.deepEqual(equilibrium(equilibriumTests[0]), ans[0]);
```
`equilibrium([2, 4, 6])` має повертати `[]`.
```js
assert.deepEqual(equilibrium(equilibriumTests[1]), ans[1]);
```
`equilibrium([2, 9, 2])` має повертати `[1]`.
```js
assert.deepEqual(equilibrium(equilibriumTests[2]), ans[2]);
```
`equilibrium([1, -1, 1, -1, 1, -1, 1])` має повертати `[0,1,2,3,4,5,6]`.
```js
assert.deepEqual(equilibrium(equilibriumTests[3]), ans[3]);
```
`equilibrium([1])` має повертати `[0]`.
```js
assert.deepEqual(equilibrium(equilibriumTests[4]), ans[4]);
```
`equilibrium([])` має повертати `[]`.
```js
assert.deepEqual(equilibrium(equilibriumTests[5]), ans[5]);
```
# --seed--
## --after-user-code--
```js
const equilibriumTests =
[[-7, 1, 5, 2, -4, 3, 0], // 3, 6
[2, 4, 6], // empty
[2, 9, 2], // 1
[1, -1, 1, -1, 1, -1, 1], // 0,1,2,3,4,5,6
[1], // 0
[] // empty
];
const ans = [[3, 6], [], [1], [0, 1, 2, 3, 4, 5, 6], [0], []];
```
## --seed-contents--
```js
function equilibrium(a) {
}
```
# --solutions--
```js
function equilibrium(a) {
let N = a.length,
i,
l = [],
r = [],
e = [];
for (l[0] = a[0], r[N - 1] = a[N - 1], i = 1; i < N; i++)
{ l[i] = l[i - 1] + a[i], r[N - i - 1] = r[N - i] + a[N - i - 1]; }
for (i = 0; i < N; i++)
{ if (l[i] === r[i]) e.push(i); }
return e;
}
```

View File

@@ -0,0 +1,156 @@
---
id: 599d1566a02b571412643b84
title: Ефіопське множення
challengeType: 5
forumTopicId: 302257
dashedName: ethiopian-multiplication
---
# --description--
Ефіопське множення - це метод множення цілих чисел за допомогою лише додавання, подвоєння та ділення на два.
**Метод:**
<ol>
<li>Візьміть два числа, щоб помножити і записати їх зверху двох стовпчиків</li>
<li>У лівому стовпчику діліть на два останнє число кілька разів, відкидаючи будь-які остачі, і записуйте результат нижче в цей самий стовпчик, поки не запишете значення <code>1</code></li>
<li>У правій колонці множте на два останнє число повторювано і запишіть результат нижче. зупиніться, коли ви вписали число в тому ж рядку, де лівий стовпчик показує <code>1</code></li>
<li>Перегляньте отриману таблицю, і відкиньте будь-який рядок, де значення в лівому стовпчику - парне</li>
<li>Підсумуйте значення в правому стовпчику так, щоб отримати результат множення двох початкових цифр</li>
</ol>
** Наприклад:** `17 × 34`
<pre>17 34
</pre>
Ділимо перший стовпчик:
<pre>17 34
8
4
2
1
</pre>
Множимо на два другий стовпчик:
<pre>17 34
8 68
4 136
2 272
1 544
</pre>
Закреслюємо рядки, в яких перша комірка парна:
<pre>17 34
8 <strike>68</strike>
4 <strike>136</strike>
2 <strike>272</strike>
1 544
</pre>
Підсумовуємо решту цифр в правому стовпчику:
<!-- markdownlint-disable MD003 -->
<pre>17 34
8 --
4 ---
2 ---
1 544
====
578
</pre>
<!-- markdownlint-enable MD003 -->
Отже `17` помножене `34`, за ефіопським методом - `578`.
# --instructions--
Завданням полягає в тому, щоб визначити три іменовані функції, методи, процедури, підпрограми:
<ol>
<li>від одиниці до половини цілого числа,</li>
<li>від одиниці до подвійного цілого, і</li>
<li>від одиниці до моменту, коли ціле число є парним</li>
</ol>
Використовуйте ці функції, щоб створити функцію, яка виконує ефіопське множення.
<!-- markdownlint-disable MD046-->
# --hints--
`eth_mult` має бути функцією.
```js
assert(typeof eth_mult === 'function');
```
`eth_mult(17,34)` має повертати `578`.
```js
assert.equal(eth_mult(17, 34), 578);
```
`eth_mult(23,46)` має повертати `1058`.
```js
assert.equal(eth_mult(23, 46), 1058);
```
`eth_mult(12,27)` має повертати `324`.
```js
assert.equal(eth_mult(12, 27), 324);
```
`eth_mult(56,98)` має повертати `5488`.
```js
assert.equal(eth_mult(56, 98), 5488);
```
`eth_mult(63,74)` має повертати `4662`.
```js
assert.equal(eth_mult(63, 74), 4662);
```
# --seed--
## --seed-contents--
```js
function eth_mult(a, b) {
}
```
# --solutions--
```js
function eth_mult(a, b) {
let sum = 0; a = [a]; b = [b];
let half = a => a / 2,
double = a => a * 2,
is_even = a => a % 2 == 0;
while (a[0] !== 1) {
a.unshift(Math.floor(half(a[0])));
b.unshift(double(b[0]));
}
for (let i = a.length - 1; i > 0; i -= 1) {
if (!is_even(a[i])) {
sum += b[i];
}
}
return sum + b[0];
}
```

View File

@@ -0,0 +1,152 @@
---
id: 59880443fb36441083c6c20e
title: Метод Ейлера
challengeType: 5
forumTopicId: 302258
dashedName: euler-method
---
# --description--
Метод Ейлера чисельно наближує рішення звичайних рівнянь першого порядку (ODE) з заданим початковим значенням. Це явний метод вирішення проблем із початковими значеннями (IVP), описаний у [цій статті](https://www.freecodecamp.org/news/eulers-method-explained-with-examples/ "news: Euler's Method Explained with Examples").
ODE повинен бути наданий за такою формою:
<ul style='list-style: none;'>
<li><big>$\frac{dy(t)}{dt} = f(t,y(t))$</big></li>
</ul>
з початковим значенням
<ul style='list-style: none;'>
<li><big>$y(t_0) = y_0$</big></li>
</ul>
Щоб отримати числове рішення, ми заміняємо похідну на LHS з скінченним наближенням до різниці:
<ul style='list-style: none;'>
<li><big>$\frac{dy(t)}{dt} \approx \frac{y(t+h)-y(t)}{h}$</big></li>
</ul>
тоді вирішіть для $y(t+h)$:
<ul style='list-style: none;'>
<li><big>$y(t+h) \approx y(t) + h \, \frac{dy(t)}{dt}$</big></li>
</ul>
що є тим самим, як і
<ul style='list-style: none;'>
<li><big>$y(t+h) \approx y(t) + h \, f(t,y(t))$</big></li>
</ul>
Тоді, правило повторного рішення:
<ul style='list-style: none;'>
<li><big>$y_{n+1} = y_n + h \, f(t_n, y_n)$</big></li>
</ul>
де $h$ - розмір кроку, найбільш відповідний параметр для точності рішення. Менший розмір кроку збільшує точність, але й обчислювальні витрати, тому вони завжди повинні бути підібрані вручну відповідно до завдань.
**Приклад: Закон Ньютона**
Закон Ньютона описує як об’єкт початкової температури $T(t_0) = T_0$ охолоджується в умовах температури $T_R$:
<ul style='list-style: none;'>
<li><big>$\frac{dT(t)}{dt} = -k \, \Delta T$</big></li>
</ul>
або
<ul style='list-style: none;'>
<li><big>$\frac{dT(t)}{dt} = -k \, (T(t) - T_R)$</big></li>
</ul>
Він каже, що швидкість охолодження $\\frac{dT(t)}{dt}$ $ об'єктів пропорційна поточній різниці температури $\\Delta T = (T(t) - T_R)$ в навколишнє середовище.
Аналітичне рішення, яке ми будемо порівняти з числовим наближенням, є
<ul style='list-style: none;'>
<li><big>$T(t) = T_R + (T_0 - T_R) \; e^{-k t}$</big></li>
</ul>
# --instructions--
Реалізуйте розпорядок методу Ейлера та використовуйте його для рішення заданого прикладу закону Ньютона про три різні розміри кроку:
<ul>
<li><code>2 s</code></li>
<li><code>5 s</code> і</li>
<li><code>10 s</code></li>
</ul>
та порівняти з аналітичним рішенням.
**Початкові значення:**
<ul>
<li>початкова температура <big>$T_0$</big> має бути <code>100 °C</code></li>
<li>температура кімнати <big>$T_R$</big> має бути <code>20 °C</code></li>
<li>охолодження константи <big>$k$</big> має буде <code>0.07</code></li>
<li>інтервал обчислення повинен бути від <code>0 s</code> до <code>100 s</code></li>
</ul>
Перший параметр функції - це початковий час, другий параметр - початкова температура, третій - минулий час і четвертий параметр - крок розміру.
# --hints--
`eulersMethod` має бути функцією.
```js
assert(typeof eulersMethod === 'function');
```
`eulersMethod(0, 100, 100, 2)` має повернути число.
```js
assert(typeof eulersMethod(0, 100, 100, 2) === 'number');
```
`eulersMethod(0, 100, 100, 2)` має повернути 20.0424631833732.
```js
assert.equal(eulersMethod(0, 100, 100, 2), 20.0424631833732);
```
`eulersMethod(0, 100, 100, 5)` має повернути 20.01449963666907.
```js
assert.equal(eulersMethod(0, 100, 100, 5), 20.01449963666907);
```
`eulersMethod(0, 100, 100, 10)` має повернути 20.000472392.
```js
assert.equal(eulersMethod(0, 100, 100, 10), 20.000472392);
```
# --seed--
## --seed-contents--
```js
function eulersMethod(x1, y1, x2, h) {
}
```
# --solutions--
```js
function eulersMethod(x1, y1, x2, h) {
let x = x1;
let y = y1;
while ((x < x2 && x1 < x2) || (x > x2 && x1 > x2)) {
y += h * (-0.07 * (y - 20));
x += h;
}
return y;
}
```

View File

@@ -0,0 +1,74 @@
---
id: 598de241872ef8353c58a7a2
title: Оцініть біноміальні коефіцієнти
challengeType: 5
forumTopicId: 302259
dashedName: evaluate-binomial-coefficients
---
# --description--
Напишіть функцію для обчислення біноміального коефіцієнта для заданих значень n і k.
Рекомендується така формула:
$\\binom{n}{k} = \\frac{n!}{(n-k)!k!} = \\frac{n(n-1)(n-2)\\ldots(n-k+1)}{k(k-1)(k-2)\\ldots 1}$
# --hints--
`binom` має бути функцією.
```js
assert(typeof binom === 'function');
```
`binom(5,3)` має повернути число 10.
```js
assert.equal(binom(5, 3), 10);
```
`binom(7,2)` має повернути число 21.
```js
assert.equal(binom(7, 2), 21);
```
`binom(10,4)` має повернути число 210.
```js
assert.equal(binom(10, 4), 210);
```
`binom(6,1)` має повернути число 6.
```js
assert.equal(binom(6, 1), 6);
```
`binom(12,8)` має повернути число 495.
```js
assert.equal(binom(12, 8), 495);
```
# --seed--
## --seed-contents--
```js
function binom(n, k) {
}
```
# --solutions--
```js
function binom(n, k) {
let coeff = 1;
for (let i = n - k + 1; i <= n; i++) coeff *= i;
for (let i = 1; i <= k; i++) coeff /= i;
return coeff;
}
```

View File

@@ -0,0 +1,246 @@
---
id: 59e09e6d412c5939baa02d16
title: Виконайте алгоритм Маркова
challengeType: 5
forumTopicId: 302260
dashedName: execute-a-markov-algorithm
---
# --description--
Створіть інтерпретацію для сторінки [алгоритм Маркова](https://en.wikipedia.org/wiki/Markov algorithm "wp: Markov algorithm").
Граматична побудова правил:
<pre>[ruleset] ::= (([comment] | [rule]) [newline]+)*
[comment] ::= # {[будь-який символ]}
[rule] ::= [pattern] [whitespace] -> [whitespace] [.] [replacement]
[whitespace] ::= ([tab] | [space]) [[whitespace]]
</pre>
У кожному рядку по одному правилу.
Якщо `.` (крапка) стоїть перед \[replacement], тоді це кінцеве правило, у випадку котрого інтерпретатор повинен зупинити виконання.
Набір правил складається з послідовності певних норм та умовних додатків.
Правила
Використовуйте поточні вправи на початку:
**Правило 1:**
<pre># Цей файл з правилами взято з Вікіпедії:
#
<code>http://en.wikipedia.org/wiki/Markov_Algorithm</code>
A -> яблуко
B -> мішок
S -> магазин
T -> артикль "the"
магазин -> мій брат
невикористаний -> .кінцеве правило
</pre>
Зразок тексту `я купив B As у T S.` має повернути речення`я купив мішок яблук у мого брата.`
**Правило 2:**
Перевірка кінцевого правила
<pre># Трохи змінено правила з Вікіпедії
A -> яблуко
B -> сумка
S -> . магазин
T -> the
магазин -> мій брат
ніколи не використовувався -> .кінцева умова
</pre>
Зразок тексту `я купив B As у T S.`повинен згенерувати`я купив мішок яблук у цьому магазині.`
**Правило 3:**
Ці вправи призначені для правильної заміни порядку, вони можуть закрити замінні послідовності, базовані на простих регулярних виразах, якщо символів спеціальних регулярних виразів не оминули.
<pre># BNF правила синтаксичного тестування
-> яблуко
WWW -> з
Bgage -> ->.*
B -> сумка
->. -> гроші
W -> WW
S -> . магазин
T ->
магазин -> мій брат
ніколи не використовувався -> закінчення правила
</pre>
Зразок тексту `я купив As B W свої Bgage у T S.` повинний перетворитися у `я купив мішок яблук за свої гроші у T магазині.`
**Правило 4:**
Ці тести для правильного порядку сканування правил може ловити підпрограми, що сканують в неправильному порядку. Це реалізує загальний двовимірний механізм множення. (Зверніть увагу, що вхідний вираз повинен бути в підкресленнях у цій реалізації.)
<pre>### Унарний механізм множення для тестування виконання алгоритму Маркова
### За методом Дона Феллоуза.
Одинарна додаткова система:
_+1 -> _1+
1+1 -> 11+
# Передача для конвертування від поділу множинного до звичайного
# додаток
1! -> !1,! -> !+
_! -> _
# Одинарне множення шляхом дублювання лівої сторони, часів правої сторони
1*1 -> x,@y
1x -> xX
X, -> 1,1
X1 -> 1X
_x -> _X
,x -> ,X
y1 -> 1y
y_ -> _
# Наступний етап додавання
1@1 -> x,@y
1@_ -> @_
,@_ -> !_
++ -> +
# Припинення очищення для додатку:
_1 -> 1
1+_ -> 1
_+_ ->
</pre>
Зразок тексту `_1111*11111_` повинний згенерувати наступне`11111111111111111111`
**Правило 5:**
Проста [Машина Тюрінга](http://en.wikipedia.org/wiki/Turing_machine "link: http&#x3A;//en.wikipedia.org/wiki/Turing_machine"), здійснюючи трьохстановий [busy beaver](http://en.wikipedia.org/wiki/Busy_beaver "link: http&#x3A;//en.wikipedia.org/wiki/Busy_beaver").
Стрічка складається з`0`s та`1`s, станами є `A`, `B`, `C` і `H` (для `H`alt), початкова позиція визначається написанням літери стану перед символом початку. Усі частини початкової стрічки, на яких працює машина, мають вказані у вхідних даних.
Окрім демонстрації того, що алгоритм Маркова є довершенням Тюрінга, він допоміг мені виявити проблему у реалізації C++, котра не була помічною у попередніх правилах.
<pre># Машина Тюрінга: трьохстановий Busy beaver:
#
#стан А, символ 0=> пишемо 1, переносимо праворуч, новий стан В
А0 -> 1B
# стан А, символ 1=> пишемо 1, переносимо ліворуч, новий стан C
0A1 -> C01
1A1 -> C11
# стан В, символ 0 => пишемо 1, переносимо ліворуч, новий стан А
0B0 -> A01
1B0 -> A11
# стан B, символ 1 => пишемо 1, переносимо праворуч, новий стан В
B1 -> 1B
# стан С, символ => 1 пишемо 1, переносимо ліворуч, новий стан В
0C0 -> B01
1C0 -> B11
# стан С, символ => 1 пишемо 1, переносимо ліворуч, зупиняємо
0C1 -> H01
1C1 -> H11
</pre>
Цей набір правил повинен перетворитися з `000000A000000` у `00011H1111000`
# --hints--
`markov` повинен бути функцією.
```js
assert(typeof markov === 'function');
```
`markov(["A -> apple","B -> bag","S -> shop","T -> the","the shop -> my brother","a never used -> .terminating rule"],"I bought a B of As from T S.")` повинно повертати "я купив мішок яблук у мого брата".
```js
assert.deepEqual(markov(rules[0], tests[0]), outputs[0]);
```
`markov(["A -> apple","B -> bag","S -> .shop","T -> the","the shop -> my brother","a never used -> .terminating rule"],"I bought a B of As from T S.")` має повертати "я купив мішок яблук у цьому магазині".
```js
assert.deepEqual(markov(rules[1], tests[1]), outputs[1]);
```
`markov(["A -> apple","WWWW -> with","Bgage -> ->.*","B -> bag","->.* -> money","W -> WW","S -> .shop","T -> the","the shop -> my brother","a never used -> .terminating rule"],"I bought a B of As W my Bgage from T S.")` має повертати "я купив мішок яблук за мої грошу у цьому магазині".
```js
assert.deepEqual(markov(rules[2], tests[2]), outputs[2]);
```
`Марков(["_+1 -> _1+","1+1 -> 11+","1! -> !1",",! -> !+","_! -> _","1*1 -> x,@y","1x -> xX","X, -> 1,1","X1 -> 1X","_x -> _X",", -> ,X","y1 -> 1y","y_ -> _","1@1 -> x,@y","1@_ -> @_",",@_ -> ! ","++ -> +","_1 -> 1","1+_ -> ","_+_ -> "],"_11*11111_")` повинен повернути "11111111111111111111111111111111111111".
```js
assert.deepEqual(markov(rules[3], tests[3]), outputs[3]);
```
`markov(["A0 -> 1B","0A1 -> C01","1A1 -> C11","0B0 -> A01","1B0 -> A11","B1 -> 1B","0C0 -> B01","1C0 -> B11","0C1 -> H01","1C1 -> H11"],"")` повинен повернути "00011H1111000".
```js
assert.deepEqual(markov(rules[4], tests[4]), outputs[4]);
```
# --seed--
## --after-user-code--
```js
let rules=[["A -> apple","B -> bag","S -> shop","T -> the","the shop -> my brother","a never used -> .terminating rule"],
["A -> apple","B -> bag","S -> .shop","T -> the","the shop -> my brother","a never used -> .terminating rule"],
["A -> apple","WWWW -> with","Bgage -> ->.*","B -> bag","->.* -> money","W -> WW","S -> .shop","T -> the","the shop -> my brother","a never used -> .terminating rule"],
["_+1 -> _1+","1+1 -> 11+","1! -> !1",",! -> !+","_! -> _","1*1 -> x,@y","1x -> xX","X, -> 1,1","X1 -> 1X","_x -> _X",",x -> ,X","y1 -> 1y","y_ -> _","1@1 -> x,@y","1@_ -> @_",",@_ -> !_","++ -> +","_1 -> 1","1+_ -> 1","_+_ -> "],
["A0 -> 1B","0A1 -> C01","1A1 -> C11","0B0 -> A01","1B0 -> A11","B1 -> 1B","0C0 -> B01","1C0 -> B11","0C1 -> H01","1C1 -> H11"]];
let tests=["I bought a B of As from T S.",
"I bought a B of As from T S.",
"I bought a B of As W my Bgage from T S.",
"_1111*11111_",
"000000A000000"];
let outputs=["I bought a bag of apples from my brother.",
"I bought a bag of apples from T shop.",
"I bought a bag of apples with my money from T shop.",
"11111111111111111111",
"00011H1111000"]
```
## --seed-contents--
```js
function markov(rules,test) {
}
```
# --solutions--
```js
function markov(rules,test) {
let pattern = new RegExp("^([^#]*?)\\s+->\\s+(\\.?)(.*)");
let origTest = test;
let captures = [];
rules.forEach(function(rule){
let m = pattern.exec(rule);
for (let j = 0; j < m.length; j++)
m[j] = m[j + 1];
captures.push(m);
});
test = origTest;
let copy = test;
for (let j = 0; j < captures.length; j++) {
let c = captures[j];
test = test.replace(c[0], c[2]);
if (c[1]==".")
break;
if (test!=copy) {
j = -1;
copy = test;
}
}
return test;
}
```

View File

@@ -0,0 +1,229 @@
---
id: 59e0a8df964e4540d5abe599
title: Execute Brain****
challengeType: 5
forumTopicId: 302261
dashedName: execute-brain
---
# --description--
Напишіть функцію для запуску Brain\*\*\*\* перекладача. Функція бере рядок як параметр і на виході також виходить рядок. Деталі наведено нижче:
RCBF є набором [Brainf\*\*\*](https://rosettacode.org/wiki/Brainf*** "Brainf\*\*\*") компіляторів та інтерпретаторів, написаних Rosetta code різними мовами.
Нижче наведено посилання на кожну з версій RCBF.
Впровадження потребує чіткого дотримання таких інструкцій:Пропустіть збіг <code> якщо комірка під курсором дорівнює 0&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td> <code>]</code>&lt;/td>
&lt;td>Поверніться до функції збігу <code>/</code> якщо комірка під курсором не є 0&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p spaces-before="0">Розмір комірки може бути довільним, EOF (&lt;em x-id="3">E&lt;/em>nd-&lt;em x-id="3">O&lt;/em>-&lt;em x-id="3">F&lt;/em>ile) підтримка не є обов’язковою, так само як і наявність обмеженої й необмеженої пам’яті.&lt;/p>
&lt;h1 spaces-before="0">--hints--&lt;/h1>
&lt;p spaces-before="0">&lt;code>brain(bye)</code> повинен вивести рядок</p>
```js
assert(typeof brain(bye) === 'string');
```
`brain ("++++++[>++++++++++<-]>+++++.")` повинен вивести рядок “A”
```js
assert.equal(brain('++++++[>++++++++++<-]>+++++.'), 'A');
```
`brain(bye)`повинен вивести `Goodbye, World!\r\n`
```js
assert.equal(brain(bye), 'Goodbye, World!\r\n');
```
`brain(hello)`повинен вивести`Hello World!\n`
```js
assert.equal(brain(hello), 'Hello World!\n');
```
`brain(fib)`повинен вивести`1, 1, 2, 3, 4, 5, 8, 13, 21, 34, 55, 89`
```js
assert.equal(brain(fib), '1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89');
```
# --seed--
## --before-user-code--
```js
let fib=`+
++
+++
++++
+>+>>
>>++++
+++++++
++++++++
+++++++++
++++++++++
++++++>++++
++++++++++++
+++++++++++++
+++<<<<<<[>[>>
>>>>+>+<<<<<<<-
]>>>>>>>[<<<<<<<
+>>>>>>>-]<[>++++
++++++[-<-[>>+>+<<
<-]>>>[<<<+>>>-]+<[
>[-]<[-]]>[<<[>>>+<<
<-]>>[-]]<<]>>>[>>+>+
<<<-]>>>[<<<+>>>-]+<[>
[-]<[-]]>[<<+>>[-]]<<<<
<<<]>>>>>[++++++++++++++
+++++++++++++++++++++++++
+++++++++.[-]]++++++++++<[
->-<]>+++++++++++++++++++++
+++++++++++++++++++++++++++.
[-]<<<<<<<<<<<<[>>>+>+<<<<-]>
>>>[<<<<+>>>>-]<-[>>.>.<<<[-]]
<<[>>+>+<<<-]>>>[<<<+>>>-]<<[<+
>-]>[<+>-]<<<-]`;
let hello='++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.'
let bye='++++++++++[>+>+++>++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++>++++++++++++<<<<<<<<<-]>>>>+.>>>>+..<.<++++++++.>>>+.<<+.<<<<++++.<++.>>>+++++++.>>>.+++.<+++++++.--------.<<<<<+.<+++.---.';
```
## --seed-contents--
```js
function brain(prog) {
}
```
# --solutions--
```js
function brain(prog){
var output="";
var code; // formatted code
var ip = 0; // current instruction within code
var nest = 0; // current bracket nesting (for Out button)
var ahead = []; // locations of matching brackets
var data = [0]; // data array (mod by +, -)
var dp = 0; // index into data (mod by <, >)
var inp = 0; // current input character (fetch with ,)
var quit = 0;
var commands = {
'>':function() { if (++dp >= data.length) data[dp]=0 },
'<':function() { if (--dp < 0) quit++ },
'+':function() { ++data[dp] },
'-':function() { --data[dp] },
'[':function() { if (!data[dp]) ip = ahead[ip]; else ++nest },
']':function() { if ( data[dp]) ip = ahead[ip]; else --nest },
',':function() {
var c = document.getElementById("input").value.charCodeAt(inp++);
data[dp] = isNaN(c) ? 0 : c; // EOF: other options are -1 or no change
},
'.':function() {
output+=String.fromCharCode(data[dp]);
/*var s = document.getElementById("output").innerHTML)
+ String.fromCharCode(data[dp]);
s = s.replace(/\n/g,"<br>").replace(/ /g,"&amp;nbsp;");
document.getElementById("output").innerHTML = s;*/
},
};
let ar=prog.split('');
var st = [], back, error = -1;
for (ip=0; ip<ar.length; ip++) {
switch(ar[ip]) {
case '[':
st.push(ip);
break;
case ']':
if (st.length == 0) error = ip;
back = st.pop();
ahead[ip] = back;
ahead[back] = ip;
break;
}
}
for(ip=0;ip<ar.length;ip++){
if(commands.hasOwnProperty(ar[ip]))
commands[ar[ip]]();
}
return output;
}
```

View File

@@ -0,0 +1,139 @@
---
id: 598ee8b91b410510ae82efef
title: Генератор простих чисел з можливістю розширення
challengeType: 5
forumTopicId: 302262
dashedName: extensible-prime-generator
---
# --description--
Напишіть генератор простих чисел, в порядку, який автоматично налаштується на генерацію будь-якого достатньо великого простого числа.
Генератор повинен мати здатність:
<ul>
<li>Показувати перші <code>n</code> прості числа</li>
<li>Показувати прості числа в діапазоні</li>
<li>Показувати число простих чисел у діапазоні</li>
<li>Показувати <code>n<sup>th</sup></code> просте число</li>
</ul>
Функція повинна мати два параметри. Перший отримає `n` або діапазон у вигляді масиву. Другий отримає логічний тип даних, що вказує, чи повертає функція прості числа у вигляді масиву або одного і того ж числа (кількість простих чисел у діапазоні або <code>n<sup>th</sup></code> просте число). Відповідно до параметрів функція має повернути масив.
# --hints--
`primeGenerator` має бути функцією.
```js
assert(typeof primeGenerator === 'function');
```
`primeGenerator(20, true)` має повернути `[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]`.
```js
assert.deepEqual(primeGenerator(20, true), [
2,
3,
5,
7,
11,
13,
17,
19,
23,
29,
31,
37,
41,
43,
47,
53,
59,
61,
67,
71
]);
```
`primeGenerator([100, 150], true)` має повернути `[101, 103, 107, 109, 113, 127, 131, 137, 139, 149]`.
```js
assert.deepEqual(primeGenerator([100, 150], true), [
101,
103,
107,
109,
113,
127,
131,
137,
139,
149
]);
```
`primeGenerator([7700, 8000], false)` має повернути `30`.
```js
assert.equal(primeGenerator([7700, 8000], false), 30);
```
`primeGenerator(10000, false)` має повернути `104729`.
```js
assert.equal(primeGenerator(10000, false), 104729);
```
# --seed--
## --seed-contents--
```js
function primeGenerator(num, showPrimes) {
}
```
# --solutions--
```js
function primeGenerator(num, showPrimes) {
let i,
arr = [];
function isPrime(num) {
// try primes <= 16
if (num <= 16) { return (
num == 2 || num == 3 || num == 5 || num == 7 || num == 11 || num == 13
); }
// cull multiples of 2, 3, 5 or 7
if (num % 2 == 0 || num % 3 == 0 || num % 5 == 0 || num % 7 == 0)
{ return false; }
// cull square numbers ending in 1, 3, 7 or 9
for (let i = 10; i * i <= num; i += 10) {
if (num % (i + 1) == 0) return false;
if (num % (i + 3) == 0) return false;
if (num % (i + 7) == 0) return false;
if (num % (i + 9) == 0) return false;
}
return true;
}
if (typeof num === 'number') {
for (i = 0; arr.length < num; i++) if (isPrime(i)) arr.push(i);
// first x primes
if (showPrimes) return arr;
// xth prime
return arr.pop();
}
if (Array.isArray(num)) {
for (i = num[0]; i <= num[1]; i++) if (isPrime(i)) arr.push(i);
// primes between x .. y
if (showPrimes) return arr;
// number of primes between x .. y
return arr.length;
}
}
```

View File

@@ -0,0 +1,80 @@
---
id: 597b2b2a2702b44414742771
title: Факторіал
challengeType: 5
forumTopicId: 302263
dashedName: factorial
---
# --description--
Напишіть функцію для повернення факторіалу числа.
Факторіал числа визначається як:
<pre><big>n! = n * (n-1) * (n-2) * ..... * 1</big>
</pre>
Наприклад:
<ul>
<li><code>3! = 3 * 2 * 1 = 6</code></li>
<li><code>4! = 4 * 3 * 2 * 1 = 24</code></li>
</ul>
**Примітка:** `0! = 1`
# --hints--
`factorial` має бути функцією.
```js
assert(typeof factorial === 'function');
```
`factorial(2)` має повернути число.
```js
assert(typeof factorial(2) === 'number');
```
`factorial(3)` має повернути число 6.
```js
assert.equal(factorial(3), 6);
```
`factorial(5)` має повернути число 120.
```js
assert.equal(factorial(5), 120);
```
`factorial(10)` має повернути число 3,628,800.
```js
assert.equal(factorial(10), 3628800);
```
# --seed--
## --seed-contents--
```js
function factorial(n) {
}
```
# --solutions--
```js
function factorial(n) {
let sum = 1;
while (n > 1) {
sum *= n;
n--;
}
return sum;
}
```

View File

@@ -0,0 +1,148 @@
---
id: 598eea87e5cf4b116c3ff81a
title: Фактори числа Мерсенна
challengeType: 5
forumTopicId: 302264
dashedName: factors-of-a-mersenne-number
---
# --description--
Число Мерсенна - це число у вигляді <code>2<sup>P</sup>-1</code>.
Якщо `P` є простим, то число Мерсенна може бути простим числом Мерсенна. (Якщо `P` не є простим, число Мерсенна також не є простим.)
У пошуку простих чисел Мерсенна вигідно усунути експоненти, знайшовши невеликий фактор перед початком, потенційно довжину, [тест Лукас-Лемер](https://rosettacode.org/wiki/Lucas-Lehmer test "Lucas-Lehmer test").
Існують дуже ефективні алгоритми визначення, чи число ділиться на <code>2<sup>P</sup>-1</code> (або відповідно, якщо <code>2<sup>P</sup> мод (число) = 1</code>).
Деякі мови вже мають вбудовані реалізації цієї операції експонента і моду (так званої modPow або подібні).
Нижче зрозуміло, як реалізувати цей modPow самостійно:
Наприклад, обчислимо <code>2<sup>23</sup> мод 47</code>.
Перетворимо експонент 23 у двійковий, ви отримаєте 10111. Починаючи з <code><tt>квадрат</tt> = 1</code>, повторно піднести до квадрату.
Видаліть верхній біт степеня, і якщо його 1 помножити на `square` на основу піднесення до степеня (2), потім обчислити <code><tt>квадрат</tt> модуль 47</code>.
Використовуйте результат модуля від останнього кроку як початкове значення `square` в наступному кроці:
<pre>Видалити необов'язковий
квадрат, помножений на 2 мод 47
------------ ------- ---
1*1 = 1 0111 1*2 = 2
2*2 = 4 0 111 без 4
4*4 16 = 1 11 16*2 = 32
32*32 4*32 1024 1 1024*2 = 2048
27*2 = 7291 *2 = 1458 1*2 = 1458
</pre>
Починаючи з <code>2<sup></sup> мод 47 = 1</code>, 47 є фактором <code>2<sup>P</sup>-1</code>.
(Щоб побачити це, відніміть 1 від обох сторін: <code>2<sup>23</sup>-1 = 0 мод 47</code>)
Оскільки ми показали, що 47 це фактор, <code>2<sup>23</sup>-1</code> не є простим.
Подальші властивості Мерсенного числа дозволяють нам ще більше вдосконалити процес.
Будь-який фактор, `q` з <code>2<sup>P</sup>-1</code> повинен бути у вигляді `2kP+1`, `k` це додатне ціле число або нуль. Крім того, `q` має бути `1` або `7 mod 8`.
Нарешті будь-який потенційний множник `q` має бути [prime](https://rosettacode.org/wiki/Primality by Trial Division "Primality by Trial Division").
Як і в інших алгоритмах пробного ділення, алгоритм припиняється, коли `2kP+1 > sqrt(N)`. Ці в першу чергу тести працюють лише з цифрами Мерсенна, де `P` - це просте число. Наприклад, <code>M<sub>4</sub>=15</code> не дає ніяких чинників, використовуючи ці технології, але фактори в 3 та 5, жоден з яких не відповідає `2kP+1`.
# --instructions--
Використовуючи вказаний метод, знайти коефіцієнт <code>2<sup>р</sup>-1</code>.
# --hints--
`check_mersenne` має бути функцією.
```js
assert(typeof check_mersenne === 'function');
```
`check_mersenne(3)` має повернути рядок.
```js
assert(typeof check_mersenne(3) == 'string');
```
`check_mersenne(3)`повинен повертатися рядок `M3 = 2^3-1 is prime`.
```js
assert.equal(check_mersenne(3), 'M3 = 2^3-1 is prime');
```
`check_mersenne(23)` повинен повертатися як рядок `M23 = 2^23-1 is composite with factor 47`.
```js
assert.equal(check_mersenne(23), 'M23 = 2^23-1 is composite with factor 47');
```
`check_mersenne(929)` повинен повертати рядок `M929 = 2^929-1 is composite with factor 13007`.
```js
assert.equal(
check_mersenne(929),
'M929 = 2^929-1 is composite with factor 13007'
);
```
# --seed--
## --seed-contents--
```js
function check_mersenne(p) {
}
```
# --solutions--
```js
function check_mersenne(p){
function isPrime(value){
for (let i=2; i < value; i++){
if (value % i == 0){
return false;
}
if (value % i != 0){
return true;
}
}
}
function trial_factor(base, exp, mod){
let square, bits;
square = 1;
bits = exp.toString(2).split('');
for (let i=0,ln=bits.length; i<ln; i++){
square = Math.pow(square, 2) * (bits[i] == 1 ? base : 1) % mod;
}
return (square == 1);
}
function mersenne_factor(p){
let limit, k, q;
limit = Math.sqrt(Math.pow(2,p) - 1);
k = 1;
while ((2*k*p - 1) < limit){
q = 2*k*p + 1;
if (isPrime(q) && (q % 8 == 1 || q % 8 == 7) && trial_factor(2,p,q)){
return q; // q is a factor of 2**p-1
}
k++;
}
return null;
}
let f, result;
result="M"+p+" = 2^"+p+"-1 is ";
f = mersenne_factor(p);
result+=f == null ? "prime" : "composite with factor "+f;
return result;
}
```

View File

@@ -0,0 +1,74 @@
---
id: 597f1e7fbc206f0e9ba95dc4
title: Множники цілого числа
challengeType: 5
forumTopicId: 302265
dashedName: factors-of-an-integer
---
# --description--
Напишіть функцію, що повертає множники додатного цілого числа у вигляді масиву.
Ці множники є додатними цілими числами, за допомогою яких число, яке розкладають на множники, можна поділити так, щоб отримати результат цілого додатного числа.
# --hints--
`factors` має бути функцією.
```js
assert(typeof factors === 'function');
```
`factors(45)` має повернути `[1,3,5,9,15,45]`.
```js
assert.deepEqual(factors(45), ans[0]);
```
`factors(53)` має повернути `[1,53]`.
```js
assert.deepEqual(factors(53), ans[1]);
```
`factors(64)` має повернути `[1,2,4,8,16,32,64]`.
```js
assert.deepEqual(factors(64), ans[2]);
```
# --seed--
## --after-user-code--
```js
const ans=[[1,3,5,9,15,45],[1,53],[1,2,4,8,16,32,64]];
```
## --seed-contents--
```js
function factors(num) {
}
```
# --solutions--
```js
function factors(num)
{
let n_factors = [], i, sqr=Math.floor(Math.sqrt(num));
for (i = 1; i <=sqr ; i += 1)
if (num % i === 0)
{
n_factors.push(i);
if (num / i !== i)
n_factors.push(num / i);
}
n_factors.sort(function(a, b){return a - b;});
return n_factors;
}
```

View File

@@ -0,0 +1,109 @@
---
id: 59c3ec9f15068017c96eb8a3
title: Ряд Фарея
challengeType: 5
forumTopicId: 302266
dashedName: farey-sequence
---
# --description--
[Ряд Фарея](https://en.wikipedia.org/wiki/Farey sequence "wp: Farey sequence") <code>F<sub>n</sub></code> of order`n` є рядом повністю скорочених дробів між `0` та `1`, які у нескороченому виді мають знаменники, менші від або такі, які дорівнюють `n` у порядку зростання.
*Ряд Фарея* деколи помилково називають *Серією Фарея*.
Кожен ряд Фарея:
<ul>
<li>починається зі значення 0, вираженого дробом $ \frac{0}{1}$</li>
<li>закінчується значенням 1, вираженим дробом {1}{1}$.</li>
</ul>
Послідовностями рядів Фарея від `1` до `5` є:
<ul>
<li style='list-style: none;'>${\bf\it{F}}_1 = \frac{{0}{1},\frac{1}{1}$</li>
<li style='list-style: none;'>${\bf\it{F}}_2 = \frac{0}{1}, \frac{1}{2}, \frac{1}{1}$</li>
<li style='list-style: none;'>${\bf\it{F}}_3 = \frac{0}{1}, \frac{1}{3}, \frac{1}{2}, \frac{2}{3}, \frac{1}{1}$</li>
<li style='list-style: none;'>${\bf\it{F}}_4 = \frac{0}{1}, \frac{1}{4}, \frac{1}{3}, \frac{1}{2}, \frac{2}{3}, \frac{3}{4}, \frac{1}{1}$</li>
<li style='list-style: none;'>${\bf\it{F}}_5 = \frac{0}{1}, \frac{1}{5}, \frac{1}{4}, \frac{1}{3}, \frac{2}{5}, \frac{1}{2}, \frac{3}{5}, \frac{2}{3}, \frac{3}{4}, \frac{4}{5}, \frac{1}{1}$</li>
</ul>
# --instructions--
Напишіть функцію, яка повертає послідовність ряду Фарея`n`. Функція повинна мати один параметр, який є`n`. Вона має повернути послідовність у вигляді масиву.
# --hints--
`farey` має бути функцією.
```js
assert(typeof farey === 'function');
```
`farey(3)` має повернути масив
```js
assert(Array.isArray(farey(3)));
```
`farey(3)` має повернути `["1/3","1/2","2/3"]`
```js
assert.deepEqual(farey(3), ['1/3', '1/2', '2/3']);
```
`farey(4)` має повернути `["1/4","1/3","1/2","2/4","2/3","3/4"]`
```js
assert.deepEqual(farey(4), ['1/4', '1/3', '1/2', '2/4', '2/3', '3/4']);
```
`farey(5)` має повернути `["1/5","1/4","1/3","2/5","1/2","2/4","3/5","2/3","3/4","4/5"]`
```js
assert.deepEqual(farey(5), [
'1/5',
'1/4',
'1/3',
'2/5',
'1/2',
'2/4',
'3/5',
'2/3',
'3/4',
'4/5'
]);
```
# --seed--
## --seed-contents--
```js
function farey(n) {
}
```
# --solutions--
```js
function farey(n){
let farSeq=[];
for(let den = 1; den <= n; den++){
for(let num = 1; num < den; num++){
farSeq.push({
str:num+"/"+den,
val:num/den});
}
}
farSeq.sort(function(a,b){
return a.val-b.val;
});
farSeq=farSeq.map(function(a){
return a.str;
});
return farSeq;
}
```

View File

@@ -0,0 +1,133 @@
---
id: 598eef80ba501f1268170e1e
title: Послідовність n-крокових чисел Фібоначчі
challengeType: 5
forumTopicId: 302267
dashedName: fibonacci-n-step-number-sequences
---
# --description--
Ця серія чисел є розширенням звичайної [послідовності Фібоначчі](https://rosettacode.org/wiki/Fibonacci sequence "Fibonacci sequence") де:
<ol>
<li>Для $n = 2$ ми маємо послідовність Фібоначчі; з початковими значеннями $[1, 1]$ і $F_k^2 = F_{k-1}^2 + F_{k-2}^2$</li>
<li>Для $n = 3$ ми маємо послідовність трібоначчі; з початковими значеннями $[1, 2]$ і $F_k^3 = F_{k-1}^3 + F_{k-2}^3 + F_{k-3}^3$</li>
<li>Для $n = 4$ маємо послідовність тетраначчі; з початковими значеннями $[1, 2, 4]$ та $F_k^4 = F_{k-1}^4 + F_{k-2}^4 + F_{k-3}^4 + F_{k-4}^4$...</li>
<li>Для загального $n>2$ ми маємо послідовність Фібоначчі $n$-крокову - $F_k^n$; з початковими значеннями з перших $n$ значень $(n-1)$'th $n$-крокової послідовності Фібоначчі $F_k^{n-1}$; і $k$'th значення цієї $n$'ої послідовності - $F_k^n = \sum_{i=1}^{(n)} {F_{k-i}^{(n)}$</li>
</ol>
Для невеликих значень $n$, <ahref="https://en.wikipe[іноді використовують грецькі числівникові префікси](https://en.wikipedia.org/wiki/Number prefix#Greek_series "wp: Number prefix#Greek_series") щоб індивідуально дати назву кожній послідовності.
Послідовність $n$- крокових чисел Фібоначчі:
| $n$ | Назва послідовності | Значення |
| --- | ------------------- | ------------------------------------------------------ |
| 2 | фібоначчі | 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 ... |
| 3 | трібоначчі | 1 1 2 4 7 13 24 44 81 149 274 504 927 1705 3136 ... |
| 4 | тетрабоначчі | 1 1 2 4 8 15 29 56 108 208 401 773 1490 2872 5536 ... |
| 5 | пентаначчі | 1 1 2 4 8 16 31 61 120 236 464 912 1793 3525 6930 ... |
| 6 | гексаначчі | 1 1 2 4 8 16 32 63 125 248 492 976 1936 3840 7617 ... |
| 7 | гептаначчі | 1 1 2 4 8 16 32 64 127 253 504 1004 2000 3984 7936 ... |
| 8 | октоначчі | 1 1 2 4 8 16 32 64 128 255 509 1016 2028 4048 8080 ... |
| 9 | нонаначчі | 1 1 2 4 8 16 32 64 128 256 511 1021 2040 4076 8144 ... |
| 10 | деканаччі | 1 1 2 4 8 16 32 64 128 256 512 1023 2045 4088 8172 ... |
Союзні послідовності можна створити там, де початкові значення змінюються: [Послідовність Люка](https://en.wikipedia.org/wiki/Lucas number "wp: Lucas number") сумує два попередніх значення, так само як серія Фібоначчі для $n= 2$, але використовує рядок $\[2, 1]$ як початкові значення.
# --instructions--
Напишіть функцію для створення послідовностей $n$-крокових чисел Фібоначчі та послідовностей Люка. Перший параметр буде $n$. Другий параметр - це кількість елементів, які будуть повернені. Третій параметр визначає чи виводити послідовність Фібоначчі чи послідовність Лукаса. Якщо параметр є `"f"`, то поверніть послідовність Фібоначчі і якщо він `"l"`, то поверніть послідовність Лукаса. Послідовності необхідно повернути у вигляді масиву.
# --hints--
`fib_luc` має бути функцією.
```js
assert(typeof fib_luc === 'function');
```
`fib_luc(2,10,"f")` має повернути `[1,1,2,3,5,8,13,21,34,55]`.
```js
assert.deepEqual(fib_luc(2, 10, 'f'), ans[0]);
```
`fib_luc(3,15,"f")` має повернути `[1,1,2,4,7,13,24,44,81,149,274,504,927,1705,3136]`.
```js
assert.deepEqual(fib_luc(3, 15, 'f'), ans[1]);
```
`fib_luc(4,15,"f")` має повернути `[1,1,2,4,8,15,29,56,108,208,401,773,1490,2872,5536]`.
```js
assert.deepEqual(fib_luc(4, 15, 'f'), ans[2]);
```
`fib_luc(2,10,"l")` має повернути `[ 2, 1, 3, 4, 7, 11, 18, 29, 47, 76]`.
```js
assert.deepEqual(fib_luc(2, 10, 'l'), ans[3]);
```
`fib_luc(3,15,"l")` має повернути `[ 2, 1, 3, 6, 10, 19, 35, 64, 118, 217, 399, 734, 1350, 2483, 4567 ]`.
```js
assert.deepEqual(fib_luc(3, 15, 'l'), ans[4]);
```
`fib_luc(4,15,"l")` має повернути `[ 2, 1, 3, 6, 12, 22, 43, 83, 160, 308, 594, 1145, 2207, 4254, 8200 ]`.
```js
assert.deepEqual(fib_luc(4, 15, 'l'), ans[5]);
```
`fib_luc(5,15,"l")` має повернути `[ 2, 1, 3, 6, 12, 24, 46, 91, 179, 352, 692, 1360, 2674, 5257, 10335 ]`.
```js
assert.deepEqual(fib_luc(5, 15, 'l'), ans[6]);
```
# --seed--
## --after-user-code--
```js
const ans = [[1,1,2,3,5,8,13,21,34,55],
[1,1,2,4,7,13,24,44,81,149,274,504,927,1705,3136],
[1,1,2,4,8,15,29,56,108,208,401,773,1490,2872,5536],
[ 2, 1, 3, 4, 7, 11, 18, 29, 47, 76],
[ 2, 1, 3, 6, 10, 19, 35, 64, 118, 217, 399, 734, 1350, 2483, 4567 ],
[ 2, 1, 3, 6, 12, 22, 43, 83, 160, 308, 594, 1145, 2207, 4254, 8200 ],
[ 2, 1, 3, 6, 12, 24, 46, 91, 179, 352, 692, 1360, 2674, 5257, 10335 ]];
```
## --seed-contents--
```js
function fib_luc(n, len, w) {
}
```
# --solutions--
```js
function fib_luc(n, len, w) {
function nacci(a, n, len) {
while (a.length < len) {
let sum = 0;
for (let i = Math.max(0, a.length - n); i < a.length; i++)
sum += a[i];
a.push(sum);
}
return a;
}
if(w=="f"){
return nacci(nacci([1,1], n, n), n, len);
}else{
return nacci(nacci([2,1], n, n), n, len);
}
}
```

View File

@@ -0,0 +1,75 @@
---
id: 597f24c1dda4e70f53c79c81
title: Послідовність Фібоначчі
challengeType: 5
forumTopicId: 302268
dashedName: fibonacci-sequence
---
# --description--
Напишіть функцію для створення числа Фібоначчі <code>n<sup>th</sup></code>.
Число Фібоначчі <code>n<sup>th</sup></code>задається:
<code>F<sub>n</sub> = F<sub>n-1</sub> + F<sub>n-2</sub></code>
Першими двома членами послідовностей є 0 і 1.
Отже, послідовність наступна: 0, 1, 1, 2, 3, 5, 8, 13...
# --hints--
`fibonacci` має бути функцією.
```js
assert(typeof fibonacci === 'function');
```
`fibonacci(2)` має повернути число.
```js
assert(typeof fibonacci(2) == 'number');
```
`fibonacci(3)` має повернути число 2.
```js
assert.equal(fibonacci(3), 2);
```
`fibonacci(5)` має повернути число 5.
```js
assert.equal(fibonacci(5), 5);
```
`fibonacci(10)` має повернути число 55.
```js
assert.equal(fibonacci(10), 55);
```
# --seed--
## --seed-contents--
```js
function fibonacci(n) {
}
```
# --solutions--
```js
function fibonacci(n) {
let a = 0, b = 1, t;
while (--n >= 0) {
t = a;
a = b;
b += t;
}
return a;
}
```

View File

@@ -0,0 +1,121 @@
---
id: 5992e222d397f00d21122931
title: Слово Фібоначчі
challengeType: 5
forumTopicId: 302269
dashedName: fibonacci-word
---
# --description--
Слово Фібоначчі можна створити аналогічно послідовності Фібоначчі [як описано тут](https://hal.archives-ouvertes.fr/docs/00/36/79/72/PDF/The_Fibonacci_word_fractal.pdf):
<pre>Визначте F_Слово<sub>1</sub> як <strong>1</strong>
Визначте F_Слово<sub>2</sub> як <strong>0</strong>
Форма F_Слова<sub>3</sub> як F_Слова<sub>2</sub> об'єднана з F_Словом<sub>1</sub> тобто: <strong>01</strong>
Форма F_Слова<sub>n</sub> as F_Слово<sub>n-1</sub> об'єднана з F_Словом<sub>n-2</sub>
</pre>
# --instructions--
Напишіть функцію для повернення слів Фібоначчі до `n`. `n` буде надано як параметр функції. Функція має повернути масив об'єктів. Об’єкти мають мати такий вигляд: `{ N: 1, Length: 1, Entropy: 0, Word: '1' }`.
# --hints--
`fibWord` має бути функцією.
```js
assert(typeof fibWord === 'function');
```
`fibWord(5)` має повернути масив.
```js
assert(Array.isArray(fibWord(5)));
```
`fibWord(5)` має повернути `[{ N:1, Length:1, Entropy:0, Word:"1" },{ N:2, Length:1, Entropy:0, Word:"0" },{ N:3, Length:2, Entropy:1, Word:"01" },{ N:4, Length:3, Entropy:0.9182958340544896, Word:"010" },{ N:5, Length:5, Entropy:0.9709505944546688, Word:"01001" }]`.
```js
assert.deepEqual(fibWord(5), ans);
```
# --seed--
## --after-user-code--
```js
let ans=[ { N: 1, Length: 1, Entropy: 0, Word: '1' },
{ N: 2, Length: 1, Entropy: 0, Word: '0' },
{ N: 3, Length: 2, Entropy: 1, Word: '01' },
{ N: 4, Length: 3, Entropy: 0.9182958340544896, Word: '010' },
{ N: 5, Length: 5, Entropy: 0.9709505944546688, Word: '01001' }];
```
## --seed-contents--
```js
function fibWord(n) {
}
```
# --solutions--
```js
function fibWord(n) {
function entropy(s) {
//create an object containing each individual char
//and the amount of iterations per char
function prob(s) {
var h = Object.create(null);
s.split('').forEach(function(c) {
h[c] && h[c]++ || (h[c] = 1);
});
return h;
}
s = s.toString(); //just in case
var e = 0, l = s.length, h = prob(s);
for (var i in h ) {
var p = h[i]/l;
e -= p * Math.log(p) / Math.log(2);
}
return e;
}
var wOne = "1", wTwo = "0", wNth = [wOne, wTwo], w = "", o = [];
for (var i = 0; i < n; i++) {
if (i === 0 || i === 1) {
w = wNth[i];
} else {
w = wNth[i - 1] + wNth[i - 2];
wNth.push(w);
}
var l = w.length;
var e = entropy(w);
if (l <= 21) {
o.push({
N: i + 1,
Length: l,
Entropy: e,
Word: w
});
} else {
o.push({
N: i + 1,
Length: l,
Entropy: e,
Word: "..."
});
}
}
return o;
}
```

View File

@@ -0,0 +1,92 @@
---
id: 5e9ddb06ec35240f39657419
title: FizzBuzz
challengeType: 5
forumTopicId: 385370
dashedName: fizzbuzz
---
# --description--
Напишіть програму, яка генерує масив цілих чисел від 1 до 100 (включно). Але:
<ul>
<li>для кратних числа 3 додайте <code>"Fizz"</code> до масиву замість числа</li>
<li>для кратних числа 5 додайте <code>"Buzz"</code> до масиву замість числа</li>
<li>для кратних чисел 3 і 5 додайте <code>"FizzBuzz"</code> до масиву замість числа</li>
</ul>
# --instructions--
Ваша програма має повернути масив, що містить результати на основі вищезазначених правил.
# --hints--
`fizzBuzz` має бути функцією.
```js
assert(typeof fizzBuzz == 'function');
```
`fizzBuzz()` має повернути масив.
```js
assert(Array.isArray(fizzBuzz()) == true);
```
Числа, які діляться лише на 3, мають повернути `"Fizz"`.
```js
assert.equal(fizzBuzz()[2], 'Fizz');
```
Числа, які діляться лише на 5, мають повернути `"Buzz"`.
```js
assert.equal(fizzBuzz()[99], 'Buzz');
```
Числа, які діляться на 3 і 5, мають повернути `"FizzBuzz"`.
```js
assert.equal(fizzBuzz()[89], 'FizzBuzz');
```
Числа, які не діляться ні на 3, ні на 5, мають повернути саме число.
```js
assert.equal(fizzBuzz()[12], 13);
```
# --seed--
## --seed-contents--
```js
function fizzBuzz() {
}
```
# --solutions--
```js
function fizzBuzz() {
let res=[];
for (let i =1; i < 101; i++) {
if (i % 3 === 0 && i % 5 === 0) {
res.push("FizzBuzz");
}
else if (i % 3 === 0) {
res.push("Fizz");
}
else if (i % 5 === 0) {
res.push("Buzz");
}
else {
res.push(i);
}
}
return res;
}
```

View File

@@ -0,0 +1,139 @@
---
id: 5a7dad05be01840e1778a0d1
title: Мова програмування Fractran
challengeType: 5
forumTopicId: 302270
dashedName: fractran
---
# --description--
[FRACTRAN](https://en.wikipedia.org/wiki/FRACTRAN "wp: FRACTRAN")-це повна езотерична мова програмування Тюрінга, винайдена математиком [Джоном Хортоном Конвеєм](https://en.wikipedia.org/wiki/John Horton Conway "wp: John Horton Conway").
Програма FRACTRAN є впорядкованим списком додатних дробів $P = (f_1, f_2, \\ldots, f_m)$, разом з початковим введенням додатного цілого числа $n$.
Програма запускається шляхом оновлення цілого числа $n$ наступним чином:
<ul>
<li>для першого дробу, $f_i$в списку, для якого $nf_i$ є цілим числом, замінить $n$ на $nf_i$;</li>
<li>повторіть це правило допоки жоден дріб у списку не виробляє ціле число, коли помножений на $n$, потім зупиніть.</li>
</ul>
Конвей дав програму для простих чисел в FRACTRAN:
$\\dfrac{17}{91}$, $\\dfrac{78}{85}$, $\\dfrac{19}{51}$, $\\dfrac{23}{38}$, $\\dfrac{29}{33}$, $\\dfrac{77}{29}$, $\\dfrac{95}{23}$, $\\dfrac{77}{19}$, $\\dfrac{1}{17}$, $\\dfrac{11}{13}$, $\\dfrac{13}{11}$, $\\dfrac{15}{14}$, $\\dfrac{15}{2}$, $\\dfrac{55}{1}$
Починаючи з $n=2$, ця програма FRACTRAN змінить $n$ на 15=2\\times (\\frac{15}{2})$, потім $825=15\\t (\\frac{55}{1}$, генеруючи наступну послідовність цілих чисел:
$2$, $15$, $825$, $725$, $1925$, $2275$, $425$, $390$, $330$, $290$, $770$, $\\ldots$
Після 2, ця послідовність містить наступні степені 2:
$2^2=4$, $2^3=8$, $2^5=32$, $2^7=128$, $2^{11}=2048$, $2^{13}=8192$, $2^{17}=131072$, $2^{19}=524288$, $\\ldots$
які є простими степенями від 2.
# --instructions--
Напишіть функцію, яка приймає програму fractran як рядковий параметр і повертає перші 10 номерів програми як масив. Якщо результат не містить 10 чисел, поверніть числа як є.
# --hints--
`fractran` має бути функцією.
```js
assert(typeof fractran == 'function');
```
`fractran("3/2, 1/3")` має повернути масив.
```js
assert(Array.isArray(fractran('3/2, 1/3')));
```
`fractran("3/2, 1/3")` має повернути `[ 2, 3, 1 ]`.
```js
assert.deepEqual(fractran('3/2, 1/3'), [2, 3, 1]);
```
`fractran("3/2, 5/3, 1/5")` має повернути `[ 2, 3, 5, 1 ]`.
```js
assert.deepEqual(fractran('3/2, 5/3, 1/5'), [2, 3, 5, 1]);
```
`fractran("3/2, 6/3")` має повернути `[ 2, 3, 6, 9, 18, 27, 54, 81, 162, 243 ]`.
```js
assert.deepEqual(fractran('3/2, 6/3'), [2, 3, 6, 9, 18, 27, 54, 81, 162, 243]);
```
`fractran("2/7, 7/2")` має повернути `[ 2, 7, 2, 7, 2, 7, 2, 7, 2, 7 ]`.
```js
assert.deepEqual(fractran('2/7, 7/2'), [2, 7, 2, 7, 2, 7, 2, 7, 2, 7]);
```
`fractran("17/91, 78/85, 19/51, 23/38, 29/33, 77/29, 95/23, 77/19, 1/17, 11/13, 13/11, 15/14, 15/2, 55/1")` має повернути `[ 2, 15, 825, 725, 1925, 2275, 425, 390, 330, 290 ]`.
```js
assert.deepEqual(
fractran(
'17/91, 78/85, 19/51, 23/38, 29/33, 77/29, 95/23, 77/19, 1/17, 11/13, 13/11, 15/14, 15/2, 55/1'
),
[2, 15, 825, 725, 1925, 2275, 425, 390, 330, 290]
);
```
# --seed--
## --seed-contents--
```js
function fractran(progStr) {
}
```
# --solutions--
```js
function fractran(progStr){
var num = new Array();
var den = new Array();
var val ;
var out="";
function compile(prog){
var regex = /\s*(\d*)\s*\/\s*(\d*)\s*(.*)/m;
while(regex.test(prog)){
num.push(regex.exec(prog)[1]);
den.push(regex.exec(prog)[2]);
prog = regex.exec(prog)[3];
}
}
function step(val){
var i=0;
while(i<den.length && val%den[i] != 0) i++;
return num[i]*val/den[i];
}
var seq=[]
function exec(val){
var i = 0;
while(val && i<limit){
seq.push(val)
val = step(val);
i ++;
}
}
// Main
compile(progStr);
var limit = 10;
exec(2);
return seq;
}
```

View File

@@ -0,0 +1,104 @@
---
id: 5a23c84252665b21eecc7e76
title: Гамма-функція
challengeType: 5
forumTopicId: 302271
dashedName: gamma-function
---
# --description--
Реалізуйте один (або більше) алгоритм для обчислення [гамма-функції](https://en.wikipedia.org/wiki/Gamma function) ($\\Gamma$) (тільки в реальному полі).
Гамма-функція може бути визначена як:
<div style='padding-left: 4em;'><big><big>$\Gamma(x) = \displaystyle\int_0^\infty t^{x-1}e^{-t} dt$</big></big></div>
# --hints--
`gamma` має бути функцією.
```js
assert(typeof gamma == 'function');
```
`gamma(.1)` має повернути число.
```js
assert(typeof gamma(0.1) == 'number');
```
`gamma(.1)` має повернути `9.513507698668736`.
```js
assert.equal(round(gamma(0.1)), round(9.513507698668736));
```
`gamma(.2)` має повернути `4.590843711998803`.
```js
assert.equal(round(gamma(0.2)), round(4.590843711998803));
```
`gamma(.3)` має повернути `2.9915689876875904`.
```js
assert.equal(round(gamma(0.3)), round(2.9915689876875904));
```
`gamma(.4)` має повернути `2.218159543757687`.
```js
assert.equal(round(gamma(0.4)), round(2.218159543757687));
```
`gamma(.5)` має повернути `1.7724538509055159`.
```js
assert.equal(round(gamma(0.5)), round(1.7724538509055159));
```
# --seed--
## --after-user-code--
```js
function round(x) {
return Number(x).toPrecision(13);
}
```
## --seed-contents--
```js
function gamma(x) {
}
```
# --solutions--
```js
function gamma(x) {
var p = [0.99999999999980993, 676.5203681218851, -1259.1392167224028,
771.32342877765313, -176.61502916214059, 12.507343278686905,
-0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7
];
var g = 7;
if (x < 0.5) {
return Math.PI / (Math.sin(Math.PI * x) * gamma(1 - x));
}
x -= 1;
var a = p[0];
var t = x + g + 0.5;
for (var i = 1; i < p.length; i++) {
a += p[i] / (x + i);
}
var result=Math.sqrt(2 * Math.PI) * Math.pow(t, x + 0.5) * Math.exp(-t) * a;
return result;
}
```

View File

@@ -0,0 +1,230 @@
---
id: 5a23c84252665b21eecc7e77
title: Метод Гауса
challengeType: 5
forumTopicId: 302272
dashedName: gaussian-elimination
---
# --description--
Напишіть функцію для вирішення \\(Ax = b\\), використовуючи матод Гауса, а тоді зворотну підстановку.
\\(A\\) є матрицею\\(n \\times n\\). Крім того, \\(x\\) та \\(b\\) є \\(n\\) за 1 вектором.
Для більшої точності використовуйте вибір ведучого елемента і масштабування.
# --hints--
`gaussianElimination` має бути функцією.
```js
assert(typeof gaussianElimination == 'function');
```
`gaussianElimination([[1,1],[1,-1]], [5,1])` має повернути масив.
```js
assert(
Array.isArray(
gaussianElimination(
[
[1, 1],
[1, -1]
],
[5, 1]
)
)
);
```
`gaussianElimination([[1,1],[1,-1]], [5,1])` має повернути `[ 3, 2 ]`.
```js
assert.deepEqual(
gaussianElimination(
[
[1, 1],
[1, -1]
],
[5, 1]
),
[3, 2]
);
```
`gaussianElimination([[2,3],[2,1]] , [8,4])` має повернути `[ 1, 2 ]`.
```js
assert.deepEqual(
gaussianElimination(
[
[2, 3],
[2, 1]
],
[8, 4]
),
[1, 2]
);
```
`gaussianElimination([[1,3],[5,-2]], [14,19])` має повернути `[ 5, 3 ]`.
```js
assert.deepEqual(
gaussianElimination(
[
[1, 3],
[5, -2]
],
[14, 19]
),
[5, 3]
);
```
`gaussianElimination([[1,1],[5,-1]] , [10,14])` має повернути `[ 4, 6 ]`.
```js
assert.deepEqual(
gaussianElimination(
[
[1, 1],
[5, -1]
],
[10, 14]
),
[4, 6]
);
```
`gaussianElimination([[1,2,3],[4,5,6],[7,8,8]] , [6,15,23])` має повернути `[ 1, 1, 1 ]`.
```js
assert.deepEqual(
gaussianElimination(
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 8]
],
[6, 15, 23]
),
[1, 1, 1]
);
```
# --seed--
## --seed-contents--
```js
function gaussianElimination(A,b) {
}
```
# --solutions--
```js
function gaussianElimination(A, b) {
// Lower Upper Decomposition
function ludcmp(A) {
// A is a matrix that we want to decompose into Lower and Upper matrices.
var d = true
var n = A.length
var idx = new Array(n) // Output vector with row permutations from partial pivoting
var vv = new Array(n) // Scaling information
for (var i=0; i<n; i++) {
var max = 0
for (var j=0; j<n; j++) {
var temp = Math.abs(A[i][j])
if (temp > max) max = temp
}
if (max == 0) return // Singular Matrix!
vv[i] = 1 / max // Scaling
}
var Acpy = new Array(n)
for (var i=0; i<n; i++) {
var Ai = A[i]
let Acpyi = new Array(Ai.length)
for (j=0; j<Ai.length; j+=1) Acpyi[j] = Ai[j]
Acpy[i] = Acpyi
}
A = Acpy
var tiny = 1e-20 // in case pivot element is zero
for (var i=0; ; i++) {
for (var j=0; j<i; j++) {
var sum = A[j][i]
for (var k=0; k<j; k++) sum -= A[j][k] * A[k][i];
A[j][i] = sum
}
var jmax = 0
var max = 0;
for (var j=i; j<n; j++) {
var sum = A[j][i]
for (var k=0; k<i; k++) sum -= A[j][k] * A[k][i];
A[j][i] = sum
var temp = vv[j] * Math.abs(sum)
if (temp >= max) {
max = temp
jmax = j
}
}
if (i <= jmax) {
for (var j=0; j<n; j++) {
var temp = A[jmax][j]
A[jmax][j] = A[i][j]
A[i][j] = temp
}
d = !d;
vv[jmax] = vv[i]
}
idx[i] = jmax;
if (i == n-1) break;
var temp = A[i][i]
if (temp == 0) A[i][i] = temp = tiny
temp = 1 / temp
for (var j=i+1; j<n; j++) A[j][i] *= temp
}
return {A:A, idx:idx, d:d}
}
// Lower Upper Back Substitution
function lubksb(lu, b) {
// solves the set of n linear equations A*x = b.
// lu is the object containing A, idx and d as determined by the routine ludcmp.
var A = lu.A
var idx = lu.idx
var n = idx.length
var bcpy = new Array(n)
for (var i=0; i<b.length; i+=1) bcpy[i] = b[i]
b = bcpy
for (var ii=-1, i=0; i<n; i++) {
var ix = idx[i]
var sum = b[ix]
b[ix] = b[i]
if (ii > -1)
for (var j=ii; j<i; j++) sum -= A[i][j] * b[j]
else if (sum)
ii = i
b[i] = sum
}
for (var i=n-1; i>=0; i--) {
var sum = b[i]
for (var j=i+1; j<n; j++) sum -= A[i][j] * b[j]
b[i] = sum / A[i][i]
}
return b // solution vector x
}
var lu = ludcmp(A)
if (lu === undefined) return // Singular Matrix!
return lubksb(lu, b)
}
```

View File

@@ -0,0 +1,175 @@
---
id: 5a23c84252665b21eecc7e78
title: Спільний FizzBuzz
challengeType: 5
forumTopicId: 302273
dashedName: general-fizzbuzz
---
# --description--
Напишіть спрощену версію [FizzBuzz](https://rosettacode.org/wiki/FizzBuzz) яка спрацює для буль якого переліку факторів, разом з їх словами.
В основному, це реалізація "fizzbuzz", де надаються правила гри користувачу. Створіть функцію для реалізації цього. Функція повинна приймати два параметри.
Перший - масив із правилами FizzBuzz. До прикладу: `[ [3, "Fizz"] , [5, "Buzz"] ]`.
Це вказує на те, що потрібно вивести `Fizz`, якщо число кратне 3, і `Buzz` якщо воно кратне 5. Якщо у двох випадках число кратне, тоді рядки мають бути об'єднані в порядку вказаному в масиві. У цьому випадку `FizzBuzz` виконується якщо число ділиться на 3 і 5.
Другий параметр - це число, для якого функція повинна повернути рядок як зазначається вище.
# --hints--
`genFizzBuzz` має бути функцією.
```js
assert(typeof genFizzBuzz == 'function');
```
`genFizzBuzz([[3, "Fizz"],[5, "Buzz"]], 6)` має повернути рядок.
```js
assert(
typeof genFizzBuzz(
[
[3, 'Fizz'],
[5, 'Buzz']
],
6
) == 'string'
);
```
`genFizzBuzz([[3, "Fizz"],[5, "Buzz"]], 6)` має повернути `"Fizz"`.
```js
assert.equal(
genFizzBuzz(
[
[3, 'Fizz'],
[5, 'Buzz']
],
6
),
'Fizz'
);
```
`genFizzBuzz([[3, "Fizz"],[5, "Buzz"]], 10)` має повернути `"Buzz"`.
```js
assert.equal(
genFizzBuzz(
[
[3, 'Fizz'],
[5, 'Buzz']
],
10
),
'Buzz'
);
```
`genFizzBuzz([[3, "Buzz"],[5, "Fizz"]], 12)` має повернути `"Buzz"`.
```js
assert.equal(
genFizzBuzz(
[
[3, 'Buzz'],
[5, 'Fizz']
],
12
),
'Buzz'
);
```
`genFizzBuzz([[3, "Buzz"],[5, "Fizz"]], 13)` має повернути `"13"`.
```js
assert.equal(
genFizzBuzz(
[
[3, 'Buzz'],
[5, 'Fizz']
],
13
),
'13'
);
```
`genFizzBuzz([[3, "Buzz"],[5, "Fizz"]], 15)` має повернути `"BuzzFizz"`.
```js
assert.equal(
genFizzBuzz(
[
[3, 'Buzz'],
[5, 'Fizz']
],
15
),
'BuzzFizz'
);
```
`genFizzBuzz([[3, "Fizz"],[5, "Buzz"]], 15)` має повернути `"FizzBuzz"`.
```js
assert.equal(
genFizzBuzz(
[
[3, 'Fizz'],
[5, 'Buzz']
],
15
),
'FizzBuzz'
);
```
`genFizzBuzz([[3, "Fizz"],[5, "Buzz"],[7, "Baxx"]], 105)` має повернути `"FizzBuzzBaxx"`.
```js
assert.equal(
genFizzBuzz(
[
[3, 'Fizz'],
[5, 'Buzz'],
[7, 'Baxx']
],
105
),
'FizzBuzzBaxx'
);
```
# --seed--
## --seed-contents--
```js
function genFizzBuzz(rules, num) {
}
```
# --solutions--
```js
function genFizzBuzz(rules, num) {
let res='';
rules.forEach(function (e) {
if(num % e[0] == 0)
res+=e[1];
})
if(res==''){
res=num.toString();
}
return res;
}
```

View File

@@ -0,0 +1,99 @@
---
id: 5a23c84252665b21eecc7e7a
title: Згенерувати нижній регістр ASCII абетки
challengeType: 5
forumTopicId: 302274
dashedName: generate-lower-case-ascii-alphabet
---
# --description--
Напишіть функцію, щоб згенерувати масив символів нижнього регістру ASCII для заданого діапазону. До прикладу, при заданому діапазоні `['a', 'd']`, функція має повернути `['a', 'b', 'c', 'd']`.
# --hints--
`lascii` має бути функцією.
```js
assert(typeof lascii == 'function');
```
`lascii("a","d")` має повернути масив.
```js
assert(Array.isArray(lascii('a', 'd')));
```
`lascii('a','d')` має повернути `[ 'a', 'b', 'c', 'd' ]`.
```js
assert.deepEqual(lascii('a', 'd'), results[0]);
```
`lascii('c','i')` має повернути `[ 'c', 'd', 'e', 'f', 'g', 'h', 'i' ]`.
```js
assert.deepEqual(lascii('c', 'i'), results[1]);
```
`lascii('m','q')` має повернути `[ 'm', 'n', 'o', 'p', 'q' ]`.
```js
assert.deepEqual(lascii('m', 'q'), results[2]);
```
`lascii('k','n')` має повернути `[ 'k', 'l', 'm', 'n' ]`.
```js
assert.deepEqual(lascii('k', 'n'), results[3]);
```
`lascii('t','z')` має повернути `[ 't', 'u', 'v', 'w', 'x', 'y', 'z' ]`.
```js
assert.deepEqual(lascii('t', 'z'), results[4]);
```
# --seed--
## --after-user-code--
```js
let results=[
[ 'a', 'b', 'c', 'd' ],
[ 'c', 'd', 'e', 'f', 'g', 'h', 'i' ],
[ 'm', 'n', 'o', 'p', 'q' ],
[ 'k', 'l', 'm', 'n' ],
[ 't', 'u', 'v', 'w', 'x', 'y', 'z' ]
]
```
## --seed-contents--
```js
function lascii(cFrom, cTo) {
}
```
# --solutions--
```js
function lascii(cFrom, cTo) {
function cRange(cFrom, cTo) {
var iStart = cFrom.charCodeAt(0);
return Array.apply(
null, Array(cTo.charCodeAt(0) - iStart + 1)
).map(function (_, i) {
return String.fromCharCode(iStart + i);
});
}
return cRange(cFrom, cTo);
}
```

View File

@@ -0,0 +1,117 @@
---
id: 5a23c84252665b21eecc7e7b
title: Генератор/Експонента
challengeType: 5
forumTopicId: 302275
dashedName: generatorexponential
---
# --description--
Генератор - це виконуваний об'єкт (наприклад, функція або процедура), що містить код, що видає по одному послідовність значень, тому кожен раз, коли ви звертаєтеся до генератора, видається наступне значення в послідовності.
Генератори часто будуються поверх співпрограм або об'єктів, щоб внутрішній стан об'єкта оброблявся "природним чином".
Генератори часто використовуються в ситуаціях, коли послідовність потенційно нескінченна, і де можливо побудувати наступне значення послідовності з лише мінімальним станом.
# --instructions--
Запишіть функцію, яка використовує генератори для створення квадратів і кубів. Створіть новий генератор, який відфільтрує всі куби з генератора квадратів.
Функція має повернути \\( n^{th} \\) значення відфільтрованого генератора.
Наприклад, для \\(n=7\\) має повернути 81, оскільки послідовність буде 4, 16, 25, 36, 49, 81. Тут число 64 відфільтровано, оскільки це куб.
# --hints--
`exponentialGenerator` має бути функцією.
```js
assert(typeof exponentialGenerator == 'function');
```
`exponentialGenerator()` має повернути число.
```js
assert(typeof exponentialGenerator(10) == 'number');
```
`exponentialGenerator(10)` має повернути `144`.
```js
assert.equal(exponentialGenerator(10), 144);
```
`exponentialGenerator(12)` має повернути `196`.
```js
assert.equal(exponentialGenerator(12), 196);
```
`exponentialGenerator(14)` має повернути `256`.
```js
assert.equal(exponentialGenerator(14), 256);
```
`exponentialGenerator(20)` має повернути `484`.
```js
assert.equal(exponentialGenerator(20), 484);
```
`exponentialGenerator(25)` має повернути `784`.
```js
assert.equal(exponentialGenerator(25), 784);
```
# --seed--
## --seed-contents--
```js
function exponentialGenerator(n) {
}
```
# --solutions--
```js
function exponentialGenerator(n){
function* PowersGenerator(m) {
var n=0;
while(1) {
yield Math.pow(n, m);
n += 1;
}
}
function* FilteredGenerator(g, f){
var value = g.next().value;
var filter = f.next().value;
while(1) {
if( value < filter ) {
yield value;
value = g.next().value;
} else if ( value > filter ) {
filter = f.next().value;
} else {
value = g.next().value;
filter = f.next().value;
}
}
}
var squares = PowersGenerator(2);
var cubes = PowersGenerator(3);
var filtered = FilteredGenerator(squares, cubes);
var curr=0;
for(var i=0;i<n;i++) curr=filtered.next();
return curr.value;
}
```

View File

@@ -0,0 +1,122 @@
---
id: 5a23c84252665b21eecc7e80
title: Код Грея
challengeType: 5
forumTopicId: 302276
dashedName: gray-code
---
# --description--
[ код Грея ](https://en.wikipedia.org/wiki/Gray code) - це форма бінарного кодування, де переходи між послідовними числами відрізняються лише на один біт.
Це корисне кодування для зменшення ризиків настання небезпеки для апаратних даних зі значеннями, що швидко змінюються та/або підключаються до повільнішого апаратного забезпечення як вхідних даних.
Це також корисно для генерації даних для [Karnaugh maps](https://en.wikipedia.org/wiki/Karnaugh map) у порядку зліва направо або зверху вниз.
# --instructions--
Створіть функцію для кодування номера та декодування номера з коду Грея. Функція повинна мати 2 параметри.
Перший - це логічний тип даних. Функція має кодувати true і декодувати false. Другим параметром буде число, яке потрібно закодувати/декодувати.
Поккажіть нормальні бінарні значення, значення коду Грея, і декодування даних коду Грея для всіх 5-бінарних чисел (0-31 включно, провідні нулі не є необхідними).
Існує багато можливих кодів Грея. Наступні кодування називаються "двійковим відображувальним кодом Грея."
Кодування (MSB є бітом 0, b є бінарним, g - кодом Грея):
<pre>якщо b [i-1] = 1
g [i] = не b [i]
інакше
g [i] = b [i]
</pre>
Або:
<pre>g = b xor (b логічно зміщено праворуч 1 раз)
</pre>
Декодування (MSB є бітом 0, b є бінарним, g - кодом Грея):
<pre>b[0] = g[0]<br>
для інших бітів:
b[i] = g[i] xor b[i-1]
</pre>
# --hints--
`gray` має бути функцією.
```js
assert(typeof gray == 'function');
```
`gray(true,177)` має повернути число.
```js
assert(typeof gray(true, 177) == 'number');
```
`gray(true,177)` має повернути `233`.
```js
assert.equal(gray(true, 177), 233);
```
`gray(true,425)` має повернути `381`.
```js
assert.equal(gray(true, 425), 381);
```
`gray(true,870)` має повернути `725`.
```js
assert.equal(gray(true, 870), 725);
```
`gray(false,233)` має повернути `177`.
```js
assert.equal(gray(false, 233), 177);
```
`gray(false,381)` має повернути `425`.
```js
assert.equal(gray(false, 381), 425);
```
`gray(false,725)`має повернути `870`.
```js
assert.equal(gray(false, 725), 870);
```
# --seed--
## --seed-contents--
```js
function gray(enc, number) {
}
```
# --solutions--
```js
function gray(enc, number){
if(enc){
return number ^ (number >> 1);
}else{
let n = number;
while (number >>= 1) {
n ^= number;
}
return n;
}
}
```

View File

@@ -0,0 +1,79 @@
---
id: 5a23c84252665b21eecc7e82
title: Найбільший спільний дільник
challengeType: 5
forumTopicId: 302277
dashedName: greatest-common-divisor
---
# --description--
Напишіть функцію, яка повертає найбільший спільний дільник двох цілих чисел.
# --hints--
`gcd` має бути функцією.
```js
assert(typeof gcd == 'function');
```
`gcd(24,36)` має повернути число.
```js
assert(typeof gcd(24, 36) == 'number');
```
`gcd(24,36)` має повернути `12`.
```js
assert.equal(gcd(24, 36), 12);
```
`gcd(30,48)` має повернути `6`.
```js
assert.equal(gcd(30, 48), 6);
```
`gcd(10,15)` має повернути `5`.
```js
assert.equal(gcd(10, 15), 5);
```
`gcd(100,25)` має повернути `25`.
```js
assert.equal(gcd(100, 25), 25);
```
`gcd(13,250)` має повернути `1`.
```js
assert.equal(gcd(13, 250), 1);
```
`gcd(1300,250)` має повернути `50`.
```js
assert.equal(gcd(1300, 250), 50);
```
# --seed--
## --seed-contents--
```js
function gcd(a, b) {
}
```
# --solutions--
```js
function gcd(a, b) {
return b==0 ? Math.abs(a):gcd(b, a % b);
}
```

View File

@@ -0,0 +1,113 @@
---
id: 5a23c84252665b21eecc7e84
title: Найбільша подальша сума
challengeType: 5
forumTopicId: 302278
dashedName: greatest-subsequential-sum
---
# --description--
Дано послідовність цілих чисел, знайдіть неперервну підпослідовність, яка збільшує суму елементів, тобто елементи жодної іншої підпослідовності не додаються до значення більше за це.
Порожня підпослідовність вважається сумою \\( 0 \\); таким чином, якщо всі елементи від'ємні, то результат повинен бути порожньою послідовністю.
# --hints--
`maximumSubsequence` має бути функцією.
```js
assert(typeof maximumSubsequence == 'function');
```
`maximumSubsequence([ 1, 2, -1, 3, 10, -10 ])` має повернути масив.
```js
assert(Array.isArray(maximumSubsequence([1, 2, -1, 3, 10, -10])));
```
`maximumSubsequence([ 1, 2, -1, 3, 10, -10 ])` має повернути `[ 1, 2, -1, 3, 10 ]`.
```js
assert.deepEqual(maximumSubsequence([1, 2, -1, 3, 10, -10]), [1, 2, -1, 3, 10]);
```
`maximumSubsequence([ 0, 8, 10, -2, -4, -1, -5, -3 ])` має повернути `[ 0, 8, 10 ]`.
```js
assert.deepEqual(maximumSubsequence([0, 8, 10, -2, -4, -1, -5, -3]), [
0,
8,
10
]);
```
`maximumSubsequence([ 9, 9, -10, 1 ])` має повернути `[ 9, 9 ]`.
```js
assert.deepEqual(maximumSubsequence([9, 9, -10, 1]), [9, 9]);
```
`maximumSubsequence([ 7, 1, -5, -3, -8, 1 ])` має повернути `[ 7, 1 ]`.
```js
assert.deepEqual(maximumSubsequence([7, 1, -5, -3, -8, 1]), [7, 1]);
```
`maximumSubsequence([ -3, 6, -1, 4, -4, -6 ])` має повернути `[ 6, -1, 4 ]`.
```js
assert.deepEqual(maximumSubsequence([-3, 6, -1, 4, -4, -6]), [6, -1, 4]);
```
`maximumSubsequence([ -1, -2, 3, 5, 6, -2, -1, 4, -4, 2, -1 ])` має повернути `[ 3, 5, 6, -2, -1, 4 ]`.
```js
assert.deepEqual(maximumSubsequence([-1, -2, 3, 5, 6, -2, -1, 4, -4, 2, -1]), [
3,
5,
6,
-2,
-1,
4
]);
```
# --seed--
## --seed-contents--
```js
function maximumSubsequence(population) {
}
```
# --solutions--
```js
function maximumSubsequence(population) {
function sumValues(arr) {
var result = 0;
for (var i = 0, len = arr.length; i < len; i++) {
result += arr[i];
}
return result;
}
var greatest;
var maxValue = 0;
for (var i = 0, len = population.length; i < len; i++) {
for (var j = i; j <= len; j++) {
var subsequence = population.slice(i, j);
var value = sumValues(subsequence);
if (value > maxValue) {
maxValue = value;
greatest = subsequence;
};
}
}
return greatest;
}
```

View File

@@ -0,0 +1,98 @@
---
id: 595608ff8bcd7a50bd490181
title: Сіракузька послідовність
challengeType: 5
forumTopicId: 302279
dashedName: hailstone-sequence
---
# --description--
Сіракузьку послідовність чисел можна згенерувати з будь-якого натурального числа `n`:
- Якщо `n` дорівнює `1`, то послідовність закінчується
- Якщо `n` дорівнює `even`, то наступне `n` послідовності `= n/2`
- Якщо `n` дорівнює `odd`, то наступне `n` послідовності `= (3 * n) + 1`
Суть гіпотеза Коллатца (Недоведена): яке б початкове число ми б не взяли, Сіракузька послідовність завжди закінчується.
Сіракузька послідовність, також відома як числа-градини (бо графіки послідовностей схожі на траєкторію руху градин в атмосфері), або як послідовність Коллатца.
# --instructions--
1. Створіть процедуру для генерації Сіруказької послідовності для числа
2. Ваша функція має повертати масив з числом менше `limit`, яке має найдовшу Сіруказьку послідовність і довжину цієї послідовності. (Але не показуйте саму послідовність!)
# --hints--
`hailstoneSequence` має бути функцією.
```js
assert(typeof hailstoneSequence === 'function');
```
`hailstoneSequence(30)` має повертати масив.
```js
assert(Array.isArray(hailstoneSequence(30)));
```
`hailstoneSequence(30)` має повертати `[27, 112]`.
```js
assert.deepEqual(hailstoneSequence(30), [27, 112]);
```
`hailstoneSequence(50000)` має повертати `[35655, 324]`.
```js
assert.deepEqual(hailstoneSequence(50000), [35655, 324]);
```
`hailstoneSequence(100000)` має повертати `[77031, 351]`.
```js
assert.deepEqual(hailstoneSequence(100000), [77031, 351]);
```
# --seed--
## --seed-contents--
```js
function hailstoneSequence(limit) {
const res = [];
return res;
}
```
# --solutions--
```js
function hailstoneSequence (limit) {
function hailstone(n) {
const seq = [n];
while (n > 1) {
n = n % 2 ? 3 * n + 1 : n / 2;
seq.push(n);
}
return seq;
}
let n = 0;
let max = 0;
for (let i = limit; --i;) {
const seq = hailstone(i);
const sLen = seq.length;
if (sLen > max) {
n = i;
max = sLen;
}
}
return [n, max];
}
```

View File

@@ -0,0 +1,129 @@
---
id: 594810f028c0303b75339ad1
title: Щасливі числа
challengeType: 5
forumTopicId: 302280
dashedName: happy-numbers
---
# --description--
[ щасливе число ](https://en.wikipedia.org/wiki/Happy_number) визначається так:
Починаючи з будь-якого додатного цілого числа, замініть число на суму квадратів цифр і повторіть дію, доки число не буде дорівнювати `1` (де воно залишиться), або воно нескінченно буде повторюватися у циклі, який не включає `1`. Ті числа, для яких цей процес закінчується `1` є щасливими, а ті, для яких процес не закінчуються `1` є нещасливими.
# --instructions--
Реалізуйте функцію, що повертає правильне значення, у разі якщо число — щасливе, якщо воно є хибним, не робить цього.
# --hints--
`happy` має бути функцією.
```js
assert(typeof happy === 'function');
```
`happy(1)` має повернути логічний тип.
```js
assert(typeof happy(1) === 'boolean');
```
`happy(1)` має повернути `true`.
```js
assert(happy(1));
```
`happy(2)` має повернути `false`.
```js
assert(!happy(2));
```
`happy(7)` має повернути `true`.
```js
assert(happy(7));
```
`happy(10)` має повернути `true`.
```js
assert(happy(10));
```
`happy(13)` має повернути `true`.
```js
assert(happy(13));
```
`happy(19)` має повернути `true`.
```js
assert(happy(19));
```
`happy(23)` має повернути `true`.
```js
assert(happy(23));
```
`happy(28)` має повернути `true`.
```js
assert(happy(28));
```
`happy(31)` має повернути `true`.
```js
assert(happy(31));
```
`happy(32)` має повернути `true`.
```js
assert(happy(32));
```
`happy(33)` має повернути `false`.
```js
assert(!happy(33));
```
# --seed--
## --seed-contents--
```js
function happy(number) {
}
```
# --solutions--
```js
function happy (number) {
let m;
let digit;
const cycle = [];
while (number !== 1 && cycle[number] !== true) {
cycle[number] = true;
m = 0;
while (number > 0) {
digit = number % 10;
m += Math.pow(digit, 2);
number = (number - digit) / 10;
}
number = m;
}
return (number === 1);
}
```

View File

@@ -0,0 +1,87 @@
---
id: 595668ca4cfe1af2fb9818d4
title: Число Харшад або Нівена
challengeType: 5
forumTopicId: 302281
dashedName: harshad-or-niven-series
---
# --description--
Числа харшад або число Нівена — це додатні цілі числа ≥ 1, що діляться на суму своїх цифр-складників.
Наприклад, `42` — це число Харшад, оскільки `42` ділиться на `(4 + 2)` без залишку.
Припустимо, що серія визначається як числа в порядку збільшення.
# --instructions--
Реалізація функції полягає в створенні послідовних членів порядку Харшаду.
Використовуйте його, щоб повернути масив з десятьма членами послідовності, починаючи з числа першого Харшада, більше ніж `n`.
# --hints--
`isHarshadOrNiven` має бути функцією.
```js
assert(typeof isHarshadOrNiven === 'function');
```
`isHarshadOrNiven(10)` має повернути `[12, 18, 20, 21, 24, 27, 30, 36, 40, 42]`
```js
assert.deepEqual(isHarshadOrNiven(10), [12, 18, 20, 21, 24, 27, 30, 36, 40, 42]);
```
`isHarshadOrNiven(400)` має повернути `[402, 405, 407, 408, 410, 414, 420, 423, 432, 440]`
```js
assert.deepEqual(isHarshadOrNiven(400), [402, 405, 407, 408, 410, 414, 420, 423, 432, 440]);
```
`isHarshadOrNiven(1000)` має повернути `[1002, 1008, 1010, 1011, 1012, 1014, 1015, 1016, 1017, 1020]`
```js
assert.deepEqual(isHarshadOrNiven(1000), [1002, 1008, 1010, 1011, 1012, 1014, 1015, 1016, 1017, 1020]);
```
# --seed--
## --seed-contents--
```js
function isHarshadOrNiven(n) {
const res = [];
return res;
}
```
# --solutions--
```js
function isHarshadOrNiven(n) {
function isHarshad(num) {
let s = 0;
const nStr = num.toString();
for (let i = 0; i < nStr.length; ++i) {
s += parseInt(nStr.charAt(i), 10);
}
return n % s === 0;
}
const res = [];
let count = 0;
while (count < 10) {
n++;
if (isHarshad(n)) {
count++;
res.push(n);
}
}
return res;
}
```

View File

@@ -0,0 +1,105 @@
---
id: 595671d4d2cdc305f0d5b36f
title: Хеш із двох масивів
challengeType: 5
forumTopicId: 302283
dashedName: hash-from-two-arrays
---
# --description--
Використовуючи два масиви однакової довжини, створіть геш-об'єкт, в якому елементи з одного масиву (ключі) будуть пов'язані з елементами з іншого (значеннями).
**Пов’язане завдання:**
<ul>
<li><a href='https://rosettacode.org/wiki/Associative arrays/Creation' title='Асоціативні масиви/Створення' target='_blank'>Асоціативні масиви/Створення</a></li>
</ul>
# --hints--
`arrToObj` має бути функцією.
```js
assert(typeof arrToObj === 'function');
```
`arrToObj([1, 2, 3, 4, 5], ["a", "b", "c", "d", "e"])` має повернути `{ 1: "a", 2: "b", 3: "c", 4: "d", 5: "e" }`
```js
assert.deepEqual(arrToObj(...testCases[0]), res[0]);
```
`arrToObj([1, 2, 3, 4, 5], ["a", "b", "c", "d"])` має повернути `{ 1: "a", 2: "b", 3: "c", 4: "d", 5: undefined }`
```js
assert.deepEqual(arrToObj(...testCases[1]), res[1]);
```
`arrToObj([1, 2, 3], ["a", "b", "c", "d", "e"])` має повернути `{ 1: "a", 2: "b", 3: "c" }`
```js
assert.deepEqual(arrToObj(...testCases[2]), res[2]);
```
`arrToObj(["a", "b", "c", "d", "e"], [1, 2, 3, 4, 5])` має повернути `{ "a": 1, "b": 2, "c": 3 , "d": 4, "e": 5 }`
```js
assert.deepEqual(arrToObj(...testCases[3]), res[3]);
```
`arrToObj(["a", "b", "c", "d", "e"], [1, 2, 3, 4])` має повернути `{ "a": 1, "b": 2, "c": 3 , "d": 4, "e": undefined }`
```js
assert.deepEqual(arrToObj(...testCases[4]), res[4]);
```
`arrToObj(["a", "b", "c"], [1, 2, 3, 4, 5])` має повернути `{ "a": 1, "b": 2, "c": 3 }`
```js
assert.deepEqual(arrToObj(...testCases[5]), res[5]);
```
# --seed--
## --after-user-code--
```js
const testCases = [
[[1, 2, 3, 4, 5], ['a', 'b', 'c', 'd', 'e']],
[[1, 2, 3, 4, 5], ['a', 'b', 'c', 'd']],
[[1, 2, 3], ['a', 'b', 'c', 'd', 'e']],
[['a', 'b', 'c', 'd', 'e'], [1, 2, 3, 4, 5]],
[['a', 'b', 'c', 'd', 'e'], [1, 2, 3, 4]],
[['a', 'b', 'c'], [1, 2, 3, 4, 5]]
];
const res = [
{ 1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e' },
{ 1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: undefined },
{ 1: 'a', 2: 'b', 3: 'c' },
{ a: 1, b: 2, c: 3, d: 4, e: 5 },
{ a: 1, b: 2, c: 3, d: 4, e: undefined },
{ a: 1, b: 2, c: 3 }
];
```
## --seed-contents--
```js
function arrToObj (keys, vals) {
return true;
}
```
# --solutions--
```js
function arrToObj (keys, vals) {
return keys.reduce((map, key, index) => {
map[key] = vals[index];
return map;
}, {});
}
```

View File

@@ -0,0 +1,237 @@
---
id: 5956795bc9e2c415eb244de1
title: Хеш-приєднання
challengeType: 5
forumTopicId: 302284
dashedName: hash-join
---
# --description--
[ внутрішнє з'єднання ](https://www.freecodecamp.org/news/sql-join-types-inner-join-vs-outer-join-example/#how-to-use-an-inner-join-in-sql "news: SQL Join Types Inner Join VS Outer Join Example#How to Use an INNER JOIN in SQL") — це операція, яка об'єднує дві таблиці даних в одну таблицю на основі відповідності значень стовпців. Найпростіший спосіб виконати цю операцію: [приєднання вкладеного циклу](https://en.wikipedia.org/wiki/Nested loop join "wp: Nested loop join")алгоритм, а більш масштабованою альтернативою є[хеш-приєднання](https://en.wikipedia.org/wiki/hash join "wp: hash join")алгоритм.
Алгоритм "хеш-приєднання" складається з двох кроків:
<ol>
<li><strong>хеш фаза:</strong> Створіть <a href='https://en.wikipedia.org/wiki/Multimap' title='wp: Multimap' target='_blank'>,багатофункціональної карти</a> з однієї із двох таблиць, зіставляючи значення кожного стовпця до всіх рядків, що містять його.</li>
<ul>
<li>Багатофункціональна карта повинна підтримувати хеш пошук, який оцінює краще звичайного лінійного пошуку, оскільки це і є суть алгоритму.</li>
<li>В ідеалі, ми створюємо мультимедійне відображення для меншої таблиці, таким чином мінімізуючи час створення та розмір пам'яті.</li>
</ul>
<li><strong>Приєднатися до фази:</strong> Скануйте іншу таблицю, знайдіть відповідні рядки, дивлячись у багатофункціональну карту, створену раніше.</li>
</ol>
В псевдокоді алгоритм може бути виражений так:
<pre><strong>нехай</strong> <i>A</i> = перша початкова таблиця (в ідеалі — найбільша)
<strong>нехай</strong> <i>B</i> = друга початкова таблиця (в ідеалі — найменша)
<strong>нехай</strong> <i>j<sub>A</sub></i> = спільна колонка ID таблиці <i>A</i>
<strong>нехай</strong> <i>j<sub>B</sub></i> = спільна колонка ID таблиці <i>В</i>
<strong>нехай</strong> <i>M<sub>B</sub></i> = багатофункціональна карта для відображення від одиничних значень до кількох рядків таблиці <i>B</i> (починаючи з порожніх)
<strong>нехай</strong> <i>C</i> = вихідна таблиця (починаючи з порожніх)
<strong>для кожного</strong> ряду <i>b</i> таблиці <i>B</i>:
<strong>місце</strong> <i>b</i> у багатофункціональній карті <i>M<sub>B</sub></i> відповідно до <i>b(j<sub>B</sub>)</i>
<strong>для кожного</strong> ряду <i>a</i> у таблиці <i>A</i>:
<strong>для кожного</strong> ряду <i>b</i> у багатофункціональній карті <i>M<sub>B</sub></i> відповідно до <i>a(j<sub>A</sub>)</i>:
<strong>нехай</strong> <i>c</i> = ланцюжок рядків <i>a</i> і ряд <i>b</i>
<strong>місце</strong> ряд <i>c</i> у таблиці <i>C</i>
</pre>
# --instructions--
Реалізуйте алгоритм "хеш-приєднання" як функцію, та продемонструйте, що вона передає тестове значення, вказане нижче. Функція має приймати два масиви об'єктів і повертати масив комбінованих об’єктів.
**Початкова інформація**
<table>
<tr>
<td style="padding: 4px; margin: 5px;">
<table style="border:none; border-collapse:collapse;">
<tr>
<td style="border:none"><i>А =</i></td>
<td style="border:none">
<table>
<tr>
<th style="padding: 4px; margin: 5px;">Вік</th>
<th style="padding: 4px; margin: 5px;">Ім'я</th>
</tr>
<tr>
<td style="padding: 4px; margin: 5px;">27</td>
<td style="padding: 4px; margin: 5px;">Йона</td>
</tr>
<tr>
<td style="padding: 4px; margin: 5px;">18</td>
<td style="padding: 4px; margin: 5px;">Алан</td>
</tr>
<tr>
<td style="padding: 4px; margin: 5px;">28</td>
<td style="padding: 4px; margin: 5px;">Глорія</td>
</tr>
<tr>
<td style="padding: 4px; margin: 5px;">18</td>
<td style="padding: 4px; margin: 5px;">Попай</td>
</tr>
<tr>
<td style="padding: 4px; margin: 5px;">28</td>
<td style="padding: 4px; margin: 5px;">Алан</td>
</tr>
</table>
</td>
<td style="border:none; padding-left:1.5em;" rowspan="2"></td>
<td style="border:none"><i>B =</i></td>
<td style="border:none">
<table>
<tr>
<th style="padding: 4px; margin: 5px;">Персонаж</th>
<th style="padding: 4px; margin: 5px;">Ворог</th>
</tr>
<tr>
<td style="padding: 4px; margin: 5px;">Йона</td>
<td style="padding: 4px; margin: 5px;">Кити</td>
</tr>
<tr>
<td style="padding: 4px; margin: 5px;">Йона</td>
<td style="padding: 4px; margin: 5px;">Павуки</td>
</tr>
<tr>
<td style="padding: 4px; margin: 5px;">Алан</td>
<td style="padding: 4px; margin: 5px;">Привиди</td>
</tr>
<tr>
<td style="padding: 4px; margin: 5px;">Алан</td>
<td style="padding: 4px; margin: 5px;">Зомбі</td>
</tr>
<tr>
<td style="padding: 4px; margin: 5px;">Глорія</td>
<td style="padding: 4px; margin: 5px;">Баффі</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style="border:none">
<i>j<sub>A</sub> =</i>
</td>
<td style="border:none">
<i><code>Ім'я</code> (напр. колонка 1)</i>
</td>
<td style="border:none">
<i>j<sub>B</sub> =</i>
</td>
<td style="border:none">
<i><code>Персонаж</code> (напр. колонка 0)</i>
</td>
</tr>
</table>
</td>
</tr>
</table>
**Результат**
| A_вік | A_ім'я | B_персонаж | B_ворог |
| ----- | ------ | ---------- | ------- |
| 27 | Йона | Йона | Кити |
| 27 | Йона | Джон | Павуки |
| 18 | Алан | Алан | Привиди |
| 18 | Алан | Алан | Зомбі |
| 28 | Глорі | Глорі | Баффі |
| 28 | Алан | Алан | Привиди |
| 28 | Алан | Алан | Зомбі |
Порядок рядків у вихідній таблиці не є важливим.
# --hints--
`hashJoin` має бути функцією.
```js
assert(typeof hashJoin === 'function');
```
`hashJoin([{ age: 27, name: "Jonah" }, { age: 18, name: "Alan" }, { age: 28, name: "Glory" }, { age: 18, name: "Popeye" }, { age: 28, name: "Alan" }], [{ character: "Jonah", nemesis: "Whales" }, { character: "Jonah", nemesis: "Spiders" }, { character: "Alan", nemesis: "Ghosts" }, { character:"Alan", nemesis: "Zombies" }, { character: "Glory", nemesis: "Buffy" }, { character: "Bob", nemesis: "foo" }])` має повернути `[{"A_age": 27,"A_name": "Jonah", "B_character": "Jonah", "B_nemesis": "Whales"}, {"A_age": 27,"A_name": "Jonah", "B_character": "Jonah", "B_nemesis": "Spiders"}, {"A_age": 18,"A_name": "Alan", "B_character": "Alan", "B_nemesis": "Ghosts"}, {"A_age": 18,"A_name": "Alan", "B_character": "Alan", "B_nemesis": "Zombies"}, {"A_age": 28,"A_name": "Glory", "B_character": "Glory", "B_nemesis": "Buffy"}, {"A_age": 28,"A_name": "Alan", "B_character": "Alan", "B_nemesis": "Ghosts"}, {"A_age": 28,"A_name": "Alan", "B_character": "Alan", "B_nemesis": "Zombies"}]`
```js
assert.deepEqual(hashJoin(hash1, hash2), res);
```
# --seed--
## --after-user-code--
```js
const hash1 = [
{ age: 27, name: 'Jonah' },
{ age: 18, name: 'Alan' },
{ age: 28, name: 'Glory' },
{ age: 18, name: 'Popeye' },
{ age: 28, name: 'Alan' }
];
const hash2 = [
{ character: 'Jonah', nemesis: 'Whales' },
{ character: 'Jonah', nemesis: 'Spiders' },
{ character: 'Alan', nemesis: 'Ghosts' },
{ character: 'Alan', nemesis: 'Zombies' },
{ character: 'Glory', nemesis: 'Buffy' },
{ character: 'Bob', nemesis: 'foo' }
];
const res = [
{ A_age: 27, A_name: 'Jonah', B_character: 'Jonah', B_nemesis: 'Whales' },
{ A_age: 27, A_name: 'Jonah', B_character: 'Jonah', B_nemesis: 'Spiders' },
{ A_age: 18, A_name: 'Alan', B_character: 'Alan', B_nemesis: 'Ghosts' },
{ A_age: 18, A_name: 'Alan', B_character: 'Alan', B_nemesis: 'Zombies' },
{ A_age: 28, A_name: 'Glory', B_character: 'Glory', B_nemesis: 'Buffy' },
{ A_age: 28, A_name: 'Alan', B_character: 'Alan', B_nemesis: 'Ghosts' },
{ A_age: 28, A_name: 'Alan', B_character: 'Alan', B_nemesis: 'Zombies' }
];
const bench1 = [{ name: 'u2v7v', num: 1 }, { name: 'n53c8', num: 10 }, { name: 'oysce', num: 9 }, { name: '0mto2s', num: 1 }, { name: 'vkh5id', num: 4 }, { name: '5od0cf', num: 8 }, { name: 'uuulue', num: 10 }, { name: '3rgsbi', num: 9 }, { name: 'kccv35r', num: 4 }, { name: '80un74', num: 9 }, { name: 'h4pp3', num: 6 }, { name: '51bit', num: 7 }, { name: 'j9ndf', num: 8 }, { name: 'vf3u1', num: 10 }, { name: 'g0bw0om', num: 10 }, { name: 'j031x', num: 7 }, { name: 'ij3asc', num: 9 }, { name: 'byv83y', num: 8 }, { name: 'bjzp4k', num: 4 }, { name: 'f3kbnm', num: 10 }];
const bench2 = [{ friend: 'o8b', num: 8 }, { friend: 'ye', num: 2 }, { friend: '32i', num: 5 }, { friend: 'uz', num: 3 }, { friend: 'a5k', num: 4 }, { friend: 'uad', num: 7 }, { friend: '3w5', num: 10 }, { friend: 'vw', num: 10 }, { friend: 'ah', num: 4 }, { friend: 'qv', num: 7 }, { friend: 'ozv', num: 2 }, { friend: '9ri', num: 10 }, { friend: '7nu', num: 4 }, { friend: 'w3', num: 9 }, { friend: 'tgp', num: 8 }, { friend: 'ibs', num: 1 }, { friend: 'ss7', num: 6 }, { friend: 'g44', num: 9 }, { friend: 'tab', num: 9 }, { friend: 'zem', num: 10 }];
```
## --seed-contents--
```js
function hashJoin(hash1, hash2) {
return [];
}
```
# --solutions--
```js
function hashJoin(hash1, hash2) {
const hJoin = (tblA, tblB, strJoin) => {
const [jA, jB] = strJoin.split('=');
const M = tblB.reduce((a, x) => {
const id = x[jB];
return (
a[id] ? a[id].push(x) : (a[id] = [x]),
a
);
}, {});
return tblA.reduce((a, x) => {
const match = M[x[jA]];
return match ? (
a.concat(match.map(row => dictConcat(x, row)))
) : a;
}, []);
};
const dictConcat = (dctA, dctB) => {
const ok = Object.keys;
return ok(dctB).reduce(
(a, k) => (a[`B_${k}`] = dctB[k]) && a,
ok(dctA).reduce(
(a, k) => (a[`A_${k}`] = dctA[k]) && a, {}
)
);
};
return hJoin(hash1, hash2, 'name=character');
}
```

View File

@@ -0,0 +1,155 @@
---
id: 595b98f8b5a2245e243aa831
title: Трикутники Герона
challengeType: 5
forumTopicId: 302285
dashedName: heronian-triangles
---
# --description--
[Формула Герона](https://en.wikipedia.org/wiki/Heron's formula "wp: Heron's formula") для площі трикутника з урахуванням довжини його трьох сторін `a` `b`, та `c` подається як:
$A = \\sqrt{s(s-a)(s-b)(s-c)},$
де `s` є половиною периметра трикутника; тобто
$s=\\frac{a+b+c}{2}
Трикутники Героніа — це трикутники, у яких усі сторони та площа є цілими числами.
Прикладом є трикутник зі сторонами `3, 4, 5`, площа якого дорівнює `6` (а периметр `12`).
Зверніть увагу, що будь-який трикутник, усі сторони якого є цілим кратним `3, 4, 5`; такі, як `6, 8, 10,`, також буде трикутником Герона.
Визначте примітивний трикутник Герона як трикутник Герона, де найбільший спільний дільник
усіх трьох сторін дорівнює `1` (єдність).
Це виключає, наприклад, трикутник `6, 8, 10.`
# --instructions--
Реалізуйте функцію, засновану на формулі Герона, яка повертає перші <code>n<sub>th</sub></code> впорядковані трикутники у масиві масивів.
# --hints--
`heronianTriangle` має бути функцією.
```js
assert(typeof heronianTriangle === 'function');
```
`heronianTriangle(10)` має повернути `[[3, 4, 5], [5, 5, 6], [5, 5, 8], [4, 13, 15], [5, 12, 13], [9, 10, 17], [3, 25, 26], [7, 15, 20], [10, 13, 13], [8, 15, 17]]`
```js
assert.deepEqual(heronianTriangle(testCases[0]), res[0]);
```
`heronianTriangle(15)` має повернути `[[3, 4, 5], [5, 5, 6], [5, 5, 8], [4, 13, 15], [5, 12, 13], [9, 10, 17], [3, 25, 26], [7, 15, 20], [10, 13, 13], [8, 15, 17], [13, 13, 24], [6, 25, 29], [11, 13, 20], [5, 29, 30], [13, 14, 15]],`
```js
assert.deepEqual(heronianTriangle(testCases[1]), res[1]);
```
`heronianTriangle(20)` має повернути `[[3, 4, 5], [5, 5, 6], [5, 5, 8], [4, 13, 15], [5, 12, 13], [9, 10, 17], [3, 25, 26], [7, 15, 20], [10, 13, 13], [8, 15, 17], [13, 13, 24], [6, 25, 29], [11, 13, 20], [5, 29, 30], [13, 14, 15], [10, 17, 21], [7, 24, 25], [8, 29, 35], [12, 17, 25], [4, 51, 53]],`
```js
assert.deepEqual(heronianTriangle(testCases[2]), res[2]);
```
`heronianTriangle(25)` має повернути `[[3, 4, 5], [5, 5, 6], [5, 5, 8], [4, 13, 15], [5, 12, 13], [9, 10, 17], [3, 25, 26], [7, 15, 20], [10, 13, 13], [8, 15, 17], [13, 13, 24], [6, 25, 29], [11, 13, 20], [5, 29, 30], [13, 14, 15], [10, 17, 21], [7, 24, 25], [8, 29, 35], [12, 17, 25], [4, 51, 53], [19, 20, 37],[16, 17, 17], [17, 17, 30], [16, 25, 39], [13, 20, 21]]`
```js
assert.deepEqual(heronianTriangle(testCases[3]), res[3]);
```
# --seed--
## --after-user-code--
```js
const testCases = [10, 15, 20, 25];
const res = [
[[3, 4, 5], [5, 5, 6], [5, 5, 8], [4, 13, 15], [5, 12, 13], [9, 10, 17], [3, 25, 26], [7, 15, 20], [10, 13, 13], [8, 15, 17]],
[[3, 4, 5], [5, 5, 6], [5, 5, 8], [4, 13, 15], [5, 12, 13], [9, 10, 17], [3, 25, 26], [7, 15, 20], [10, 13, 13], [8, 15, 17], [13, 13, 24], [6, 25, 29], [11, 13, 20], [5, 29, 30], [13, 14, 15]],
[[3, 4, 5], [5, 5, 6], [5, 5, 8], [4, 13, 15], [5, 12, 13], [9, 10, 17], [3, 25, 26], [7, 15, 20], [10, 13, 13], [8, 15, 17], [13, 13, 24], [6, 25, 29], [11, 13, 20], [5, 29, 30], [13, 14, 15], [10, 17, 21], [7, 24, 25], [8, 29, 35], [12, 17, 25], [4, 51, 53]],
[[3, 4, 5], [5, 5, 6], [5, 5, 8], [4, 13, 15], [5, 12, 13], [9, 10, 17], [3, 25, 26], [7, 15, 20], [10, 13, 13], [8, 15, 17], [13, 13, 24], [6, 25, 29], [11, 13, 20], [5, 29, 30], [13, 14, 15], [10, 17, 21], [7, 24, 25], [8, 29, 35], [12, 17, 25], [4, 51, 53], [19, 20, 37], [16, 17, 17], [17, 17, 30], [16, 25, 39], [13, 20, 21]]
];
```
## --seed-contents--
```js
function heronianTriangle(n) {
return [];
}
```
# --solutions--
```js
function heronianTriangle(n) {
const list = [];
const result = [];
let j = 0;
for (let c = 1; c <= 200; c++) {
for (let b = 1; b <= c; b++) {
for (let a = 1; a <= b; a++) {
if (gcd(gcd(a, b), c) === 1 && isHeron(heronArea(a, b, c))) {
list[j++] = new Array(a, b, c, heronArea(a, b, c));
}
}
}
}
sort(list);
for (let i = 0; i < n; i++) {
result[i] = [list[i][0], list[i][1], list[i][2]];
}
return result;
function heronArea(a, b, c) {
const s = (a + b + c) / 2;
return Math.sqrt(s * (s - a) * (s - b) * (s - c));
}
function isHeron(h) { return h % 1 === 0 && h > 0; }
function gcd(a, b) {
let leftover = 1;
let dividend = a > b ? a : b;
let divisor = a > b ? b : a;
while (leftover !== 0) {
leftover = dividend % divisor;
if (leftover > 0) {
dividend = divisor;
divisor = leftover;
}
}
return divisor;
}
function sort(arg) {
let swapped = true;
let temp = [];
while (swapped) {
swapped = false;
for (let i = 1; i < arg.length; i++) {
if (arg[i][4] < arg[i - 1][4] || arg[i][4] === arg[i - 1][4] && arg[i][3] < arg[i - 1][3]) {
temp = arg[i];
arg[i] = arg[i - 1];
arg[i - 1] = temp;
swapped = true;
}
}
}
}
}
```

View File

@@ -0,0 +1,166 @@
---
id: 59622f89e4e137560018a40e
title: Послідовність Хофштадтера
challengeType: 5
forumTopicId: 302286
dashedName: hofstadter-figure-figure-sequences
---
# --description--
Ці дві послідовності додатніх чисел визначаються як:
$R(1)=1\\ ;\\ S(1)=2 \\\\R(n)=R(n-1)+S(n-1), \\quad n>1.$
Послідовність $S(n)$ далі визначається як послідовність натуральних чисел, яких немає в $R(n)$.
Послідовність $R$ запущена:
<pre>1, 3, 7, 12, 18, ...</pre>
Послідовність $R$ запущена:
<pre>2, 4, 5, 6, 8, ...</pre>
# --instructions--
Створіть 2 функції названі як `ffr` і `ffs` коли їм надають `n` повернення` R(n)` або ` S(n)` відповідно. (Зверніть увагу на те, щоб R(1) = 1 і S(1) = 2 уникати окремих помилок).
Не слід припускати жодного максимального значення для ` n `.
**Посилання**
<ul>
<li>
Sloane's <a href='https://oeis.org/A005228' target='_blank'>A005228</a> і <a href='https://oeis.org/A030124' target='_blank'>A030124</a>.
</li>
<li>
Вікіпедія: <a href='https://en.wikipedia.org/wiki/Hofstadter_sequence#Hofstadter_Figure-Figure_sequences' title='wp: Hofstadter_sequence#Hofstadter_Figure-Figure_sequences' target='_blank'> Послідовність Хофштадтера</a>.
</li>
</ul>
# --hints--
`ffr` має бути функцією.
```js
assert(typeof ffr === 'function');
```
`ffr` має бути функцією.
```js
assert(typeof ffs === 'function');
```
`ffr` повинен повернути ціле число.
```js
assert(Number.isInteger(ffr(1)));
```
`ffr` повинен повернути ціле число.
```js
assert(Number.isInteger(ffs(1)));
```
`ffr(10)` повинен повертатися `69`
```js
assert.equal(ffr(ffrParamRes[0][0]), ffrParamRes[0][1]);
```
`ffr(50)` повинен повертатися ` 1509`
```js
assert.equal(ffr(ffrParamRes[1][0]), ffrParamRes[1][1]);
```
`ffr(100)` повинен повертатися ` 5764 `
```js
assert.equal(ffr(ffrParamRes[2][0]), ffrParamRes[2][1]);
```
`ffr(1000)` повинен повертатися ` 526334`
```js
assert.equal(ffr(ffrParamRes[3][0]), ffrParamRes[3][1]);
```
`ffs(10)` повинен повертатися ` 14`
```js
assert.equal(ffs(ffsParamRes[0][0]), ffsParamRes[0][1]);
```
`ffr(50)` повинен повертатися ` 59`
```js
assert.equal(ffs(ffsParamRes[1][0]), ffsParamRes[1][1]);
```
`ffr(100)` повинен повертатися ` 112`
```js
assert.equal(ffs(ffsParamRes[2][0]), ffsParamRes[2][1]);
```
`ffs(1000)` повинен повертатися ` 1041`
```js
assert.equal(ffs(ffsParamRes[3][0]), ffsParamRes[3][1]);
```
# --seed--
## --after-user-code--
```js
const ffrParamRes = [[10, 69], [50, 1509], [100, 5764], [1000, 526334]];
const ffsParamRes = [[10, 14], [50, 59], [100, 112], [1000, 1041]];
```
## --seed-contents--
```js
function ffr(n) {
return n;
}
function ffs(n) {
return n;
}
```
# --solutions--
```js
const R = [null, 1];
const S = [null, 2];
function extendSequences (n) {
let current = Math.max(R[R.length - 1], S[S.length - 1]);
let i;
while (R.length <= n || S.length <= n) {
i = Math.min(R.length, S.length) - 1;
current += 1;
if (current === R[i] + S[i]) {
R.push(current);
} else {
S.push(current);
}
}
}
function ffr (n) {
extendSequences(n);
return R[n];
}
function ffs (n) {
extendSequences(n);
return S[n];
}
```

View File

@@ -0,0 +1,92 @@
---
id: 59637c4d89f6786115efd814
title: Q послідовність Гофстедтера
challengeType: 5
forumTopicId: 302287
dashedName: hofstadter-q-sequence
---
# --description--
[Q послідовність Гофстедтера](https://en.wikipedia.org/wiki/Hofstadter_sequence#Hofstadter_Q_sequence "wp: Hofstadter_sequence#Hofstadter_Q_sequence") визначають як:
$Q(1)=Q(2)=1, \\\\ Q(n)=Q\\big(n-Q(n-1)\\big)+Q\\big(n-Q(n-2)), \\quad n>2.$
Вона визначається як [послідовність Фібоначчі](https://rosettacode.org/wiki/Fibonacci sequence "Fibonacci sequence"), але в той час як наступний член у послідовності Фібоначчі - це сума попередніх двох членів, у послідовності Q попередні два члени вказують на те, як далеко треба повернутися назад в послідовності Q, щоб знайти два числа, які потрібно підсумувати, щоб утворити наступний член послідовності.
# --instructions--
Реалізуйте рівняння Q послідовності Гофстедтера в якості функції. Функція має прийняти число, `n` та повернути ціле число.
# --hints--
`hofstadterQ` має бути функцією.
```js
assert(typeof hofstadterQ === 'function');
```
`hofstadterQ()` має повернути `integer`
```js
assert(Number.isInteger(hofstadterQ(1000)));
```
`hofstadterQ(1000)` має повернути `502`
```js
assert.equal(hofstadterQ(testCase[0]), res[0]);
```
`hofstadterQ(1500)` має повернути `755`
```js
assert.equal(hofstadterQ(testCase[1]), res[1]);
```
`hofstadterQ(2000)` має повернути `1005`
```js
assert.equal(hofstadterQ(testCase[2]), res[2]);
```
`hofstadterQ(2500)` має повернути `1261`
```js
assert.equal(hofstadterQ(testCase[3]), res[3]);
```
# --seed--
## --after-user-code--
```js
const testCase = [1000, 1500, 2000, 2500];
const res = [502, 755, 1005, 1261];
```
## --seed-contents--
```js
function hofstadterQ(n) {
return n;
}
```
# --solutions--
```js
function hofstadterQ (n) {
const memo = [1, 1, 1];
const Q = function (i) {
let result = memo[i];
if (typeof result !== 'number') {
result = Q(i - Q(i - 1)) + Q(i - Q(i - 2));
memo[i] = result;
}
return result;
};
return Q(n);
}
```

View File

@@ -0,0 +1,101 @@
---
id: 5a23c84252665b21eecc7eb0
title: 'І перед Е (виняток: окрім після С)'
challengeType: 5
forumTopicId: 302288
dashedName: i-before-e-except-after-c
---
# --description--
Вираз ["I перед E, але не після C"](https://en.wikipedia.org/wiki/I before E except after C) - це загальновідомий мнемонічний вираз, який допомагає при написанні англійський слів.
Використовуючи надані слова, перевірте, чи два підпункти фрази переконливі окремо:
<ol>
<li>
<i>"Я до E, коли не передував С".</i>
</li>
<li>
<i>"E до того, коли перед мною передувала С".</i>
</li>
</ol>
Вихідна фраза є правдоподібною, якщо обидві субфрази правдоподібні.
# --instructions--
Напишіть функцію, яка допускає слово і перевірте, чи воно підлягає правилу. Якщо слово підлягає правилу, то функція успішна, якщо ні - функція хибна.
# --hints--
`IBeforeExceptC` має бути функцією.
```js
assert(typeof IBeforeExceptC == 'function');
```
`IBeforeExceptC("receive")` має повертати логічне значення.
```js
assert(typeof IBeforeExceptC('receive') == 'boolean');
```
`IBeforeExceptC("receive")` має повертати `true`.
```js
assert.equal(IBeforeExceptC('receive'), true);
```
`IBeforeExceptC("science")` має повертати `false`.
```js
assert.equal(IBeforeExceptC('science'), false);
```
`IBeforeExceptC("imperceivable")` має повертати `true`.
```js
assert.equal(IBeforeExceptC('imperceivable'), true);
```
`IBeforeExceptC("inconceivable")` має повертати `true`.
```js
assert.equal(IBeforeExceptC('inconceivable'), true);
```
`IBeforeExceptC("insufficient")` має повертати `false`.
```js
assert.equal(IBeforeExceptC('insufficient'), false);
```
`IBeforeExceptC("omniscient")` має повертати `false`.
```js
assert.equal(IBeforeExceptC('omniscient'), false);
```
# --seed--
## --seed-contents--
```js
function IBeforeExceptC(word) {
}
```
# --solutions--
```js
function IBeforeExceptC(word)
{
if(word.indexOf("c")==-1 && word.indexOf("ie")!=-1)
return true;
else if(word.indexOf("cei")!=-1)
return true;
return false;
}
```

View File

@@ -0,0 +1,104 @@
---
id: 5a23c84252665b21eecc7eaf
title: IBAN
challengeType: 5
forumTopicId: 302289
dashedName: iban
---
# --description--
The [Міжнародний номер банківського рахунку (IBAN)](https://en.wikipedia.org/wiki/International_Bank_Account_Number) є міжнародно узгодженим засобом ідентифікації банківських рахунків через національні кордони зі зниженим ризиком розповсюдження [transcription errors](https://en.wikipedia.org/wiki/Transcription_error).
IBAN містить до 34 літерно-цифрових символів:
<ul>
<li>спочатку дволітерний код країни за стандартом ISO 3166-1 alpha-2</li>
<li>потім дві контрольні цифри, та</li>
<li>нарешті, базовий номер банківського рахунку для конкретної країни (BBAN).</li>
</ul>
Контрольні цифри дають змогу перевірити правильність номеру банківського рахунку, щоб підтвердити його цілісність навіть перед поданням транзакції.
# --instructions--
Напишіть функцію, яка приймає рядок IBAN як параметр. Якщо вона допустима, поверніть true. Якщо ні, поверніть false.
# --hints--
`isValid` має бути функцією.
```js
assert(typeof isValid == 'function');
```
`isValid("GB82 WEST 1234 5698 7654 32")` має повернути логічне значення.
```js
assert(typeof isValid('GB82 WEST 1234 5698 7654 32') == 'boolean');
```
`isValid("GB82 WEST 1234 5698 7654 32")` має повернути `true`.
```js
assert.equal(isValid('GB82 WEST 1234 5698 7654 32'), true);
```
`isValid("GB82 WEST 1.34 5698 7654 32")` має повернути `false`.
```js
assert.equal(isValid('GB82 WEST 1.34 5698 7654 32'), false);
```
`isValid("GB82 WEST 1234 5698 7654 325")` має повернути `false`.
```js
assert.equal(isValid('GB82 WEST 1234 5698 7654 325'), false);
```
`isValid("GB82 TEST 1234 5698 7654 32")` має повернути `false`.
```js
assert.equal(isValid('GB82 TEST 1234 5698 7654 32'), false);
```
`isValid("SA03 8000 0000 6080 1016 7519")` має повернути `true`.
```js
assert.equal(isValid('SA03 8000 0000 6080 1016 7519'), true);
```
# --seed--
## --seed-contents--
```js
function isValid(iban) {
}
```
# --solutions--
```js
function isValid(iban) {
var ibanLen = {
NO:15, BE:16, DK:18, FI:18, FO:18, GL:18, NL:18, MK:19,
SI:19, AT:20, BA:20, EE:20, KZ:20, LT:20, LU:20, CR:21,
CH:21, HR:21, LI:21, LV:21, BG:22, BH:22, DE:22, GB:22,
GE:22, IE:22, ME:22, RS:22, AE:23, GI:23, IL:23, AD:24,
CZ:24, ES:24, MD:24, PK:24, RO:24, SA:24, SE:24, SK:24,
VG:24, TN:24, PT:25, IS:26, TR:26, FR:27, GR:27, IT:27,
MC:27, MR:27, SM:27, AL:28, AZ:28, CY:28, DO:28, GT:28,
HU:28, LB:28, PL:28, BR:29, PS:29, KW:30, MU:30, MT:31
}
iban = __helpers.removeWhiteSpace(iban)
if (!iban.match(/^[\dA-Z]+$/)) return false
var len = iban.length
if (len != ibanLen[iban.substr(0,2)]) return false
iban = iban.substr(4) + iban.substr(0,4)
for (var s='', i=0; i<len; i+=1) s+=parseInt(iban.charAt(i),36)
for (var m=s.substr(0,15)%97, s=s.substr(15); s; s=s.substr(13)) m=(m+s.substr(0,13))%97
return m == 1
}
```

View File

@@ -0,0 +1,88 @@
---
id: 5a23c84252665b21eecc7eb1
title: Одинична матриця
challengeType: 5
forumTopicId: 302290
dashedName: identity-matrix
---
# --description--
*Одинична матриця* це квадратна матриця розміру \\( n \\times n \\), де всі діагональні елементи `1`і (одиниці), а всі інші елементи `0`і (нулі).
<ul>
<li style='list-style: none;'>\(\displaystyle I_{n}=\begin{bmatrix} 1 &#x26; 0 &#x26; 0 \cr 0 &#x26; 1 &#x26; 0 \cr 0 &#x26; 0 &#x26; 1 \cr \end{bmatrix}\)</li>
</ul>
# --instructions--
Напишіть функцію, яка приймає число `n` як параметр і повертає одиничну матрицю порядку \\( n \\times n \\).
# --hints--
`idMatrix` має бути функцією.
```js
assert(typeof idMatrix == 'function');
```
`idMatrix(1)` має повернути масив.
```js
assert(Array.isArray(idMatrix(1)));
```
`idMatrix(1)` має повернути `[ [ 1 ] ]`.
```js
assert.deepEqual(idMatrix(1), results[0]);
```
`idMatrix(2)` має повернути `[ [ 1, 0 ], [ 0, 1 ] ]`.
```js
assert.deepEqual(idMatrix(2), results[1]);
```
`idMatrix(3)` має повернути `[ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ]`.
```js
assert.deepEqual(idMatrix(3), results[2]);
```
`idMatrix(4)` має повернути `[ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ]`.
```js
assert.deepEqual(idMatrix(4), results[3]);
```
# --seed--
## --after-user-code--
```js
let results=[[ [ 1 ] ],
[ [ 1, 0 ], [ 0, 1 ] ],
[ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ],
[ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ]]
```
## --seed-contents--
```js
function idMatrix(n) {
}
```
# --solutions--
```js
function idMatrix(n) {
return Array.apply(null, new Array(n)).map(function (x, i, xs) {
return xs.map(function (_, k) {
return i === k ? 1 : 0;
})
});
}
```

View File

@@ -0,0 +1,96 @@
---
id: 5a23c84252665b21eecc7ec1
title: Ітерація цифр квадрату числа
challengeType: 5
forumTopicId: 302291
dashedName: iterated-digits-squaring
---
# --description--
Якщо ви додасте квадрат цифр натурального числа (цілого числа, більшого за нуль), ви завжди отримаєте або 1, або 89:
<pre>15 -> 26 -> 40 -> 16 -> 37 -> 58 -> 89
7 -> 49 -> 97 -> 130 -> 10 -> 1
</pre>
# --instructions--
Напишіть функцію, яка використовує число як параметр, і видає 1 або 89 після виконання описаного процесу.
# --hints--
`iteratedSquare` має бути функцією.
```js
assert(typeof iteratedSquare == 'function');
```
`iteratedSquare(4)` має повертати число.
```js
assert(typeof iteratedSquare(4) == 'number');
```
`iteratedSquare(4)` має повертати `89`.
```js
assert.equal(iteratedSquare(4), 89);
```
`iteratedSquare(7)` має повертати`1`.
```js
assert.equal(iteratedSquare(7), 1);
```
`iteratedSquare(15)` має повертати`89`.
```js
assert.equal(iteratedSquare(15), 89);
```
`iteratedSquare(20)` має повертати`89`.
```js
assert.equal(iteratedSquare(20), 89);
```
`iteratedSquare(70)` має повертати`1`.
```js
assert.equal(iteratedSquare(70), 1);
```
`iteratedSquare(100)` має повертати`1`.
```js
assert.equal(iteratedSquare(100), 1);
```
# --seed--
## --seed-contents--
```js
function iteratedSquare(n) {
}
```
# --solutions--
```js
function iteratedSquare(n) {
var total;
while (n != 89 && n != 1) {
total = 0;
while (n > 0) {
total += Math.pow(n % 10, 2);
n = Math.floor(n/10);
}
n = total;
}
return n;
}
```

View File

@@ -0,0 +1,146 @@
---
id: 5a23c84252665b21eecc7ec2
title: Подібність Джаро
challengeType: 5
forumTopicId: 302292
dashedName: jaro-distance
---
# --description--
Подібність Джаро — це міра схожості між двома рядками. Чим більший показник подібності Джаро для двох рядків, тим більше вони схожі. Оцінка нормується таким чином: `0` — схожість відсутня, а `1` — це точна схожість.
**Визначення**
Подібність Джаро \\( d_j \\) з двох вибраних рядків \\((\\1\\) і \\(s_2\\) є
\\begin{align}d_j = \\begin{cases}0& & \\text{if }m=0 \\\\\\\\{\\frac {1}{3}}\\left({\\frac {m}{|s\_{1}|}}+{\\frac {m}{|s\_{2}|}}+{\\frac {m-t}{m}}\\right)& & \\text{otherwise}\\end{cases}\\end{align}
Де:
<ul>
<li>\(m\) є числом <i>відповідних символів</i>;</li>
<li> \(t\) — це половина числа <i>транспозицій</i>.</li>
</ul>
Два символи з \\(s_1\\) та \\(s_2\\) відповідно, вважаються *співпадінням*, якщо вони однакові і розташовані не далі, ніж \\(\\left\\lfloor\\frac{\\max(|s_1|, s_2|)}{2}\\right\\rfloor-1\\).
Кожен символ \\(s_1\\) порівнюється з усіма відповідними символами у \\(s_2\\) . Кількість відповідних (але в різному порядку) символів, розділених на 2, визначає кількість * транспозицій *.
**Наприклад**
У рядках \\(s_1\\) *DWAYNE* та \\(s_2\\) *DUANE* виявили:
<ul>
<li>\(m = 4\)</li>
<li>\(|s_1| = 6\)</li>
<li>\(|s_2| = 5\)</li>
<li>\(t = 0\)</li>
</ul>
Ми знайшли: \\(d_j = \\frac{1}{3}\\left(\\frac{4}{6} + \\frac{4}{5} + \\frac{4-0}{4}\\right) = 0.822\\).
# --instructions--
Напишіть функцію а, у параметрах встановіть дві рядки. Це має бути схоже на подібність Джаро.
# --hints--
`jaro` має бути функцією.
```js
assert(typeof jaro == 'function');
```
`jaro("MARTHA", "MARHTA")` має повернути число.
```js
assert(typeof jaro('MARTHA', 'MARHTA') == 'number');
```
`jaro("MARTHA", "MARHTA")` має повернути `0.9444444444444445`.
```js
assert.equal(jaro('MARTHA', 'MARHTA'), 0.9444444444444445);
```
`jaro("DIXON", "DICKSONX")` має повернути `0.7666666666666666`.
```js
assert.equal(jaro('DIXON', 'DICKSONX'), 0.7666666666666666);
```
`jaro("JELLYFISH", "SMELLYFISH")` має повернути `0.8962962962962964`.
```js
assert.equal(jaro('JELLYFISH', 'SMELLYFISH'), 0.8962962962962964);
```
`jaro("HELLOS", "CHELLO")` має повернути `0.888888888888889`.
```js
assert.equal(jaro('HELLOS', 'CHELLO'), 0.888888888888889);
```
`jaro("ABCD", "BCDA")` має повернути `0.8333333333333334`.
```js
assert.equal(jaro('ABCD', 'BCDA'), 0.8333333333333334);
```
# --seed--
## --seed-contents--
```js
function jaro(s, t) {
}
```
# --solutions--
```js
function jaro(s, t) {
var s_len = s.length;
var t_len = t.length;
if (s_len == 0 && t_len == 0) return 1;
var match_distance = Math.max(s_len, t_len) / 2 - 1;
var s_matches = new Array(s_len);
var t_matches = new Array(t_len);
var matches = 0;
var transpositions = 0;
for (var i = 0; i < s_len; i++) {
var start = Math.max(0, i - match_distance);
var end = Math.min(i + match_distance + 1, t_len);
for (var j = start; j < end; j++) {
if (t_matches[j]) continue;
if (s.charAt(i) != t.charAt(j)) continue;
s_matches[i] = true;
t_matches[j] = true;
matches++;
break;
}
}
if (matches == 0) return 0;
var k = 0;
for (var i = 0; i < s_len; i++) {
if (!s_matches[i]) continue;
while (!t_matches[k]) k++;
if (s.charAt(i) != t.charAt(k)) transpositions++;
k++;
}
return ((matches / s_len) +
(matches / t_len) +
((matches - transpositions / 2.0) / matches)) / 3.0;
}
```

View File

@@ -0,0 +1,90 @@
---
id: 5a23c84252665b21eecc7ec4
title: JortSort
challengeType: 5
forumTopicId: 302293
dashedName: jortsort
---
# --description--
jortSort — це набір інструментів для сортування, за допомогою яких користувач виконає роботу і гарантує ефективність, оскільки вам більше не доведеться сортувати. Вперше, його представила Дженн "Moneydollars" Шиффер на престижному [JSConf](https://www.youtube.com/watch?v=pj4U_W0OFoE).
jortSort має бути функцією, яка бере в якості аргументу єдиний масив об'єктів, що можна порівняти. Потім він сортує масив у порядку зростання та порівнює відсортований масив з початковим масивом. Якщо масиви збігаються (тобто вихідний масив вже було відсортовано), функція повертає true. Якщо масиви не співпадають (наприклад, вихідний масив не було сортовано), функція повертає false.
# --hints--
`jortsort` має бути функцією.
```js
assert(typeof jortsort == 'function');
```
`jortsort([1,2,3,4,5])` має повернути boolean.
```js
assert(typeof jortsort([1, 2, 3, 4, 5]) == 'boolean');
```
`jortsort([1,2,3,4,5])` має повернути `true`.
```js
assert.equal(jortsort([1, 2, 3, 4, 5]), true);
```
`jortsort([1,2,13,4,5])` має повернути `false`.
```js
assert.equal(jortsort([1, 2, 13, 4, 5]), false);
```
`jortsort([12,4,51,2,4])` має повернути `false`.
```js
assert.equal(jortsort([12, 4, 51, 2, 4]), false);
```
`jortsort([1,2])` має повернути `true`.
```js
assert.equal(jortsort([1, 2]), true);
```
`jortsort([5,4,3,2,1])` має повернути `false`.
```js
assert.equal(jortsort([5, 4, 3, 2, 1]), false);
```
`jortsort([1,1,1,1,1])` має повернути `true`.
```js
assert.equal(jortsort([1, 1, 1, 1, 1]), true);
```
# --seed--
## --seed-contents--
```js
function jortsort(array) {
}
```
# --solutions--
```js
function jortsort(array) {
// sort the array
var originalArray = array.slice(0);
array.sort( function(a,b){return a - b} );
// compare to see if it was originally sorted
for (var i = 0; i < originalArray.length; ++i) {
if (originalArray[i] !== array[i]) return false;
}
return true;
};
```

View File

@@ -0,0 +1,98 @@
---
id: 5a23c84252665b21eecc7ec5
title: Задача Йосифа Флавія
challengeType: 5
forumTopicId: 302294
dashedName: josephus-problem
---
# --description--
[ Задача Йосифа Флавія](https://en.wikipedia.org/wiki/Josephus problem) це математична головоломка з похмурим описом: $n$ ув'язнені стоять у колі, послідовно пронумеровані від $0$ до $n-1$.
Кат йде по колу, починаючи від ув’язненого $0$, виводить кожного $k$-го ув’язненого і вбиває його.
З часом, коло стає все меншим і меншим, поки не залишиться лише один в’язень, якого потім відпускають.
Наприклад, якщо є $n = 5$ ув'язнених і $k = 2$, порядок вбивства в'язнів (назвемо це "послідовністю вбивств") буде 1, 3, 0 і 4, а вцілілий буде #2.
Враховуючи будь-які $n, k > 0$, дізнайтеся, хто з ув'язнених виживе.
В одному з таких випадків було 41 ув'язнених, а кожен 3 <sup>rd</sup> в'язень був убитий ($k=3$).
Серед них був розумний хлопець на ім'я Йосип, який вирішив цю задачу, та обрав виграшну позицію, а згодом постійно розповідав про це.
Який номер він обрав?
# --instructions--
Напишіть функцію, яка бере початкову кількість ув'язнених і "k" в якості параметра і повертає номер в'язня, який вижив.
# --hints--
`josephus` повинен бути функцією.
```js
assert(typeof josephus == 'function');
```
`josephus(30,3)` повинен повернути число.
```js
assert(typeof josephus(30, 3) == 'number');
```
`josephus(30,3)` має повернути `28`.
```js
assert.equal(josephus(30, 3), 28);
```
`josephus(30,5)` має повернути `2`.
```js
assert.equal(josephus(30, 5), 2);
```
`josephus(20,2)` повинен повернути `8`.
```js
assert.equal(josephus(20, 2), 8);
```
`josephus(17,6)` повинен повернути `1`.
```js
assert.equal(josephus(17, 6), 1);
```
`josephus(29,4)` повинен повернути `1`.
```js
assert.equal(josephus(29, 4), 1);
```
# --seed--
## --seed-contents--
```js
function josephus(init, kill) {
}
```
# --solutions--
```js
function josephus(init, kill) {
const arr = Array.from(Array(init).keys());
let curr = -1
while (arr.length > 1) {
curr = (curr + kill) % arr.length;
arr.splice(curr, 1);
curr--;
}
return arr[0];
}
```

View File

@@ -0,0 +1,469 @@
---
id: 5a23c84252665b21eecc7ecb
title: K-d дерево
challengeType: 5
forumTopicId: 302295
dashedName: k-d-tree
---
# --description--
K-d дерево (скорочення від *k*-вимірне дерево) — це структура даних з поділом простору для упорядкування точок у k-вимірному просторі. k-d дерева є корисною структурою даних для декількох застосувань, таких як пошуки у багатовимірному просторі ключів (напр., пошук діапазонів і пошук найближчого сусіда). k-d дерева — це особливий вид дерев двійкового поділу простору. Однак, k-d дерева не підходять для пошуку найближчого сусіда у високорозмірних просторах. Взагалі, якщо розмірність — це *k*, кількість точок у даних, *N*, повинна становити *N* ≫ 2<sup><i>k</i></sup>. Інакше, коли k-d дерева використовуються з високорозмірними даними, більшість точок дерева будуть оцінені, а ефективність не буде кращою, ніж вичерпний пошук, тож замість цього використовують інші методи, такі як приблизний найближчий сусід.
# --instructions--
Напишіть функцію, яка виконає пошук найближчого сусіда за допомогою k-d дерева. Функція потребує два параметри: масив k-вимірних точок і одну k-вимірну точку, найближчий сусід якої має бути виданий функцією. K-вимірна точка буде дана як набір k-елементів.
# --hints--
`kdNN` має бути функцією.
```js
assert(typeof kdNN == 'function');
```
`kdNN([[[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]], [9, 2])` має повернути масив.
```js
assert(
Array.isArray(
kdNN(
[
[2, 3],
[5, 4],
[9, 6],
[4, 7],
[8, 1],
[7, 2]
],
[9, 2]
)
)
);
```
`kdNN([[[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]], [9, 2])` має повернути масив.
```js
assert.deepEqual(
kdNN(
[
[2, 3],
[5, 4],
[9, 6],
[4, 7],
[8, 1],
[7, 2]
],
[9, 2]
),
[8, 1]
);
```
`kdNN([[[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]], [9, 2])` має повернути масив.
```js
assert.deepEqual(
kdNN(
[
[2, 3],
[5, 4],
[9, 6],
[4, 7],
[8, 1],
[7, 2]
],
[7, 1]
),
[8, 1]
);
```
`kdNN([[[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]], [9, 2])` має повернути масив.
```js
assert.deepEqual(
kdNN(
[
[2, 3],
[5, 4],
[9, 6],
[4, 7],
[8, 1],
[7, 2]
],
[3, 2]
),
[2, 3]
);
```
`kdNN([[[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]], [9, 2])` має повернути масив.
```js
assert.deepEqual(
kdNN(
[
[2, 3, 1],
[9, 4, 5],
[4, 6, 7],
[1, 2, 5],
[7, 8, 9],
[3, 6, 1]
],
[1, 2, 3]
),
[1, 2, 5]
);
```
`kdNN([[[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]], [9, 2])` має повернути масив.
```js
assert.deepEqual(
kdNN(
[
[2, 3, 1],
[9, 4, 5],
[4, 6, 7],
[1, 2, 5],
[7, 8, 9],
[3, 6, 1]
],
[4, 5, 6]
),
[4, 6, 7]
);
```
`kdNN([[[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]], [9, 2])` має повернути масив.
```js
assert.deepEqual(
kdNN(
[
[2, 3, 1],
[9, 4, 5],
[4, 6, 7],
[1, 2, 5],
[7, 8, 9],
[3, 6, 1]
],
[8, 8, 8]
),
[7, 8, 9]
);
```
# --seed--
## --seed-contents--
```js
function kdNN(fpoints, fpoint) {
}
```
# --solutions--
```js
function kdNN(fpoints, fpoint) {
function Node(obj, dimension, parent) {
this.obj = obj;
this.left = null;
this.right = null;
this.parent = parent;
this.dimension = dimension;
}
function kdTree(points, metric, dimensions) {
var self = this;
function buildTree(points, depth, parent) {
var dim = depth % dimensions.length,
median,
node;
if (points.length === 0) {
return null;
}
if (points.length === 1) {
return new Node(points[0], dim, parent);
}
points.sort(function(a, b) {
return a[dimensions[dim]] - b[dimensions[dim]];
});
median = Math.floor(points.length / 2);
node = new Node(points[median], dim, parent);
node.left = buildTree(points.slice(0, median), depth + 1, node);
node.right = buildTree(points.slice(median + 1), depth + 1, node);
return node;
}
this.root = buildTree(points, 0, null);
this.insert = function(point) {
function innerSearch(node, parent) {
if (node === null) {
return parent;
}
var dimension = dimensions[node.dimension];
if (point[dimension] < node.obj[dimension]) {
return innerSearch(node.left, node);
} else {
return innerSearch(node.right, node);
}
}
var insertPosition = innerSearch(this.root, null),
newNode,
dimension;
if (insertPosition === null) {
this.root = new Node(point, 0, null);
return;
}
newNode = new Node(
point,
(insertPosition.dimension + 1) % dimensions.length,
insertPosition
);
dimension = dimensions[insertPosition.dimension];
if (point[dimension] < insertPosition.obj[dimension]) {
insertPosition.left = newNode;
} else {
insertPosition.right = newNode;
}
};
this.nearest = function(point, maxNodes, maxDistance) {
var i, result, bestNodes;
bestNodes = new BinaryHeap(function(e) {
return -e[1];
});
function nearestSearch(node) {
var bestChild,
dimension = dimensions[node.dimension],
ownDistance = metric(point, node.obj),
linearPoint = {},
linearDistance,
otherChild,
i;
function saveNode(node, distance) {
bestNodes.push([node, distance]);
if (bestNodes.size() > maxNodes) {
bestNodes.pop();
}
}
for (i = 0; i < dimensions.length; i += 1) {
if (i === node.dimension) {
linearPoint[dimensions[i]] = point[dimensions[i]];
} else {
linearPoint[dimensions[i]] = node.obj[dimensions[i]];
}
}
linearDistance = metric(linearPoint, node.obj);
if (node.right === null && node.left === null) {
if (
bestNodes.size() < maxNodes ||
ownDistance < bestNodes.peek()[1]
) {
saveNode(node, ownDistance);
}
return;
}
if (node.right === null) {
bestChild = node.left;
} else if (node.left === null) {
bestChild = node.right;
} else {
if (point[dimension] < node.obj[dimension]) {
bestChild = node.left;
} else {
bestChild = node.right;
}
}
nearestSearch(bestChild);
if (bestNodes.size() < maxNodes || ownDistance < bestNodes.peek()[1]) {
saveNode(node, ownDistance);
}
if (
bestNodes.size() < maxNodes ||
Math.abs(linearDistance) < bestNodes.peek()[1]
) {
if (bestChild === node.left) {
otherChild = node.right;
} else {
otherChild = node.left;
}
if (otherChild !== null) {
nearestSearch(otherChild);
}
}
}
if (maxDistance) {
for (i = 0; i < maxNodes; i += 1) {
bestNodes.push([null, maxDistance]);
}
}
if (self.root) nearestSearch(self.root);
result = [];
for (i = 0; i < Math.min(maxNodes, bestNodes.content.length); i += 1) {
if (bestNodes.content[i][0]) {
result.push([bestNodes.content[i][0].obj, bestNodes.content[i][1]]);
}
}
return result;
};
}
function BinaryHeap(scoreFunction) {
this.content = [];
this.scoreFunction = scoreFunction;
}
BinaryHeap.prototype = {
push: function(element) {
// Add the new element to the end of the array.
this.content.push(element);
// Allow it to bubble up.
this.bubbleUp(this.content.length - 1);
},
pop: function() {
// Store the first element so we can return it later.
var result = this.content[0];
// Get the element at the end of the array.
var end = this.content.pop();
// If there are any elements left, put the end element at the
// start, and let it sink down.
if (this.content.length > 0) {
this.content[0] = end;
this.sinkDown(0);
}
return result;
},
peek: function() {
return this.content[0];
},
size: function() {
return this.content.length;
},
bubbleUp: function(n) {
// Fetch the element that has to be moved.
var element = this.content[n];
// When at 0, an element can not go up any further.
while (n > 0) {
// Compute the parent element's index, and fetch it.
var parentN = Math.floor((n + 1) / 2) - 1,
parent = this.content[parentN];
// Swap the elements if the parent is greater.
if (this.scoreFunction(element) < this.scoreFunction(parent)) {
this.content[parentN] = element;
this.content[n] = parent;
// Update 'n' to continue at the new position.
n = parentN;
}
// Found a parent that is less, no need to move it further.
else {
break;
}
}
},
sinkDown: function(n) {
// Look up the target element and its score.
var length = this.content.length,
element = this.content[n],
elemScore = this.scoreFunction(element);
while (true) {
// Compute the indices of the child elements.
var child2N = (n + 1) * 2,
child1N = child2N - 1;
// This is used to store the new position of the element,
// if any.
var swap = null;
// If the first child exists (is inside the array)...
if (child1N < length) {
// Look it up and compute its score.
var child1 = this.content[child1N],
child1Score = this.scoreFunction(child1);
// If the score is less than our element's, we need to swap.
if (child1Score < elemScore) swap = child1N;
}
// Do the same checks for the other child.
if (child2N < length) {
var child2 = this.content[child2N],
child2Score = this.scoreFunction(child2);
if (child2Score < (swap == null ? elemScore : child1Score)) {
swap = child2N;
}
}
// If the element needs to be moved, swap it, and continue.
if (swap != null) {
this.content[n] = this.content[swap];
this.content[swap] = element;
n = swap;
}
// Otherwise, we are done.
else {
break;
}
}
}
};
var dims = [];
for (var i = 0; i < fpoint.length; i++) dims.push(i);
var tree = new kdTree(
fpoints,
function(e1, e2) {
var d = 0;
var e3 = e1;
if (!Array.isArray(e1)) {
e3 = [];
for (var key in e1) e3.push(e1[key]);
e1 = e3;
}
e1.forEach(function(e, i) {
var sqd = e1[i] - e2[i];
d += sqd * sqd;
});
return d;
},
dims
);
return tree.nearest(fpoint, 1, 1000)[0][0];
}
```

View File

@@ -0,0 +1,110 @@
---
id: 5a23c84252665b21eecc7eca
title: Числа Капрекара
challengeType: 5
forumTopicId: 302296
dashedName: kaprekar-numbers
---
# --description--
Додатнє ціле число — це [число Капрекара](https://en.wikipedia.org/wiki/Kaprekar number), якщо:
<ul>
<li>Це 1, або</li>
<li>Квадрат числа у десятковій системі числення можна розбити на дві частини, сума яких дає початкове число. </li>
</ul>
Зауважте, що розділ у результаті якого вийдуть лише нулі, є недопустимим, оскільки 0 не вважається додатним числом.
Приклади чисел Капрекара:
<ul>
<li><code>2223</code> це число Капрекар, оскільки <code>2223 * 2223 = 4941729</code> <code>4941729</code> може бути розділено на <code>494</code> та <code>1729</code>, та <code>494 + 1729 = 2223</code></li>
<li>Серія чисел Kaprekar відома як <a href='https://oeis.org/A006886' target='_blank'>A006886</a>, і починається <code>1, 9, 45, 55, ...</code></li>
</ul>
# --instructions--
Напишіть функцію, яка приймає число $n$, основа $bs$, і повертає true, якщо число - це число Капрекара для цієї основи. В іншому випадку видається результат false.
# --hints--
`isKaprekar` повинен бути функцією.
```js
assert(typeof isKaprekar == 'function');
```
`isKaprekar(1, 10)` повинен стати логічним значенням.
```js
assert(typeof isKaprekar(1, 10) == 'boolean');
```
`isKaprekar(1, 10)`повинен повертати `true`.
```js
assert.equal(isKaprekar(1, 10), true);
```
`isKaprekar(9, 10)` повинен повертати `true`.
```js
assert.equal(isKaprekar(9, 10), true);
```
`isKaprekar(2223, 10)` повинен повертати `true`.
```js
assert.equal(isKaprekar(2223, 10), true);
```
`isKaprekar(22823, 10)` повинен повертати `false`.
```js
assert.equal(isKaprekar(22823, 10), false);
```
`isKaprekar(9, 17)` повинен повертати `false`.
```js
assert.equal(isKaprekar(9, 17), false);
```
`isKaprekar(225, 17)` повинен повертати `true`.
```js
assert.equal(isKaprekar(225, 17), true);
```
`isKaprekar(999, 17)` повинен повертати `false`.
```js
assert.equal(isKaprekar(999, 17), false);
```
# --seed--
## --seed-contents--
```js
function isKaprekar(n, bs) {
}
```
# --solutions--
```js
function isKaprekar(n, bs) {
if (n < 1) return false;
if (n == 1) return true;
for (var a = n * n, b = 0, s = 1; a; s *= bs) {
b += (a % bs) * s;
a = Math.floor(a / bs);
if (b && a + b == n) return true;
}
return false;
}
```

View File

@@ -0,0 +1,255 @@
---
id: 5a23c84252665b21eecc7ed1
title: Задача пакування рюкзака/0-1
challengeType: 5
forumTopicId: 323649
dashedName: knapsack-problem0-1
---
# --description--
Задача пакування рюкзака/0-1 виглядає так:
Дано масив об'єктів, які необхідно помістити у рюкзак. Кожен об'єкт має назву, вагу та цінність. Необхідно обрати об'єкти в такий спосіб, аби максимізувати сумарну вартість (або користь), але не перевищити максимально припустиму масу.
# --instructions--
Напишіть функцію, щоб розв'язати задачу пакування рюкзака. У параметрах функції вказуюється масив об’єктів і максимальна вага. Вона має повертати найбільше можливе значення.
# --hints--
`knapsack([{ name:'map', weight:9, value:150 }, { name:'compass', weight:13, value:35 }, { name:'water', weight:153, value:200 }, { name:'sandwich', weight:50, value:160 }, { name:'glucose', weight:15, value:60 }, { name:'tin', weight:68, value:45 }, { name:'banana', weight:27, value:60 }, { name:'apple', weight:39, value:40 }], 100)` має повертати `405`.
```js
assert.equal(
knapsack(
[
{ name: 'map', weight: 9, value: 150 },
{ name: 'compass', weight: 13, value: 35 },
{ name: 'water', weight: 153, value: 200 },
{ name: 'sandwich', weight: 50, value: 160 },
{ name: 'glucose', weight: 15, value: 60 },
{ name: 'tin', weight: 68, value: 45 },
{ name: 'banana', weight: 27, value: 60 },
{ name: 'apple', weight: 39, value: 40 }
],
100
),
405
);
```
`knapsack([{ name:'map', weight:9, value:150 }, { name:'compass', weight:13, value:35 }, { name:'water', weight:153, value:200 }, { name:'sandwich', weight:50, value:160 }, { name:'glucose', weight:15, value:60 }, { name:'tin', weight:68, value:45 }, { name:'banana', weight:27, value:60 }, { name:'apple', weight:39, value:40 }], 200)` має повертати`510`.
```js
assert.equal(
knapsack(
[
{ name: 'map', weight: 9, value: 150 },
{ name: 'compass', weight: 13, value: 35 },
{ name: 'water', weight: 153, value: 200 },
{ name: 'sandwich', weight: 50, value: 160 },
{ name: 'glucose', weight: 15, value: 60 },
{ name: 'tin', weight: 68, value: 45 },
{ name: 'banana', weight: 27, value: 60 },
{ name: 'apple', weight: 39, value: 40 }
],
200
),
510
);
```
`knapsack([{ name:'cheese', weight:23, value:30 }, { name:'beer', weight:52, value:10 }, { name:'suntan cream', weight:11, value:70 }, { name:'camera', weight:32, value:30 }, { name:'T-shirt', weight:24, value:15 }, { name:'trousers', weight:48, value:10 }, { name:'umbrella', weight:73, value:40 }], 100)` має повертати`145`.
```js
assert.equal(
knapsack(
[
{ name: 'cheese', weight: 23, value: 30 },
{ name: 'beer', weight: 52, value: 10 },
{ name: 'suntan cream', weight: 11, value: 70 },
{ name: 'camera', weight: 32, value: 30 },
{ name: 'T-shirt', weight: 24, value: 15 },
{ name: 'trousers', weight: 48, value: 10 },
{ name: 'umbrella', weight: 73, value: 40 }
],
100
),
145
);
```
`knapsack([{ name:'cheese', weight:23, value:30 }, { name:'beer', weight:52, value:10 }, { name:'suntan cream', weight:11, value:70 }, { name:'camera', weight:32, value:30 }, { name:'T-shirt', weight:24, value:15 }, { name:'trousers', weight:48, value:10 }, { name:'umbrella', weight:73, value:40 }], 200)` має повертати`185`.
```js
assert.equal(
knapsack(
[
{ name: 'cheese', weight: 23, value: 30 },
{ name: 'beer', weight: 52, value: 10 },
{ name: 'suntan cream', weight: 11, value: 70 },
{ name: 'camera', weight: 32, value: 30 },
{ name: 'T-shirt', weight: 24, value: 15 },
{ name: 'trousers', weight: 48, value: 10 },
{ name: 'umbrella', weight: 73, value: 40 }
],
200
),
185
);
```
`knapsack([{ name:'waterproof trousers', weight:42, value:70 }, { name:'waterproof overclothes', weight:43, value:75 }, { name:'note-case', weight:22, value:80 }, { name:'sunglasses', weight:7, value:20 }, { name:'towel', weight:18, value:12 }, { name:'socks', weight:4, value:50 }, { name:'book', weight:30, value:10 }], 100)` має повертати`237`.
```js
assert.equal(
knapsack(
[
{ name: 'waterproof trousers', weight: 42, value: 70 },
{ name: 'waterproof overclothes', weight: 43, value: 75 },
{ name: 'note-case', weight: 22, value: 80 },
{ name: 'sunglasses', weight: 7, value: 20 },
{ name: 'towel', weight: 18, value: 12 },
{ name: 'socks', weight: 4, value: 50 },
{ name: 'book', weight: 30, value: 10 }
],
100
),
237
);
```
`knapsack([{ name:'waterproof trousers', weight:42, value:70 }, { name:'waterproof overclothes', weight:43, value:75 }, { name:'note-case', weight:22, value:80 }, { name:'sunglasses', weight:7, value:20 }, { name:'towel', weight:18, value:12 }, { name:'socks', weight:4, value:50 }, { name:'book', weight:30, value:10 }], 200)` має повертати`317`.'
```js
assert.equal(
knapsack(
[
{ name: 'waterproof trousers', weight: 42, value: 70 },
{ name: 'waterproof overclothes', weight: 43, value: 75 },
{ name: 'note-case', weight: 22, value: 80 },
{ name: 'sunglasses', weight: 7, value: 20 },
{ name: 'towel', weight: 18, value: 12 },
{ name: 'socks', weight: 4, value: 50 },
{ name: 'book', weight: 30, value: 10 }
],
200
),
317
);
```
# --seed--
## --seed-contents--
```js
function knapsack(items, maxweight) {
}
```
# --solutions--
```js
function knapsack(items, maxweight) {
var _ = {
max: function(e) {
var mx = e[0];
e.forEach(function(f) {
if (mx < f) mx = f;
});
return mx;
},
map: function(array, func) {
return array.map(func);
},
isUndefined: function(a) {
if (a) {
return false;
}
return true;
},
range: function(start, end, step) {
var a = [];
var f = (f = (i, end) => i < end);
if (start > end) f = (i, end) => i > end;
for (var i = start; f(i, end); i += step) a.push(i);
return a;
}
};
var valuefn = e => e.value;
var weightfn = e => e.weight;
var _epsilon = 0.01;
var _p = _.max(_.map(items, valuefn));
var _k = (_epsilon * _p) / items.length;
var _memo = (function() {
var _mem = {};
var _key = function(i, w) {
return i + '::' + w;
};
return {
get: function(i, w) {
return _mem[_key(i, w)];
},
put: function(i, w, r) {
_mem[_key(i, w)] = r;
return r;
}
};
})();
var _m = function(i, w) {
i = Math.round(i);
w = Math.round(w);
if (i < 0 || w === 0) {
// empty base case
return { items: [], totalWeight: 0, totalValue: 0 };
}
var mm = _memo.get(i, w);
if (!_.isUndefined(mm)) {
return mm;
}
var item = items[i];
if (weightfn(item) > w) {
//item does not fit, try the next item
return _memo.put(i, w, _m(i - 1, w));
}
// this item could fit.
// are we better off excluding it?
var excluded = _m(i - 1, w);
// or including it?
var included = _m(i - 1, w - weightfn(item));
if (
included.totalValue + Math.floor(valuefn(item) / _k) >
excluded.totalValue
) {
// better off including it
// make a copy of the list
var i1 = included.items.slice();
i1.push(item);
return _memo.put(i, w, {
items: i1,
totalWeight: included.totalWeight + weightfn(item),
totalValue: included.totalValue + Math.floor(valuefn(item) / _k)
});
}
//better off excluding it
return _memo.put(i, w, excluded);
};
var scaled = _m(items.length - 1, maxweight);
var val = 0;
scaled.items.forEach(function(e) {
val += e.value;
});
return val;
}
```

View File

@@ -0,0 +1,212 @@
---
id: 5a23c84252665b21eecc7ed2
title: Обмежена задача пакування рюкзака
challengeType: 5
forumTopicId: 323652
dashedName: knapsack-problembounded
---
# --description--
Обмежена задача пакування:
Дано масив об'єктів, які потрібно помістити в рюкзак. Кожен об'єкти має назву, частини (кількість конкретного товару), вагу та цінність. Необхідно обрати об'єкти в такий спосіб, аби максимізувати сумарну вартість (або користь), але не перевищити максимально припустиму масу. Пам'ятайте, що кожен об'єкт може відображатися у межах 0 і `pieces` разів.
# --instructions--
Напишіть функцію, щоб розв'язати задачу пакування рюкзака. У параметрах функції вказується масив об’єктів і максимальна вагу. Вона має повернути найбільше можливе значення.
# --hints--
`findBestPack([{ name:'map', weight:9, value:150, pieces:1 }, { name:'compass', weight:13, value:35, pieces:1 }, { name:'water', weight:153, value:200, pieces:2 }, { name:'sandwich', weight:50, value:60, pieces:2 }, { name:'glucose', weight:15, value:60, pieces:2 }, { name:'tin', weight:68, value:45, pieces:3 }, { name:'banana', weight:27, value:60, pieces:3 }, { name:'apple', weight:39, value:40, pieces:3 }, { name:'cheese', weight:23, value:30, pieces:1 }, { name:'beer', weight:52, value:10, pieces:3 }, { name:'suntan, cream', weight:11, value:70, pieces:1 }, { name:'camera', weight:32, value:30, pieces:1 }, { name:'T-shirt', weight:24, value:15, pieces:2 }], 300)` має повертати`755`.
```js
assert.equal(
findBestPack(
[
{ name: 'map', weight: 9, value: 150, pieces: 1 },
{ name: 'compass', weight: 13, value: 35, pieces: 1 },
{ name: 'water', weight: 153, value: 200, pieces: 2 },
{ name: 'sandwich', weight: 50, value: 60, pieces: 2 },
{ name: 'glucose', weight: 15, value: 60, pieces: 2 },
{ name: 'tin', weight: 68, value: 45, pieces: 3 },
{ name: 'banana', weight: 27, value: 60, pieces: 3 },
{ name: 'apple', weight: 39, value: 40, pieces: 3 },
{ name: 'cheese', weight: 23, value: 30, pieces: 1 },
{ name: 'beer', weight: 52, value: 10, pieces: 3 },
{ name: 'suntan, cream', weight: 11, value: 70, pieces: 1 },
{ name: 'camera', weight: 32, value: 30, pieces: 1 },
{ name: 'T-shirt', weight: 24, value: 15, pieces: 2 }
],
300
),
755
);
```
`findBestPack([{ name:'map', weight:9, value:150, pieces:1 }, { name:'compass', weight:13, value:35, pieces:1 }, { name:'water', weight:153, value:200, pieces:2 }, { name:'sandwich', weight:50, value:60, pieces:2 }, { name:'glucose', weight:15, value:60, pieces:2 }, { name:'tin', weight:68, value:45, pieces:3 }, { name:'banana', weight:27, value:60, pieces:3 }, { name:'apple', weight:39, value:40, pieces:3 }, { name:'cheese', weight:23, value:30, pieces:1 }, { name:'beer', weight:52, value:10, pieces:3 }, { name:'suntan, cream', weight:11, value:70, pieces:1 }, { name:'camera', weight:32, value:30, pieces:1 }, { name:'T-shirt', weight:24, value:15, pieces:2 }], 400)` має повертати`875`.
```js
assert.equal(
findBestPack(
[
{ name: 'map', weight: 9, value: 150, pieces: 1 },
{ name: 'compass', weight: 13, value: 35, pieces: 1 },
{ name: 'water', weight: 153, value: 200, pieces: 2 },
{ name: 'sandwich', weight: 50, value: 60, pieces: 2 },
{ name: 'glucose', weight: 15, value: 60, pieces: 2 },
{ name: 'tin', weight: 68, value: 45, pieces: 3 },
{ name: 'banana', weight: 27, value: 60, pieces: 3 },
{ name: 'apple', weight: 39, value: 40, pieces: 3 },
{ name: 'cheese', weight: 23, value: 30, pieces: 1 },
{ name: 'beer', weight: 52, value: 10, pieces: 3 },
{ name: 'suntan, cream', weight: 11, value: 70, pieces: 1 },
{ name: 'camera', weight: 32, value: 30, pieces: 1 },
{ name: 'T-shirt', weight: 24, value: 15, pieces: 2 }
],
400
),
875
);
```
`findBestPack([{ name:'map', weight:9, value:150, pieces:1 }, { name:'compass', weight:13, value:35, pieces:1 }, { name:'water', weight:153, value:200, pieces:2 }, { name:'sandwich', weight:50, value:60, pieces:2 }, { name:'glucose', weight:15, value:60, pieces:2 }, { name:'tin', weight:68, value:45, pieces:3 }, { name:'banana', weight:27, value:60, pieces:3 }, { name:'apple', weight:39, value:40, pieces:3 }, { name:'cheese', weight:23, value:30, pieces:1 }, { name:'beer', weight:52, value:10, pieces:3 }, { name:'suntan, cream', weight:11, value:70, pieces:1 }, { name:'camera', weight:32, value:30, pieces:1 }, { name:'T-shirt', weight:24, value:15, pieces:2 }], 500)` має повертати`1015`.
```js
assert.equal(
findBestPack(
[
{ name: 'map', weight: 9, value: 150, pieces: 1 },
{ name: 'compass', weight: 13, value: 35, pieces: 1 },
{ name: 'water', weight: 153, value: 200, pieces: 2 },
{ name: 'sandwich', weight: 50, value: 60, pieces: 2 },
{ name: 'glucose', weight: 15, value: 60, pieces: 2 },
{ name: 'tin', weight: 68, value: 45, pieces: 3 },
{ name: 'banana', weight: 27, value: 60, pieces: 3 },
{ name: 'apple', weight: 39, value: 40, pieces: 3 },
{ name: 'cheese', weight: 23, value: 30, pieces: 1 },
{ name: 'beer', weight: 52, value: 10, pieces: 3 },
{ name: 'suntan, cream', weight: 11, value: 70, pieces: 1 },
{ name: 'camera', weight: 32, value: 30, pieces: 1 },
{ name: 'T-shirt', weight: 24, value: 15, pieces: 2 }
],
500
),
1015
);
```
`findBestPack([{ name:'map', weight:9, value:150, pieces:1 }, { name:'compass', weight:13, value:35, pieces:1 }, { name:'water', weight:153, value:200, pieces:2 }, { name:'sandwich', weight:50, value:60, pieces:2 }, { name:'glucose', weight:15, value:60, pieces:2 }, { name:'tin', weight:68, value:45, pieces:3 }, { name:'banana', weight:27, value:60, pieces:3 }, { name:'apple', weight:39, value:40, pieces:3 }, { name:'cheese', weight:23, value:30, pieces:1 }, { name:'beer', weight:52, value:10, pieces:3 }, { name:'suntan, cream', weight:11, value:70, pieces:1 }, { name:'camera', weight:32, value:30, pieces:1 }, { name:'T-shirt', weight:24, value:15, pieces:2 }], 600)` should return `1120`.
```js
assert.equal(
findBestPack(
[
{ name: 'map', weight: 9, value: 150, pieces: 1 },
{ name: 'compass', weight: 13, value: 35, pieces: 1 },
{ name: 'water', weight: 153, value: 200, pieces: 2 },
{ name: 'sandwich', weight: 50, value: 60, pieces: 2 },
{ name: 'glucose', weight: 15, value: 60, pieces: 2 },
{ name: 'tin', weight: 68, value: 45, pieces: 3 },
{ name: 'banana', weight: 27, value: 60, pieces: 3 },
{ name: 'apple', weight: 39, value: 40, pieces: 3 },
{ name: 'cheese', weight: 23, value: 30, pieces: 1 },
{ name: 'beer', weight: 52, value: 10, pieces: 3 },
{ name: 'suntan, cream', weight: 11, value: 70, pieces: 1 },
{ name: 'camera', weight: 32, value: 30, pieces: 1 },
{ name: 'T-shirt', weight: 24, value: 15, pieces: 2 }
],
600
),
1120
);
```
`findBestPack([{ name:'map', weight:9, value:150, pieces:1 }, { name:'compass', weight:13, value:35, pieces:1 }, { name:'water', weight:153, value:200, pieces:2 }, { name:'sandwich', weight:50, value:60, pieces:2 }, { name:'glucose', weight:15, value:60, pieces:2 }, { name:'tin', weight:68, value:45, pieces:3 }, { name:'banana', weight:27, value:60, pieces:3 }, { name:'apple', weight:39, value:40, pieces:3 }, { name:'cheese', weight:23, value:30, pieces:1 }, { name:'beer', weight:52, value:10, pieces:3 }, { name:'suntan, cream', weight:11, value:70, pieces:1 }, { name:'camera', weight:32, value:30, pieces:1 }, { name:'T-shirt', weight:24, value:15, pieces:2 }], 700)` має повертати`1225`.
```js
assert.equal(
findBestPack(
[
{ name: 'map', weight: 9, value: 150, pieces: 1 },
{ name: 'compass', weight: 13, value: 35, pieces: 1 },
{ name: 'water', weight: 153, value: 200, pieces: 2 },
{ name: 'sandwich', weight: 50, value: 60, pieces: 2 },
{ name: 'glucose', weight: 15, value: 60, pieces: 2 },
{ name: 'tin', weight: 68, value: 45, pieces: 3 },
{ name: 'banana', weight: 27, value: 60, pieces: 3 },
{ name: 'apple', weight: 39, value: 40, pieces: 3 },
{ name: 'cheese', weight: 23, value: 30, pieces: 1 },
{ name: 'beer', weight: 52, value: 10, pieces: 3 },
{ name: 'suntan, cream', weight: 11, value: 70, pieces: 1 },
{ name: 'camera', weight: 32, value: 30, pieces: 1 },
{ name: 'T-shirt', weight: 24, value: 15, pieces: 2 }
],
700
),
1225
);
```
# --seed--
## --seed-contents--
```js
function findBestPack(data, maxweight) {
}
```
# --solutions--
```js
function findBestPack(data, maxweight) {
var m = [[0]]; // maximum pack value found so far
var b = [[0]]; // best combination found so far
var opts = [0]; // item index for 0 of item 0
var P = [1]; // item encoding for 0 of item 0
var choose = 0;
for (var j = 0; j < data.length; j++) {
opts[j + 1] = opts[j] + data[j].pieces; // item index for 0 of item j+1
P[j + 1] = P[j] * (1 + data[j].pieces); // item encoding for 0 of item j+1
}
for (var j = 0; j < opts[data.length]; j++) {
m[0][j + 1] = b[0][j + 1] = 0; // best values and combos for empty pack: nothing
}
for (var w = 1; w <= maxweight; w++) {
m[w] = [0];
b[w] = [0];
for (var j = 0; j < data.length; j++) {
var N = data[j].pieces; // how many of these can we have?
var base = opts[j]; // what is the item index for 0 of these?
for (var n = 1; n <= N; n++) {
var W = n * data[j].weight; // how much do these items weigh?
var s = w >= W ? 1 : 0; // can we carry this many?
var v = s * n * data[j].value; // how much are they worth?
var I = base + n; // what is the item number for this many?
var wN = w - s * W; // how much other stuff can we be carrying?
var C = n * P[j] + b[wN][base]; // encoded combination
m[w][I] = Math.max(m[w][I - 1], v + m[wN][base]); // best value
choose = b[w][I] = m[w][I] > m[w][I - 1] ? C : b[w][I - 1];
}
}
}
var best = [];
for (var j = data.length - 1; j >= 0; j--) {
best[j] = Math.floor(choose / P[j]);
choose -= best[j] * P[j];
}
var wgt = 0;
var val = 0;
for (var i = 0; i < best.length; i++) {
if (0 == best[i]) continue;
wgt += best[i] * data[i].weight;
val += best[i] * data[i].value;
}
return val;
}
```

View File

@@ -0,0 +1,169 @@
---
id: 5a23c84252665b21eecc7ed3
title: Задача пакування рюкзака/Безперервна
challengeType: 5
forumTopicId: 323654
dashedName: knapsack-problemcontinuous
---
# --description--
Злодій грабує м'ясну лавку і може вибрати декілька предметів.
Злодій знає вагу і ціну кожного предмета. Оскільки його рюкзак має обмеження максимальної ваги, він хоче вибрати предмети так, щоб отримати максимальний прибуток. Він може розрізати предмети; після різання ціна товару знизиться пропорційно початковій ціні за співвідношенням мас. Тобто половина товару коштуватиме вдвічі дешевше від початкової вартості.
# --instructions--
Напишіть функцію, яка приймає масив об'єктів, що становлять товари, доступні в магазині. Кожен об'єкт має назву, вагу та вартість. У параметрах функції також вказується максимальна вага. Функція повинна повернути максимально можливе значення, а загальна вага вибраних елементів не повинна перевищувати максимальну вагу.
# --hints--
`knapContinuous([{ "weight":3.8, "value":36, name:"beef" }, { "weight":5.4, "value":43, name:"pork" }, { "weight":3.6, "value":90, name:"ham" }, { "weight":2.4, "value":45, name:"greaves" }, { "weight":4.0, "value":30, name:"flitch" }, { "weight":2.5, "value":56, name:"brawn" }, { "weight":3.7, "value":67, name:"welt" }, { "weight":3.0, "value":95, name:"salami" }, { "weight":5.9, "value":98, name:"sausage" }], 10)` має повертати`257.875`.
```js
assert.equal(
knapContinuous(
[
{ weight: 3.8, value: 36, name: 'beef' },
{ weight: 5.4, value: 43, name: 'pork' },
{ weight: 3.6, value: 90, name: 'ham' },
{ weight: 2.4, value: 45, name: 'greaves' },
{ weight: 4.0, value: 30, name: 'flitch' },
{ weight: 2.5, value: 56, name: 'brawn' },
{ weight: 3.7, value: 67, name: 'welt' },
{ weight: 3.0, value: 95, name: 'salami' },
{ weight: 5.9, value: 98, name: 'sausage' }
],
10
),
257.875
);
```
`knapContinuous([{ "weight":3.8, "value":36, name:"beef" }, { "weight":5.4, "value":43, name:"pork" }, { "weight":3.6, "value":90, name:"ham" }, { "weight":2.4, "value":45, name:"greaves" }, { "weight":4.0, "value":30, name:"flitch" }, { "weight":2.5, "value":56, name:"brawn" }, { "weight":3.7, "value":67, name:"welt" }, { "weight":3.0, "value":95, name:"salami" }, { "weight":5.9, "value":98, name:"sausage" }], 12)` має повертати`295.05405405405406`.
```js
assert.equal(
knapContinuous(
[
{ weight: 3.8, value: 36, name: 'beef' },
{ weight: 5.4, value: 43, name: 'pork' },
{ weight: 3.6, value: 90, name: 'ham' },
{ weight: 2.4, value: 45, name: 'greaves' },
{ weight: 4.0, value: 30, name: 'flitch' },
{ weight: 2.5, value: 56, name: 'brawn' },
{ weight: 3.7, value: 67, name: 'welt' },
{ weight: 3.0, value: 95, name: 'salami' },
{ weight: 5.9, value: 98, name: 'sausage' }
],
12
),
295.05405405405406
);
```
`knapContinuous([{ "weight":3.8, "value":36, name:"beef" }, { "weight":5.4, "value":43, name:"pork" }, { "weight":3.6, "value":90, name:"ham" }, { "weight":2.4, "value":45, name:"greaves" }, { "weight":4.0, "value":30, name:"flitch" }, { "weight":2.5, "value":56, name:"brawn" }, { "weight":3.7, "value":67, name:"welt" }, { "weight":3.0, "value":95, name:"salami" }, { "weight":5.9, "value":98, name:"sausage" }], 15)` має повертати`349.3783783783784`.
```js
assert.equal(
knapContinuous(
[
{ weight: 3.8, value: 36, name: 'beef' },
{ weight: 5.4, value: 43, name: 'pork' },
{ weight: 3.6, value: 90, name: 'ham' },
{ weight: 2.4, value: 45, name: 'greaves' },
{ weight: 4.0, value: 30, name: 'flitch' },
{ weight: 2.5, value: 56, name: 'brawn' },
{ weight: 3.7, value: 67, name: 'welt' },
{ weight: 3.0, value: 95, name: 'salami' },
{ weight: 5.9, value: 98, name: 'sausage' }
],
15
),
349.3783783783784
);
```
`knapContinuous([{ "weight":3.8, "value":36, name:"beef" }, { "weight":5.4, "value":43, name:"pork" }, { "weight":3.6, "value":90, name:"ham" }, { "weight":2.4, "value":45, name:"greaves" }, { "weight":4.0, "value":30, name:"flitch" }, { "weight":2.5, "value":56, name:"brawn" }, { "weight":3.7, "value":67, name:"welt" }, { "weight":3.0, "value":95, name:"salami" }, { "weight":5.9, "value":98, name:"sausage" }], 22)` має повертати`459.5263157894737`.
```js
assert.equal(
knapContinuous(
[
{ weight: 3.8, value: 36, name: 'beef' },
{ weight: 5.4, value: 43, name: 'pork' },
{ weight: 3.6, value: 90, name: 'ham' },
{ weight: 2.4, value: 45, name: 'greaves' },
{ weight: 4.0, value: 30, name: 'flitch' },
{ weight: 2.5, value: 56, name: 'brawn' },
{ weight: 3.7, value: 67, name: 'welt' },
{ weight: 3.0, value: 95, name: 'salami' },
{ weight: 5.9, value: 98, name: 'sausage' }
],
22
),
459.5263157894737
);
```
`knapContinuous([{ "weight":3.8, "value":36, name:"beef" }, { "weight":5.4, "value":43, name:"pork" }, { "weight":3.6, "value":90, name:"ham" }, { "weight":2.4, "value":45, name:"greaves" }, { "weight":4.0, "value":30, name:"flitch" }, { "weight":2.5, "value":56, name:"brawn" }, { "weight":3.7, "value":67, name:"welt" }, { "weight":3.0, "value":95, name:"salami" }, { "weight":5.9, "value":98, name:"sausage" }], 24)` має повертати`478.4736842105263`.
```js
assert.equal(
knapContinuous(
[
{ weight: 3.8, value: 36, name: 'beef' },
{ weight: 5.4, value: 43, name: 'pork' },
{ weight: 3.6, value: 90, name: 'ham' },
{ weight: 2.4, value: 45, name: 'greaves' },
{ weight: 4.0, value: 30, name: 'flitch' },
{ weight: 2.5, value: 56, name: 'brawn' },
{ weight: 3.7, value: 67, name: 'welt' },
{ weight: 3.0, value: 95, name: 'salami' },
{ weight: 5.9, value: 98, name: 'sausage' }
],
24
),
478.4736842105263
);
```
# --seed--
## --seed-contents--
```js
function knapContinuous(items, maxweight) {
}
```
# --solutions--
```js
function knapContinuous(items, maxweight) {
function item_cmp(a, b) {
const ua = a.unitVal,
ub = b.unitVal;
return ua < ub ? 1 : ua > ub ? -1 : 0;
}
items = items.map(({ value, weight }) => ({
unitVal: value / weight,
weight
}));
items.sort(item_cmp);
let val = 0;
let wt = 0;
for (let { unitVal, weight } of items) {
var portion = Math.min(maxweight - wt, weight);
wt += portion;
var addVal = portion * unitVal;
val += addVal;
if (wt >= maxweight) {
break;
}
}
return val;
}
```

View File

@@ -0,0 +1,185 @@
---
id: 5a23c84252665b21eecc7ed4
title: Задача пакування рюкзака/Необмежена
challengeType: 5
forumTopicId: 323655
dashedName: knapsack-problemunbounded
---
# --description--
Мандрівник змінює курс і змушений зробити незаплановану зупинку Шангрі-Ла. Перед від'їздом йому дозволили взяти стільки предметів, скільки захоче, за умови, що вибрані предмети помістяться в його рюкзак, і він зможе його нести.
Він знає максимальну вагу, яку зможе нести; і, що об'єм рюкзака обмежений.
Над штрих-кодами предметів написана їх вага та об'єм. Він витягує свою останню копію фінансового звіту та дізнається ціну кожного предмету.
Йому можна брати лише цілі предмети, і їх є набагато більше, ніж він би зміг нести.
# --instructions--
Напишіть функцію, а у її параметрах вкажіть масив об'єктів, максимальну вагу та максимальний об'єм. Кожен об'єкт має назву, вартість, вагу та об'єм. Функція має повернути максимальне значення предметів, які мандрівник може взяти з собою.
# --hints--
`knapsackUnbounded([{ name:"panacea", value:3000, weight:0.3, volume:0.025 }, { name:"ichor", value:1800, weight:0.2, volume:0.015 }, { name:"gold", value:2500, weight:2, volume:0.002 }], 25, 0.25)` має повертати `54500`.
```js
assert.equal(
knapsackUnbounded(
[
{ name: 'panacea', value: 3000, weight: 0.3, volume: 0.025 },
{ name: 'ichor', value: 1800, weight: 0.2, volume: 0.015 },
{ name: 'gold', value: 2500, weight: 2, volume: 0.002 }
],
25,
0.25
),
54500
);
```
`knapsackUnbounded([{ name:"panacea", value:3000, weight:0.3, volume:0.025 }, { name:"ichor", value:1800, weight:0.2, volume:0.015 }, { name:"gold", value:2500, weight:2, volume:0.002 }], 55, 0.25)` має повертати `88400`.
```js
assert.equal(
knapsackUnbounded(
[
{ name: 'panacea', value: 3000, weight: 0.3, volume: 0.025 },
{ name: 'ichor', value: 1800, weight: 0.2, volume: 0.015 },
{ name: 'gold', value: 2500, weight: 2, volume: 0.002 }
],
55,
0.25
),
88400
);
```
`knapsackUnbounded([{ name:"panacea", value:3000, weight:0.3, volume:0.025 }, { name:"ichor", value:1800, weight:0.2, volume:0.015 }, { name:"gold", value:2500, weight:2, volume:0.002 }], 25, 0.15)` має повертати `42500`.
```js
assert.equal(
knapsackUnbounded(
[
{ name: 'panacea', value: 3000, weight: 0.3, volume: 0.025 },
{ name: 'ichor', value: 1800, weight: 0.2, volume: 0.015 },
{ name: 'gold', value: 2500, weight: 2, volume: 0.002 }
],
25,
0.15
),
42500
);
```
`knapsackUnbounded([{ name:"panacea", value:3000, weight:0.3, volume:0.025 }, { name:"ichor", value:1800, weight:0.2, volume:0.015 }, { name:"gold", value:2500, weight:2, volume:0.002 }], 35, 0.35)` має повертати `75900`.
```js
assert.equal(
knapsackUnbounded(
[
{ name: 'panacea', value: 3000, weight: 0.3, volume: 0.025 },
{ name: 'ichor', value: 1800, weight: 0.2, volume: 0.015 },
{ name: 'gold', value: 2500, weight: 2, volume: 0.002 }
],
35,
0.35
),
75900
);
```
`knapsackUnbounded([{ name:"panacea", value:3000, weight:0.3, volume:0.025 }, { name:"ichor", value:1800, weight:0.2, volume:0.015 }, { name:"gold", value:2500, weight:2, volume:0.002 }], 15, 0.25)` має повертати`43200`.
```js
assert.equal(
knapsackUnbounded(
[
{ name: 'panacea', value: 3000, weight: 0.3, volume: 0.025 },
{ name: 'ichor', value: 1800, weight: 0.2, volume: 0.015 },
{ name: 'gold', value: 2500, weight: 2, volume: 0.002 }
],
15,
0.25
),
43200
);
```
# --seed--
## --seed-contents--
```js
function knapsackUnbounded(items, maxweight, maxvolume) {
}
```
# --solutions--
```js
function knapsackUnbounded(items, maxWeight, maxVolume) {
function getPickTotals(items, pick) {
let totalValue = 0;
let totalWeight = 0;
let totalVolume = 0;
for (let i = 0; i < items.length; i++) {
totalValue += pick[i] * items[i].value;
totalWeight += pick[i] * items[i].weight;
totalVolume += pick[i] * items[i].volume;
}
return [totalValue, totalWeight, totalVolume];
}
function getMaxes(items, maxWeight, maxVolume) {
const maxes = [];
for (let i = 0; i < items.length; i++) {
const maxUnitsInWeight = Math.floor(maxWeight / items[i].weight);
const maxUnitsInVolume = Math.floor(maxVolume / items[i].volume);
const maxUnitsInLimit = Math.min(maxUnitsInWeight, maxUnitsInVolume);
maxes.push(maxUnitsInLimit);
}
return maxes;
}
function isInLimit(value, limit) {
return value <= limit;
}
function getCombinations(maxValues, curPicks, combinations) {
if (maxValues.length === 0) {
combinations.push(curPicks);
}
const curMax = maxValues[0];
const leftMaxValues = maxValues.slice(1);
for (let i = 0; i <= curMax; i++) {
getCombinations(leftMaxValues, curPicks.concat(i), combinations);
}
return combinations;
}
let bestValue = 0;
let bestPick = [];
const maxes = getMaxes(items, maxWeight, maxVolume);
const combinations = getCombinations(maxes, [], []);
for (let i = 0; i < combinations.length; i++) {
const curPick = combinations[i];
const [curValue, curWeight, curVolume] = getPickTotals(items, curPick);
if (!isInLimit(curWeight, maxWeight) || !isInLimit(curVolume, maxVolume)) {
continue;
}
if (curValue > bestValue) {
bestValue = curValue;
bestPick = [curPick];
} else if (curValue === bestValue) {
bestPick.push(curPick);
}
}
return bestValue;
}
```

View File

@@ -0,0 +1,225 @@
---
id: 5a23c84252665b21eecc7ed5
title: Задача про хід коня
challengeType: 5
forumTopicId: 302297
dashedName: knights-tour
---
# --description--
[Knight's Tour](https://en.wikipedia.org/wiki/Knight%27s_tour) Задача: У вас є порожня `w` \* `h` шахівниця з одним конем на якомусь полі. Кінь повинен виконати послідовність ходів таким чином, щоб побувати на кожному полі шахівниці лише раз. Зауважте, що йому *не* не обов'язково пройти весь маршрут, а отже кінь не повинен закінчити гру, зробивши один хід від початкової позиції.
# --instructions--
Напишіть функцію, яка бере `w` і `h` як параметри й повертає кількість початкових позицій звідти, де можливо виконати завдання, про яке йшлося вище.
# --hints--
`knightTour` повинен бути функцією.
```js
assert(typeof knightTour == 'function');
```
`knightTour(6, 6)` повинен повернути число.
```js
assert(typeof knightTour(6, 6) == 'number');
```
`knightTour(6, 6)` повинен повернути `36`.
```js
assert.equal(knightTour(6, 6), 36);
```
`knightTour(5, 6)`повинен повернути `30`.
```js
assert.equal(knightTour(5, 6), 30);
```
`knightTour(4, 6)` повинен повернути. `12`.
```js
assert.equal(knightTour(4, 6), 12);
```
`knightTour(7, 3)` повинен повернути `10`.
```js
assert.equal(knightTour(7, 3), 10);
```
`knightTour(8, 6)` повинен повернути `48`.
```js
assert.equal(knightTour(8, 6), 48);
```
# --seed--
## --seed-contents--
```js
function knightTour(w, h) {
}
```
# --solutions--
```js
function knightTour(w, h) {
function createBoards(rows, columns) {
const board = [];
const visited = [];
for (let i = 0; i < rows; i++) {
board.push(new Array(columns).fill(-1));
visited.push(new Array(columns).fill(false));
}
return [board, visited];
}
function copyBoard(board) {
const copied = [];
for (let i = 0; i < board.length; i++) {
copied.push([...board[i]]);
}
return copied;
}
function isOnBoard(value, limit) {
return value >= 0 && value < limit;
}
function markVisited(board, visited, row, column) {
visited[row][column] = true;
board[row][column] = -1;
}
function areAllVisited(visited) {
return (
visited.filter(row => row.filter(column => column === false).length !== 0)
.length === 0
);
}
function getMovesFrom(board, row, column) {
const possibleMoves = [];
for (let i = 0; i < moves.length; i++) {
const [rowChange, colChange] = moves[i];
const [rowN, colN] = [row + rowChange, column + colChange];
if (!isOnBoard(rowN, board.length) || !isOnBoard(colN, board[0].length)) {
continue;
}
possibleMoves.push([rowN, colN]);
}
return possibleMoves;
}
function fillAllowedMovesCounts(board) {
for (let row = 0; row < board.length; row++) {
for (let column = 0; column < board[0].length; column++) {
board[row][column] = getMovesFrom(board, row, column).length;
}
}
}
function updateAllowedMovesCounts(board, possibleMoves) {
for (let i = 0; i < possibleMoves.length; i++) {
const [row, column] = possibleMoves[i];
if (board[row][column] > 0) {
board[row][column]--;
}
}
}
function getBestNextMoves(board, allowedMoves) {
let bestMoves = [];
let fewestNextMoves = Infinity;
let zeroMove = [];
for (let i = 0; i < allowedMoves.length; i++) {
const [moveRow, moveCol] = allowedMoves[i];
const numMoves = board[moveRow][moveCol];
if (numMoves === -1) {
continue;
}
if (numMoves === 0) {
zeroMove.push(allowedMoves[i]);
}
if (numMoves < fewestNextMoves) {
bestMoves = [allowedMoves[i]];
fewestNextMoves = numMoves;
} else if (numMoves === fewestNextMoves) {
bestMoves.push(allowedMoves[i]);
}
}
if (bestMoves.length > 0) {
return bestMoves;
}
return zeroMove;
}
function solve(board, visited, lastRow, lastColumn) {
if (areAllVisited(visited)) {
return true;
}
const nextMoves = getMovesFrom(board, lastRow, lastColumn);
updateAllowedMovesCounts(board, nextMoves);
const allowedMoves = nextMoves.filter(
([row, column]) => !visited[row][column]
);
const bestMoves = getBestNextMoves(board, allowedMoves);
const restMoves = allowedMoves.filter(
move => bestMoves.indexOf(move) === -1
);
const possibleMoves = [...bestMoves];
possibleMoves.push(...getBestNextMoves(board, restMoves));
for (let i = 0; i < possibleMoves.length; i++) {
const [moveRow, moveCol] = possibleMoves[i];
const newBoard = copyBoard(board);
const newVisited = copyBoard(visited);
markVisited(newBoard, newVisited, moveRow, moveCol);
if (solve(newBoard, newVisited, moveRow, moveCol)) {
return true;
}
}
return false;
}
function solveStart(board, visited, startRow, startColumn) {
const newBoard = copyBoard(board);
const newVisited = copyBoard(visited);
markVisited(newBoard, newVisited, startRow, startColumn);
return solve(newBoard, newVisited, startRow, startColumn);
}
const moves = [
[-1, -2],
[-2, -1],
[-2, 1],
[-1, 2],
[1, 2],
[2, 1],
[2, -1],
[1, -2]
];
const [baseBoard, baseVisited] = createBoards(h, w);
fillAllowedMovesCounts(baseBoard);
let solvedCount = 0;
for (let row = 0; row < h; row++) {
for (let column = 0; column < w; column++) {
if (solveStart(baseBoard, baseVisited, row, column)) {
solvedCount++;
}
}
}
return solvedCount;
}
```

View File

@@ -0,0 +1,85 @@
---
id: 5a23c84252665b21eecc7edb
title: Найбільше ціле число з об'єднаних цілих чисел
challengeType: 5
forumTopicId: 302298
dashedName: largest-int-from-concatenated-ints
---
# --description--
Дано множину додатних цілих чисел, напишіть функцію для впорядкування цілих чисел таким чином, щоб конкатенація чисел утворила найбільше можливе ціле число і повернула це ціле число.
# --hints--
`maxCombine` має бути функцією.
```js
assert(typeof maxCombine == 'function');
```
`maxCombine([1, 3, 3, 4, 55])` має повернути число.
```js
assert(typeof maxCombine([1, 3, 3, 4, 55]) == 'number');
```
`maxCombine([1, 3, 3, 4, 55])` має повернути `554331`.
```js
assert.equal(maxCombine([1, 3, 3, 4, 55]), 554331);
```
`maxCombine([71, 45, 23, 4, 5])` має повернути `71545423`.
```js
assert.equal(maxCombine([71, 45, 23, 4, 5]), 71545423);
```
`maxCombine([14, 43, 53, 114, 55])` має повернути `55534314114`.
```js
assert.equal(maxCombine([14, 43, 53, 114, 55]), 55534314114);
```
`maxCombine([1, 34, 3, 98, 9, 76, 45, 4])` має повернути `998764543431`.
```js
assert.equal(maxCombine([1, 34, 3, 98, 9, 76, 45, 4]), 998764543431);
```
`maxCombine([54, 546, 548, 60])` має повернути `6054854654`.
```js
assert.equal(maxCombine([54, 546, 548, 60]), 6054854654);
```
# --seed--
## --seed-contents--
```js
function maxCombine(xs) {
}
```
# --solutions--
```js
function maxCombine(xs) {
return parseInt(
xs
.sort(function(x, y) {
var a = x.toString(),
b = y.toString(),
ab = parseInt(a + b),
ba = parseInt(b + a);
return ab > ba ? -1 : ab < ba ? 1 : 0;
})
.join(''),
10
);
}
```

View File

@@ -0,0 +1,99 @@
---
id: 5a23c84252665b21eecc7edc
title: Остання п'ятниця кожного місяця
challengeType: 5
forumTopicId: 302299
dashedName: last-friday-of-each-month
---
# --description--
Напишіть функцію, яка видає дату останньої п'ятниці конкретного місяця за певний рік.
# --hints--
`lastFriday` повинен бути функцією.
```js
assert(typeof lastFriday == 'function');
```
`lastFriday(2018, 1)` повинен видавати число.
```js
assert(typeof lastFriday(2018, 1) == 'number');
```
`lastFriday(2018, 1)` повинен видавати `26`.
```js
assert.equal(lastFriday(2018, 1), 26);
```
`lastFriday(2017, 2)` повинен видавати `24`.
```js
assert.equal(lastFriday(2017, 2), 24);
```
`lastFriday(2012, 3)` повинен видавати `30`.
```js
assert.equal(lastFriday(2012, 3), 30);
```
`lastFriday(1900, 4)` повинен видавати `27`.
```js
assert.equal(lastFriday(1900, 4), 27);
```
`lastFriday(2000, 5)` повинен видавати `26`.
```js
assert.equal(lastFriday(2000, 5), 26);
```
`lastFriday(2006, 6)` повинен видавати `30`.
```js
assert.equal(lastFriday(2006, 6), 30);
```
`lastFriday(2010, 7)` повинен видавати `30`.
```js
assert.equal(lastFriday(2010, 7), 30);
```
`lastFriday(2005, 8)` повинен видавати `26`.
```js
assert.equal(lastFriday(2005, 8), 26);
```
# --seed--
## --seed-contents--
```js
function lastFriday(year, month) {
}
```
# --solutions--
```js
function lastFriday(year, month) {
var i, last_day;
i = 0;
while (true) {
last_day = new Date(year, month, i);
if (last_day.getDay() === 5) {
return last_day.getDate();
}
i -= 1;
}
}
```

View File

@@ -0,0 +1,211 @@
---
id: 5e4ce2b6ac708cc68c1df25e
title: Остання літера-перша літера
challengeType: 5
forumTopicId: 385256
dashedName: last-letter-first-letter
---
# --description--
Одна дитяча гра розпочинається зі слова в певній категорії. Кожен учасник по черзі каже слово, що починається на останню літеру попереднього слова. Якщо слово вже назвали, повторювати його не можна. Якщо суперник не може назвати слово з певної категорії, він вибуває з гри.
Нижче наведений приклад категорії "тварини",
<pre>Дитина 1: dog (собака)
Дитина 2: goldfish (золота рибка)
Дитина 1: hippopotamus (бегемот)
Дитина 2: snake (змія)
...
</pre>
# --instructions--
Напишіть функцію, яка охоплює вхідний масив слів. Функція повинна видавати масив слів, в яких перша літера кожного слова така ж сама, як остання літера попереднього слова. Використовуйте лише слова з вхідного масиву, і якщо слово було використане, то повторювати його не можна. Слова в масиві видачі слід вибирати та впорядковувати таким чином, щоб вони були якомога довшими.
# --hints--
`findLongestChain` повинен бути функцією.
```js
assert(typeof findLongestChain == 'function');
```
`findLongestChain(["certain", "each", "game", "involves", "starting", "with", "word"])` повинен видавати масив.
```js
assert(
Array.isArray(
findLongestChain([
'certain',
'each',
'game',
'involves',
'starting',
'with',
'word'
])
)
);
```
`findLongestChain(["certain", "each", "game", "involves", "starting", "with", "word"])` повинен видавати `["involves", "starting", "game", "each"]`.
```js
assert.deepEqual(
findLongestChain([
'certain',
'each',
'game',
'involves',
'starting',
'with',
'word'
]),
['involves', 'starting', 'game', 'each']
);
```
`findLongestChain(["audino", "bagon", "kangaskhan", "banette", "bidoof", "braviary", "exeggcute", "yamask"])` повинен видавати `["braviary", "yamask", "kangaskhan"]`
```js
assert.deepEqual(
findLongestChain([
'audino',
'bagon',
'kangaskhan',
'banette',
'bidoof',
'braviary',
'exeggcute',
'yamask'
]),
['braviary', 'yamask', 'kangaskhan']
);
```
`findLongestChain(["harp", "poliwrath", "poochyena", "porygon2", "porygonz", "archana"])` повинен видавати `["poliwrath", "harp", "poochyena", "archana"]`.
```js
assert.deepEqual(
findLongestChain([
'harp',
'poliwrath',
'poochyena',
'porygon2',
'porygonz',
'archana'
]),
['poliwrath', 'harp', 'poochyena', 'archana']
);
```
`findLongestChain(["scolipede", "elephant", "zeaking", "sealeo", "silcoon", "tigers"])` повинен видавати `["scolipede", "elephant", "tigers", "sealeo"]`.
```js
assert.deepEqual(
findLongestChain([
'scolipede',
'elephant',
'zeaking',
'sealeo',
'silcoon',
'tigers'
]),
['scolipede', 'elephant', 'tigers', 'sealeo']
);
```
`findLongestChain(["loudred", "lumineon", "lunatone", "machamp", "magnezone", "nosepass", "petilil", "pidgeotto", "pikachu"])` повинен видавати `["machamp", "petilil", "lumineon", "nosepass"]`.
```js
assert.deepEqual(
findLongestChain([
'loudred',
'lumineon',
'lunatone',
'machamp',
'magnezone',
'nosepass',
'petilil',
'pidgeotto',
'pikachu'
]),
['machamp', 'petilil', 'lumineon', 'nosepass']
);
```
# --seed--
## --seed-contents--
```js
function findLongestChain(items) {
}
```
# --solutions--
```js
function findLongestChain(items) {
function Ref(index, first_char, last_char) {
this.index = index;
this.first_char = first_char;
this.last_char = last_char;
}
var items_len = items.length
var refs_len = items_len;
var refs = []
// enough space for all items
var longest_path_refs_len = 0;
var longest_path_refs = new Array(items_len);
function search(curr_len) {
if (curr_len > longest_path_refs_len) {
longest_path_refs_len = curr_len;
for (var i = 0; i < curr_len; i++) {
longest_path_refs[i] = refs[i];
}
}
// recursive search
var last_char = refs[curr_len - 1].last_char;
for (var i = curr_len; i < refs_len; i++)
if (refs[i].first_char == last_char) {
var aux = refs[curr_len];
refs[curr_len] = refs[i];
refs[i] = aux;
search(curr_len + 1);
refs[i] = refs[curr_len];
refs[curr_len] = aux;
}
}
for (var i = 0; i < items_len; i++) {
var itemsi_len = items[i].length;
refs.push(new Ref(i, items[i][0], items[i][itemsi_len - 1]));
}
// try each item as possible start
for (var i = 0; i < items_len; i++) {
var aux = refs[0];
refs[0] = refs[i];
refs[i] = aux;
search(1);
refs[i] = refs[0];
refs[0] = aux;
}
var longest_path_len = longest_path_refs_len;
var longest_path = new Array(longest_path_len);
for (var i = 0; i < longest_path_len; i++)
longest_path[i] = items[longest_path_refs[i].index];
return longest_path;
}
```

View File

@@ -0,0 +1,79 @@
---
id: 5a23c84252665b21eecc7ede
title: Високосний рік
challengeType: 5
forumTopicId: 302300
dashedName: leap-year
---
# --description--
Визначте, чи конкретний рік є високосним роком у григоріанському календарі.
# --hints--
`isLeapYear` повинен бути функцією.
```js
assert(typeof isLeapYear == 'function');
```
`isLeapYear()` повинен повертати логічний тип.
```js
assert(typeof isLeapYear(2018) == 'boolean');
```
`isLeapYear(2018)` повинен повернути `false`.
```js
assert.equal(isLeapYear(2018), false);
```
`isLeapYear(2016)` повинен повернути `true`.
```js
assert.equal(isLeapYear(2016), true);
```
`isLeapYear(2000)` повинен повернути `true`.
```js
assert.equal(isLeapYear(2000), true);
```
`isLeapYear(1900)` повинен повернути `false`.
```js
assert.equal(isLeapYear(1900), false);
```
`isLeapYear(1996)` повинен повернути `true`.
```js
assert.equal(isLeapYear(1996), true);
```
`isLeapYear(1800)` повинен повернути `false`.
```js
assert.equal(isLeapYear(1800), false);
```
# --seed--
## --seed-contents--
```js
function isLeapYear(year) {
}
```
# --solutions--
```js
function isLeapYear(year) {
return year % 100 === 0 ? year % 400 === 0 : year % 4 === 0;
}
```

View File

@@ -0,0 +1,87 @@
---
id: 5a23c84252665b21eecc7edf
title: Найменше спільне кратне
challengeType: 5
forumTopicId: 302301
dashedName: least-common-multiple
---
# --description--
Найменше спільне кратне 12 та 18 це 36, оскільки 12 - коефіцієнт (12 × 3 = 36), та 18 - коефіцієнт (18 × 2 = 36), і немає цілого додатного числа менше ніж 36, яке мало б обидва коефіцієнти. В окремому випадку, якщо *m* або *n* дорівнює нулю, то найменше спільне кратне дорівнює нулю. Одним зі способів обчислення найменшого спільного кратного є повторення всіх кратних *m*, доки не буде знайдено таке, що є кратним *n*. Якщо у вас вже є *gcd* для [greatest common divisor](https://rosettacode.org/wiki/greatest common divisor), в такому випадку ця формула вираховує *lcm*. ( \\operatorname{lcm}(m, n) = \\frac{|m \\times n|}{\\operatorname{gcd}(m, n)} )
# --instructions--
Обчисліть найменше спільне кратне масиву цілих чисел. З огляду на значення *m* та *n*, найменше спільне кратне - це найменше позитивне ціле число, яке має як *m*, так і *n* у якості факторів.
# --hints--
`LCM` має бути функцією.
```js
assert(typeof LCM == 'function');
```
`LCM([2, 4, 8])` має повернути число.
```js
assert(typeof LCM([2, 4, 8]) == 'number');
```
`LCM([2, 4, 8])` має повертати `8`.
```js
assert.equal(LCM([2, 4, 8]), 8);
```
`LCM([4, 8, 12])` має повертати `24`.
```js
assert.equal(LCM([4, 8, 12]), 24);
```
`LCM([3, 4, 5, 12, 40])` має повертати `120`.
```js
assert.equal(LCM([3, 4, 5, 12, 40]), 120);
```
`LCM([11, 33, 90])` має повертати `990`.
```js
assert.equal(LCM([11, 33, 90]), 990);
```
`LCM([-50, 25, -45, -18, 90, 447])` має повертати `67050`.
```js
assert.equal(LCM([-50, 25, -45, -18, 90, 447]), 67050);
```
# --seed--
## --seed-contents--
```js
function LCM(A) {
}
```
# --solutions--
```js
function LCM(A) {
var n = A.length,
a = Math.abs(A[0]);
for (var i = 1; i < n; i++) {
var b = Math.abs(A[i]),
c = a;
while (a && b) {
a > b ? (a %= b) : (b %= a);
}
a = Math.abs(c * A[i]) / (a + b);
}
return a;
}
```

View File

@@ -0,0 +1,115 @@
---
id: 5a23c84252665b21eecc7ee0
title: Ліві факторіали
challengeType: 5
forumTopicId: 302302
dashedName: left-factorials
---
# --description--
**Ліві факторіали**, $ !n $, можуть посилатися як на *субфакторіали*, так і на *факторіальні суми*. Можна заплутатися, побачивши, що одне і те ж позначення використовується для двох різних визначень. Іноді *субфакторіали* (також відомі як *перестановки*) можуть використовувати будь-яке з цих позначень:
<ul>
<li>$!n`$</li>
<li>$!n$</li>
<li>$n¡$</li>
</ul>
(Можливо, візуально це не очевидно, але в останньому прикладі використовується перевернутий знак оклику) У цьому завданні буде використовуватися дана формула для **лівого факторіала**:
$ !n = \\sum\_{k=0}^{n-1} k! $
де $!0 = 0$
# --instructions--
Напишіть функцію для обчислення лівого факторіала заданого числа.
# --hints--
`leftFactorial` має бути функцією.
```js
assert(typeof leftFactorial == 'function');
```
`leftFactorial(0)` має повернути число.
```js
assert(typeof leftFactorial(0) == 'number');
```
`leftFactorial(0)` має повернути `0`.
```js
assert.equal(leftFactorial(0), 0);
```
`leftFactorial(1)` має повернути `1`.
```js
assert.equal(leftFactorial(1), 1);
```
`leftFactorial(2)` має повернути `2`.
```js
assert.equal(leftFactorial(2), 2);
```
`leftFactorial(3)` має повернути `4`.
```js
assert.equal(leftFactorial(3), 4);
```
`leftFactorial(10)` має повернути `409114`.
```js
assert.equal(leftFactorial(10), 409114);
```
`leftFactorial(17)` має повернути `22324392524314`.
```js
assert.equal(leftFactorial(17), 22324392524314);
```
`leftFactorial(19)` має повернути `6780385526348314`.
```js
assert.equal(leftFactorial(19), 6780385526348314);
```
# --seed--
## --seed-contents--
```js
function leftFactorial(n) {
}
```
# --solutions--
```js
function leftFactorial(n) {
if (n == 0) return 0;
if (n == 1) return 1;
// Note: for n>=20, the result may not be correct.
// This is because JavaScript uses 53 bit integers and
// for n>=20 result becomes too large.
let res = 2,
fact = 2;
for (var i = 2; i < n; i++) {
res += fact;
fact *= i + 1;
}
return res;
}
```

View File

@@ -0,0 +1,209 @@
---
id: 5e4ce2bbac708cc68c1df25f
title: Частототність
challengeType: 5
forumTopicId: 385263
dashedName: letter-frequency
---
# --description--
Обчисліть частоту кожного символу у даному рядку.
Потрібно порахувати всі символи. Включаючи малі та великі літери, цифри, пробіли, спеціальні символи або будь-який інший роздільний символ.
# --instructions--
Напишіть функцію для підрахунку всіх символів, які входять у даний рядок.
Функція повинна повертати 2D масив, де кожен із елементів має бути записаний у такій формі: `['char', freq]`. Символ має бути рядком із довжиною 1, а freq - числом, що позначає кількість цих символів.
Наприклад, дано рядок "ab", то ваша функція повинна повертати `[['a', 1], ['b', 1]]`.
# --hints--
`letterFrequency` має бути функцією.
```js
assert(typeof letterFrequency == 'function');
```
`letterFrequency("Not all that Mrs. Bennet, however")` має повертати масив.
```js
assert(Array.isArray(letterFrequency('Not all that Mrs. Bennet, however')));
```
`letterFrequency("Not all that Mrs. Bennet, however")` повинен повернути `[[" ", 5], [",", 1], [".", 1], ["B", 1], ["M", 1], ["N", 1], ["a", 2], ["e", 4], ["h", 2], ["l", 2], ["n", 2], ["o", 2], ["r", 2], ["s", 1], ["t", 4], ["v", 1], ["w", 1]]`.
```js
assert.deepEqual(letterFrequency('Not all that Mrs. Bennet, however'), [
[' ', 5],
[',', 1],
['.', 1],
['B', 1],
['M', 1],
['N', 1],
['a', 2],
['e', 4],
['h', 2],
['l', 2],
['n', 2],
['o', 2],
['r', 2],
['s', 1],
['t', 4],
['v', 1],
['w', 1]
]);
```
`letterFrequency("daughters, could ask on the ")` повинен повернути `[[" ", 5],[",", 1],["a", 2],["c", 1],["d", 2],["e", 2],["g", 1],["h", 2],["k", 1],["l", 1],["n", 1],["o", 2],["r", 1],["s", 2],["t", 2],["u", 2]]`.
```js
assert.deepEqual(letterFrequency('daughters, could ask on the '), [
[' ', 5],
[',', 1],
['a', 2],
['c', 1],
['d', 2],
['e', 2],
['g', 1],
['h', 2],
['k', 1],
['l', 1],
['n', 1],
['o', 2],
['r', 1],
['s', 2],
['t', 2],
['u', 2]
]);
```
`letterFrequency("husband any satisfactory description")` повинен повернути `[[" ", 3], ["a", 4], ["b", 1], ["c", 2], ["d", 2], ["e", 1], ["f", 1], ["h", 1], ["i", 3], ["n", 3], ["o", 2], ["p", 1], ["r", 2], ["s", 4], ["t", 3], ["u", 1], ["y", 2]]`.
```js
assert.deepEqual(letterFrequency('husband any satisfactory description'), [
[' ', 3],
['a', 4],
['b', 1],
['c', 2],
['d', 2],
['e', 1],
['f', 1],
['h', 1],
['i', 3],
['n', 3],
['o', 2],
['p', 1],
['r', 2],
['s', 4],
['t', 3],
['u', 1],
['y', 2]
]);
```
`letterFrequency("in various ways--with barefaced")` повинен повернути `[[" ", 3], ["-", 2], ["a", 4], ["b", 1], ["c", 1], ["d", 1], ["e", 2], ["f", 1], ["h", 1], ["i", 3], ["n", 1], ["o", 1], ["r", 2], ["s", 2], ["t", 1], ["u", 1], ["v", 1], ["w", 2], ["y", 1]]`.
```js
assert.deepEqual(letterFrequency('in various ways--with barefaced'), [
[' ', 3],
['-', 2],
['a', 4],
['b', 1],
['c', 1],
['d', 1],
['e', 2],
['f', 1],
['h', 1],
['i', 3],
['n', 1],
['o', 1],
['r', 2],
['s', 2],
['t', 1],
['u', 1],
['v', 1],
['w', 2],
['y', 1]
]);
```
`letterFrequency("distant surmises; but he eluded")` повинен повернути `[[" ", 4], [";", 1], ["a", 1], ["b", 1], ["d", 3], ["e", 4], ["h", 1], ["i", 2], ["l", 1], ["m", 1], ["n", 1], ["r", 1], ["s", 4], ["t", 3], ["u", 3]]`.
```js
assert.deepEqual(letterFrequency('distant surmises; but he eluded'), [
[' ', 4],
[';', 1],
['a', 1],
['b', 1],
['d', 3],
['e', 4],
['h', 1],
['i', 2],
['l', 1],
['m', 1],
['n', 1],
['r', 1],
['s', 4],
['t', 3],
['u', 3]
]);
```
`letterFrequency("last obliged to accept the second-hand,")` повинен повернути `[[" ", 5], [",", 1], ["-", 1], ["a", 3], ["b", 1], ["c", 3], ["d", 3], ["e", 4], ["g", 1], ["h", 2], ["i", 1], ["l", 2], ["n", 2], ["o", 3], ["p", 1], ["s", 2], ["t", 4]]`.
```js
assert.deepEqual(letterFrequency('last obliged to accept the second-hand,'), [
[' ', 5],
[',', 1],
['-', 1],
['a', 3],
['b', 1],
['c', 3],
['d', 3],
['e', 4],
['g', 1],
['h', 2],
['i', 1],
['l', 2],
['n', 2],
['o', 3],
['p', 1],
['s', 2],
['t', 4]
]);
```
# --seed--
## --seed-contents--
```js
function letterFrequency(txt) {
}
```
# --solutions--
```js
function letterFrequency(txt) {
var cs = txt.split(''),
i = cs.length,
dct = {},
c = '',
keys;
while (i--) {
c = cs[i];
dct[c] = (dct[c] || 0) + 1;
}
keys = Object.keys(dct);
keys.sort();
return keys.map(function (c) { return [c, dct[c]]; });
}
```

View File

@@ -0,0 +1,105 @@
---
id: 5e4ce2eaac708cc68c1df260
title: Відстань Левенштейна
challengeType: 5
forumTopicId: 385264
dashedName: levenshtein-distance
---
# --description--
У інформаційній теорії та комп'ютерних науках **відстань Левенштейна** — це [метрика](https://en.wikipedia.org/wiki/string metric), яка вимірює відмінність між двома послідовностями (тобто [відстань редагування](https://en.wikipedia.org/wiki/edit distance)). Відстань Левенштейна між двома рядками визначається як мінімальна кількість операцій вставки, видалення або заміни, необхідних для перетворення одного рядка в інший.
Наприклад:
Відстань Левенштейна між "**kitten**" і "**sitting**" складають 3, оскільки неможливо перетворити одне слово в інше за меншу кількість операцій:
<ul>
<li><strong>k</strong>itten <strong>s</strong>itten (заміна 'k' на 's')</li>
<li>sitt<strong>e</strong>n sitt<strong>i</strong>n (заміна 'e' на 'i')</li>
<li>sittin sittin<strong>g</strong> (вставити 'g' в кінці).</li>
</ul>
*Відстань Левенштейна між "**rosettacode**" та "**raisethysword**" складає **8**.*
*Якщо рядки поміняти місцями, відстань між ними не зміниться.*
# --instructions--
Напишіть функцію, яка повертає відстань Левенштейна між двома рядками, вказаними як параметри.
# --hints--
`levenshtein` має бути функцією.
```js
assert(typeof levenshtein == 'function');
```
`levenshtein("mist", "dist")` має повернути число.
```js
assert(typeof levenshtein('mist', 'dist') == 'number');
```
`levenshtein("mist", "dist")` має повернути `1`.
```js
assert.equal(levenshtein('mist', 'dist'), 1);
```
`levenshtein("tier", "tor")` має повернути `2`.
```js
assert.equal(levenshtein('tier', 'tor'), 2);
```
`levenshtein("kitten", "sitting")` має повернути `3`.
```js
assert.equal(levenshtein('kitten', 'sitting'), 3);
```
`levenshtein("stop", "tops")` має повернути `2`.
```js
assert.equal(levenshtein('stop', 'tops'), 2);
```
`levenshtein("rosettacode", "raisethysword")` має повернути `8`.
```js
assert.equal(levenshtein('rosettacode', 'raisethysword'), 8);
```
`levenshtein("mississippi", "swiss miss")` має повернути `8`.
```js
assert.equal(levenshtein('mississippi', 'swiss miss'), 8);
```
# --seed--
## --seed-contents--
```js
function levenshtein(a, b) {
}
```
# --solutions--
```js
function levenshtein(a, b) {
var t = [], u, i, j, m = a.length, n = b.length;
if (!m) { return n; }
if (!n) { return m; }
for (j = 0; j <= n; j++) { t[j] = j; }
for (i = 1; i <= m; i++) {
for (u = [i], j = 1; j <= n; j++) {
u[j] = a[i - 1] === b[j - 1] ? t[j - 1] : Math.min(t[j - 1], t[j], u[j - 1]) + 1;
} t = u;
} return u[n];
}
```

View File

@@ -0,0 +1,97 @@
---
id: 5e4ce2f5ac708cc68c1df261
title: Лінійний конгруентний метод
challengeType: 5
forumTopicId: 385266
dashedName: linear-congruential-generator
---
# --description--
[Лінійний конгруентний метод](https://en.wikipedia.org/wiki/linear congruential generator) є дуже простим прикладом [генератора випадкових чисел](http://rosettacode.org/wiki/random number generator). Усі лінійні конгруентні генератори працюють за формулою:
$$r_{n + 1} = (a \times r_n + c) \bmod m$$
Де:
<ul>
<li>$ r_0 $ — початкове число.</li>
<li>$r_1$, $r_2$, $r_3$, ..., — випадкові числа.</li>
<li>$a$, $c$, $m$ — константи.</li>
</ul>
Якщо уважно вибирати значення $a$, $c$ і $m$, то генератор створює рівномірний розподіл цілих чисел від $0$ до $m - 1$.
Згенеровані алгоритмом числа неякісні. $r_n$ та $r\_{n + 1}$ не є незалежними, як справжні випадкові числа. Знаючи $r_n$, можна передбачити $r\_{n + 1}$, тому лінійний конгруентний метод не є криптографічно стійким. Лінійний конгруентний метод добре підходить для простих завдань, наприклад для [Miller-Rabin primality test](http://rosettacode.org/wiki/Miller-Rabin primality test) або [FreeCell deals](http://rosettacode.org/wiki/deal cards for FreeCell). Перевагою цього методу є те, що можна легко відтворити послідовність чисел з того самого $r_0$. Можна також відтворити таку послідовність за допомогою іншої мови програмування, оскільки формула дуже проста.
# --instructions--
Напишіть функцію з параметрами $r_0,a,c,m,n$, яка видає $r_n$.
# --hints--
`linearCongGenerator` має бути функцією.
```js
assert(typeof linearCongGenerator == 'function');
```
`linearCongGenerator(324, 1145, 177, 2148, 3)` має повернути число.
```js
assert(typeof linearCongGenerator(324, 1145, 177, 2148, 3) == 'number');
```
`linearCongGenerator(324, 1145, 177, 2148, 3)` має повернути `855`.
```js
assert.equal(linearCongGenerator(324, 1145, 177, 2148, 3), 855);
```
`linearCongGenerator(234, 11245, 145, 83648, 4)` має повернути `1110`.
```js
assert.equal(linearCongGenerator(234, 11245, 145, 83648, 4), 1110);
```
`linearCongGenerator(85, 11, 1234, 214748, 5)` має повернути `62217`.
```js
assert.equal(linearCongGenerator(85, 11, 1234, 214748, 5), 62217);
```
`linearCongGenerator(0, 1103515245, 12345, 2147483648, 1)` має повернути `12345`.
```js
assert.equal(linearCongGenerator(0, 1103515245, 12345, 2147483648, 1), 12345);
```
`linearCongGenerator(0, 1103515245, 12345, 2147483648, 2)` має повернути `1406932606`.
```js
assert.equal(
linearCongGenerator(0, 1103515245, 12345, 2147483648, 2),
1406932606
);
```
# --seed--
## --seed-contents--
```js
function linearCongGenerator(r0, a, c, m, n) {
}
```
# --solutions--
```js
function linearCongGenerator(r0, a, c, m, n) {
for (let i = 0; i < n; i++) {
r0 = (a * r0 + c) % m;
}
return r0;
}
```

View File

@@ -0,0 +1,111 @@
---
id: 5e4ce2a1ac708cc68c1df25d
title: Множення в стовпчик
challengeType: 5
forumTopicId: 385269
dashedName: long-multiplication
---
# --description--
Без сумніву застосовуйте [множення в стовпчик](https://en.wikipedia.org/wiki/long multiplication).
Це один з можливих підходів у довгій арифметиці.
# --instructions--
Напишіть функцію, яка враховує масив рядків як параметр. Ваша функція повинна повернути добуток цих двох великих чисел, як рядок.
**Примітка:** В JavaScript, арифметичні операції з малою кількістю чисел є неточними з великими числами, тому ви повинні самостійно обчислювати.
# --hints--
`mult` повинен бути функцією.
```js
assert(typeof mult == 'function');
```
`mult("18446744073709551616", "18446744073709551616")` повинна видати рядок.
```js
assert(typeof mult('18446744073709551616', '18446744073709551616') == 'string');
```
`mult("18446744073709551616", "18446744073709551616")` повинен повернути `"340282366920938463463374607431768211456"`.
```js
assert.equal(
mult('18446744073709551616', '18446744073709551616'),
'340282366920938463463374607431768211456'
);
```
`mult("31844674073709551616", "1844674407309551616")` повинен повернути `"58743055272886011737990786529368211456"`.
```js
assert.equal(
mult('31844674073709551616', '1844674407309551616'),
'58743055272886011737990786529368211456'
);
```
`mult("1846744073709551616", "44844644073709551616")` повинен повернути `"82816580680737279241781007431768211456"`.
```js
assert.equal(
mult('1846744073709551616', '44844644073709551616'),
'82816580680737279241781007431768211456'
);
```
`mult("1844674407370951616", "1844674407709551616")` повинен повернути`"3402823669833978308014392742590611456"`.
```js
assert.equal(
mult('1844674407370951616', '1844674407709551616'),
'3402823669833978308014392742590611456'
);
```
`mult("2844674407370951616", "1844674407370955616")` повинен повернути `"5247498076580334548376218009219475456"`.
```js
assert.equal(
mult('2844674407370951616', '1844674407370955616'),
'5247498076580334548376218009219475456'
);
```
# --seed--
## --seed-contents--
```js
function mult(strNum1, strNum2) {
}
```
# --solutions--
```js
function mult(strNum1, strNum2) {
var a1 = strNum1.split("").reverse();
var a2 = strNum2.toString().split("").reverse();
var aResult = new Array;
for ( var iterNum1 = 0; iterNum1 < a1.length; iterNum1++ ) {
for ( var iterNum2 = 0; iterNum2 < a2.length; iterNum2++ ) {
var idxIter = iterNum1 + iterNum2; // Get the current array position.
aResult[idxIter] = a1[iterNum1] * a2[iterNum2] + ( idxIter >= aResult.length ? 0 : aResult[idxIter] );
if ( aResult[idxIter] > 9 ) { // Carrying
aResult[idxIter + 1] = Math.floor( aResult[idxIter] / 10 ) + ( idxIter + 1 >= aResult.length ? 0 : aResult[idxIter + 1] );
aResult[idxIter] %= 10;
}
}
}
return aResult.reverse().join("");
}
```

View File

@@ -0,0 +1,102 @@
---
id: 5e6dd1278e6ca105cde40ea9
title: Найдовша спільна підпослідовність
challengeType: 5
forumTopicId: 385271
dashedName: longest-common-subsequence
---
# --description--
** Найдовша спільна підпослідовність**([**LCS**](http://en.wikipedia.org/wiki/Longest_common_subsequence_problem)) груп А і В - це найдовша група спільних елементів між двома групами, які розташовані в однаковому порядку в кожній групі. Наприклад, послідовності "1234" і "1224533324" мають LCS "1234":
***1234***
***12***245***3***332***4***
На прикладі рядка розглянемо послідовності "thisisatest" та "testing123testing". LCS буде "tsitest":
***t***hi***si***sa***test***
***t***e***s***t***i***ng123***test***ing.
Ваш код має складатися тільки з рядків.
Для отримання додаткової інформації про це завдання, будь ласка, дивіться [Wikipedia](https://en.wikipedia.org/wiki/Longest_common_subsequence_problem).
# --instructions--
Напишіть чутливу до регістру символів функцію, яка повертає LCS двох рядків. Вам не потрібно показувати багато LCS.
# --hints--
`lcs` повинен бути функцією.
```js
assert(typeof lcs == 'function');
```
`lcs("thisisatest", "testing123testing")` повинен вивести рядок.
```js
assert(typeof lcs('thisisatest', 'testing123testing') == 'string');
```
`lcs("thisisatest", "testing123testing")` повинен повернути `"tsitest"`.
```js
assert.equal(lcs('thisisatest', 'testing123testing'), 'tsitest');
```
`lcs("ABCDGH", "AEDFHR")` повинен повернути `"ADH"`.
```js
assert.equal(lcs('ABCDGH', 'AEDFHR'), 'ADH');
```
`lcs("AGGTAB", "GXTXAYB")` повинен повернути `"GTAB"`.
```js
assert.equal(lcs('AGGTAB', 'GXTXAYB'), 'GTAB');
```
`lcs("BDACDB", "BDCB")` повинен повернути `"BDCB"`.
```js
assert.equal(lcs('BDACDB', 'BDCB'), 'BDCB');
```
`lcs("ABAZDC", "BACBAD")` повинен повернути `"ABAD"`.
```js
assert.equal(lcs('ABAZDC', 'BACBAD'), 'ABAD');
```
# --seed--
## --seed-contents--
```js
function lcs(a, b) {
}
```
# --solutions--
```js
function lcs(a, b) {
var aSub = a.substr(0, a.length - 1);
var bSub = b.substr(0, b.length - 1);
if (a.length === 0 || b.length === 0) {
return '';
} else if (a.charAt(a.length - 1) === b.charAt(b.length - 1)) {
return lcs(aSub, bSub) + a.charAt(a.length - 1);
} else {
var x = lcs(a, bSub);
var y = lcs(aSub, b);
return (x.length > y.length) ? x : y;
}
}
```

View File

@@ -0,0 +1,120 @@
---
id: 5e6dd139859c290b6ab80292
title: Задача про найдовшу зростаючу підпослідовність
challengeType: 5
forumTopicId: 385272
dashedName: longest-increasing-subsequence
---
# --description--
Задача про найдовшу зростаючу підпослідовність полягає у пошуку підпослідовності даної послідовності, в якій елементи підпослідовності розташовані в порядку зростання, тобто, кожен наступний елемент підпослідовності більше попереднього, також, підпослідовність є якомога довшою. Наприклад:
Для наступного масиву:
$\\{3, 10, 2, 1, 20\\}$
Найдовша зростаюча підпослідовність:
$\\{3, 10, 20\\}$
Для отримання додаткової інформації про цю задачу, будь ласка, перейдіть за посиланням [Wikipedia](https://en.wikipedia.org/wiki/Longest increasing subsequence).
# --instructions--
Напишіть функцію, яка приймає масив чисел як параметр і виводить найдовшу зростаючу послідовність.
Гарантовано, що кожен масив матиме найдовшу зростаючу послідовність.
# --hints--
`findSequence` має бути функцією.
```js
assert(typeof findSequence == 'function');
```
`findSequence([3, 10, 2, 1, 20])` повинен видати масив.
```js
assert(Array.isArray(findSequence([3, 10, 2, 1, 20])));
```
`findSequence([3, 10, 2, 1, 20])` повинен видати `[3, 10, 20]`.
```js
assert.deepEqual(findSequence([3, 10, 2, 1, 20]), [3, 10, 20]);
```
`findSequence([2, 7, 3, 5, 8])` повинен видати `[2, 3, 5, 8]`.
```js
assert.deepEqual(findSequence([2, 7, 3, 5, 8]), [2, 3, 5, 8]);
```
`findSequence([2, 6, 4, 5, 1])` повинен видати `[2, 4, 5]`.
```js
assert.deepEqual(findSequence([2, 6, 4, 5, 1]), [2, 4, 5]);
```
`findSequence([10, 22, 9, 33, 21, 50, 60, 80])` повинен видати `[10, 22, 33, 50, 60, 80]`.
```js
assert.deepEqual(findSequence([10, 22, 9, 33, 21, 50, 60, 80]), [
10,
22,
33,
50,
60,
80
]);
```
`findSequence([0, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15])` повинен видати `[0, 2, 6, 9, 11, 15`.
```js
assert.deepEqual(
findSequence([0, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]),
[0, 2, 6, 9, 11, 15]
);
```
# --seed--
## --seed-contents--
```js
function findSequence(input) {
}
```
# --solutions--
```js
function findSequence(input) {
var len = input.length;
var result = []
for (var i = 0; i < len; i++) result.push(1)
for (var i = 0; i < len; i++)
for (var j = i - 1; j >= 0; j--)
if (input[i] > input[j] && result[j] >= result[i])
result[i] = result[j] + 1;
var maxValue = Math.max.apply(null, result);
var maxIndex = result.indexOf(Math.max.apply(Math, result));
var output = [];
output.push(input[maxIndex]);
for (var i = maxIndex; i >= 0; i--) {
if (maxValue == 0) break;
if (input[maxIndex] > input[i] && result[i] == maxValue - 1) {
output.push(input[i]);
maxValue--;
}
}
output.reverse();
return output;
}
```

View File

@@ -0,0 +1,101 @@
---
id: 5e6dd14192286d95fc43046e
title: Завдання найдовшого рядка
challengeType: 5
forumTopicId: 385275
dashedName: longest-string-challenge
---
# --description--
У цьому завданні ви повинні знайти рядки, які є найдовшими серед вказаних.
# --instructions--
Напишіть функцію, яка приймає масив рядків і повертає рядки, довжина яких дорівнює найдовшій довжині.
# --hints--
`longestString` має бути функцією.
```js
assert(typeof longestString == 'function');
```
`longestString(["a", "bb", "ccc", "ee", "f", "ggg"])` має повернути масив.
```js
assert(Array.isArray(longestString(['a', 'bb', 'ccc', 'ee', 'f', 'ggg'])));
```
`longestString(["a", "bb", "ccc", "ee", "f", "ggg"])` має повернути масив `["ccc", "ggg"]'`.
```js
assert.deepEqual(longestString(['a', 'bb', 'ccc', 'ee', 'f', 'ggg']), [
'ccc',
'ggg'
]);
```
`longestString(["afedg", "bb", "sdccc", "efdee", "f", "geegg"])` має повернути `["afedg", "sdccc", "efdee", "geegg"]`.
```js
assert.deepEqual(
longestString(['afedg', 'bb', 'sdccc', 'efdee', 'f', 'geegg']),
['afedg', 'sdccc', 'efdee', 'geegg']
);
```
`longestString(["a", "bhghgb", "ccc", "efde", "fssdrr", "ggg"])` має повернути `["bhghgb", "fssdrr"]`.
```js
assert.deepEqual(
longestString(['a', 'bhghgb', 'ccc', 'efde', 'fssdrr', 'ggg']),
['bhghgb', 'fssdrr']
);
```
`longestString(["ahgfhg", "bdsfsb", "ccc", "ee", "f", "ggdsfg"])` має повернути `["ahgfhg", "bdsfsb", "ggdsfg"]`.
```js
assert.deepEqual(
longestString(['ahgfhg', 'bdsfsb', 'ccc', 'ee', 'f', 'ggdsfg']),
['ahgfhg', 'bdsfsb', 'ggdsfg']
);
```
`longestString(["a", "bbdsf", "ccc", "edfe", "gzzzgg"])` має повернути `["gzzzgg"]`.
```js
assert.deepEqual(longestString(['a', 'bbdsf', 'ccc', 'edfe', 'gzzzgg']), [
'gzzzgg'
]);
```
# --seed--
## --seed-contents--
```js
function longestString(strings) {
}
```
# --solutions--
```js
function longestString(strings) {
var mx = 0;
var result = []
strings.forEach(function (e) {
if (e.length > mx) {
mx = e.length
result = [e]
} else if (e.length == mx)
result.push(e)
})
return result
}
```

View File

@@ -0,0 +1,92 @@
---
id: 5e6dd14797f5ce267c2f19d0
title: Послідовність "подивися-і-скажи"
challengeType: 5
forumTopicId: 385277
dashedName: look-and-say-sequence
---
# --description--
[Послідовність "подивися-і-скажи" ](https://en.wikipedia.org/wiki/Look and say sequence) - це рекурсивна послідовність певних чисел.
Визначення послідовності
<ul><li>Візьміть десяткове число</li>
<li><span>Подивіться</span>на число, візуально групуючи цифри, які послідовно повторюються.</li>
<li><span>Назвіть</span> число зліва направо, група за групою; скільки таких цифр можливо.</li></ul><span> Це число стає наступним у послідовності.</span>
Наприклад:
<ul><li>Починаючи з цифри 1, у вас є <span>одна</span> цифра 1, яка формує число 11</li>
<li>Починаючи з 11, ви маєте <span>дві</span> цифри 1. Тобто 21</li>
<li>Починаючи з числа 21, ви маєте <span>одну</span> цифру 2, і <span>одну</span> цифру 1. Тобто (12) (11), які стають 1211</li>
<li>Починаючи з числа 1211, ви маєте <span>одну</span> цифру 1, <span>одну</span> цифру 2, і <span>дві</span> цифри 1. Тобто (11)(12)(21), які стають 111221</li></ul>
# --instructions--
Напишіть функцію, яка приймає рядок в якості параметра, обробляє його, і повертає результат.
# --hints--
`lookAndSay` повинен бути функцією.
```js
assert(typeof lookAndSay == 'function');
```
`lookAndSay("1")` повинен повернути рядок.
```js
assert(typeof lookAndSay('1') == 'string');
```
`lookAndSay("1")` повинен повертати `"11"`.
```js
assert.equal(lookAndSay('1'), '11');
```
`lookAndSay("11")` повинен повертати `"21"`.
```js
assert.equal(lookAndSay('11'), '21');
```
`lookAndSay("21")` повинен повертати `"1211"`.
```js
assert.equal(lookAndSay('21'), '1211');
```
`lookAndSay("1211")` повинен повертати `"111221"`.
```js
assert.equal(lookAndSay('1211'), '111221');
```
`lookAndSay("3542")` повинен повертати `"13151412"`.
```js
assert.equal(lookAndSay('3542'), '13151412');
```
# --seed--
## --seed-contents--
```js
function lookAndSay(str) {
}
```
# --solutions--
```js
function lookAndSay(str) {
return str.replace(/(.)\1*/g, function(seq, p1) {
return seq.length.toString() + p1;
});
}
```

View File

@@ -0,0 +1,139 @@
---
id: 5e6dd15004c88cf00d2a78b3
title: Циклічне повторення декількох масивів одночасно
challengeType: 5
forumTopicId: 385279
dashedName: loop-over-multiple-arrays-simultaneously
---
# --description--
Циклічно повторюйте декілька масивів та створюйте новий, чий елемент $i^{th}$ є об'єднанням $i^{th}$ кожного вказаного елемента.
Наприклад, якщо вам дано цей масив масивів:
```js
[ ["a", "b", "c"], ["A", "B", "C"], [1, 2, 3] ]
```
вихід має бути:
```js
["aA1","bB2","cC3"]
```
# --instructions--
Напишіть функцію, яка приймає масив масивів в якості параметра і повертає масив рядків, задовольняючи даний опис.
# --hints--
`loopSimult` має бути функцією.
```js
assert(typeof loopSimult == 'function');
```
`loopSimult([["a", "b", "c"], ["A", "B", "C"], [1, 2, 3]])` повинен повернути масив.
```js
assert(
Array.isArray(
loopSimult([
['a', 'b', 'c'],
['A', 'B', 'C'],
[1, 2, 3]
])
)
);
```
`loopSimult([["a", "b", "c"], ["A", "B", "C"], [1, 2, 3]])` повинен повернути `["aA1", "bB2", "cC3"]`.
```js
assert.deepEqual(
loopSimult([
['a', 'b', 'c'],
['A', 'B', 'C'],
[1, 2, 3]
]),
['aA1', 'bB2', 'cC3']
);
```
`loopSimult([["c", "b", "c"], ["4", "5", "C"], [7, 7, 3]])` повинен повернути `["c47", "b57", "cC3"]`.
```js
assert.deepEqual(
loopSimult([
['c', 'b', 'c'],
['4', '5', 'C'],
[7, 7, 3]
]),
['c47', 'b57', 'cC3']
);
```
`loopSimult([["a", "b", "c", "d"], ["A", "B", "C", "d"], [1, 2, 3, 4]])` повинн повернути `["aA1", "bB2", "cC3", "dd4"]`.
```js
assert.deepEqual(
loopSimult([
['a', 'b', 'c', 'd'],
['A', 'B', 'C', 'd'],
[1, 2, 3, 4]
]),
['aA1', 'bB2', 'cC3', 'dd4']
);
```
`loopSimult([["a", "b"], ["A", "B"], [1, 2]])`повинен повернути `["aA1", "bB2"]`.
```js
assert.deepEqual(
loopSimult([
['a', 'b'],
['A', 'B'],
[1, 2]
]),
['aA1', 'bB2']
);
```
`loopSimult([["b", "c"], ["B", "C"], [2, 3]])` повинен повернути `["bB2", "cC3"]`.
```js
assert.deepEqual(
loopSimult([
['b', 'c'],
['B', 'C'],
[2, 3]
]),
['bB2', 'cC3']
);
```
# --seed--
## --seed-contents--
```js
function loopSimult(A) {
}
```
# --solutions--
```js
function loopSimult(A) {
var res = [], output;
for (var i = 0; i < A[0].length; i += 1) {
output = "";
for (var j = 0; j < A.length; j++)
output += A[j][i];
res.push(output);
}
return res;
}
```

View File

@@ -0,0 +1,318 @@
---
id: 5e6decd8ec8d7db960950d1c
title: LU-розклад матриці
challengeType: 5
forumTopicId: 385280
dashedName: lu-decomposition
---
# --description--
Кожну квадратну матрицю $A$ можна розкласти на добуток з нижньої трикутної матриці $L$ та верхньої трикутної матриці $U$, як описано у [LU decomposition](https://en.wikipedia.org/wiki/LU decomposition).
$A = LU$
Таке представлення матриці є модифікованим методом Гауса.
В той час як [розклад Холецького](http://rosettacode.org/wiki/Cholesky decomposition) тільки працює для симетричних, позитивно-визначених матриць, загальніший LU-розклад матриці працює для будь-якої квадратної матриці.
Існують декілька алгоритмів для розрахунку $L$ та $U$.
Для отримання *алгоритму Крота* для прикладу 3x3, нам необхідно розв'язати наступну систему:
\\begin{align}A = \\begin{pmatrix} a\_{11} & a\_{12} & a\_{13}\\\\ a\_{21} & a\_{22} & a\_{23}\\\\ a\_{31} & a\_{32} & a\_{33}\\\\ \\end{pmatrix}= \\begin{pmatrix} l\_{11} & 0 & 0 \\\\ l\_{21} & l\_{22} & 0 \\\\ l\_{31} & l\_{32} & l\_{33}\\\\ \\end{pmatrix} \\begin{pmatrix} u\_{11} & u\_{12} & u\_{13} \\\\ 0 & u\_{22} & u\_{23} \\\\ 0 & 0 & u\_{33} \\end{pmatrix} = LU\\end{align}
Зараз нам доведеться розв'язати 9 рівнянь з 12 невідомими. Щоб зробити систему унікальною в розв'язанні, зазвичай діагональні елементи $L$ встановлюються на 1
$l\_{11}=1$
$l\_{22}=1$
$l\_{33}=1$
тож ми отримали розв'язуючу систему з 9 невідомих та 9 рівнянь.
\\begin{align}A = \\begin{pmatrix} a\_{11} & a\_{12} & a\_{13}\\\\ a\_{21} & a\_{22} & a\_{23}\\\\ a\_{31} & a\_{32} & a\_{33}\\\\ \\end{pmatrix} = \\begin{pmatrix} 1 & 0 & 0 \\\\ l\_{21} & 1 & 0 \\\\ l\_{31} & l\_{32} & 1\\\\ \\end{pmatrix} \\begin{pmatrix} u\_{11} & u\_{12} & u\_{13} \\\\ 0 & u\_{22} & u\_{23} \\\\ 0 & 0 & u\_{33} \\end{pmatrix} = \\begin{pmatrix} u\_{11} & u\_{12} & u\_{13} \\\\ u\_{11}l\_{21} & u\_{12}l\_{21}+u\_{22} & u\_{13}l\_{21}+u\_{23} \\\\ u\_{11}l\_{31} & u\_{12}l\_{31}+u\_{22}l\_{32} & u\_{13}l\_{31} + u\_{23}l\_{32}+u\_{33} \\end{pmatrix} = LU\\end{align}
Розв'язуючи для інших $l$ і $u$, ми отримуємо наступні рівняння:
$u\_{11}=a\_{11}
$u\_{12}=a\_{12}
$u\_{13}=a\_{13}
$u\_{22}=a\_{22} - u\_{12}l\_{21}$
$u\_{23}=a\_{23} - u\_{13}l\_{21}$
$u\_{33}=a\_{33} - (u\_{13}l\_{31} + u\_{23}l\_{32})$
і для $l$:
$l\_{21}=\\frac{1}{u\_{11}} a\_{21}$
$l\_{31}=\\frac{1}{u\_{11}} a\_{31}$
$l\_{32}=\\frac{1}{u\_{22}} (a\_{32} - u\_{12}l\_{31})$
Як бачимо, існує шаблон обчислення, який можна виразити наступною формулою, спочатку за $U$
$u\_{ij} = a\_{ij} - \\sum\_{k=1}^{i-1} u\_{kj}l\_{ik}$
і потім для $L$
$l\_{ij} = \\frac{1}{u\_{jj}} (a\_{ij} - \\sum\_{k=1}^{j-1} u\_{kj}l\_{ik})$
Як бачимо, у другій формулі, щоб отримати $l\_{ij}$ нижче діагоналі, ми повинні поділити на діагональний елемент (значення) $u\_{jj}$, так виникає проблема, коли значення $u\_{jj}$ дорівнює 0 або є дуже малим, що призводить до числової нестабільності.
Розв'язок цього завдання є *вибір головного елемента матриці* $A$, що означає перегрупування рядків $A$, на розклад $LU$ таким чином, щоб найбільший елемент кожної колонки потрапляв на діагональ $A$. Переміщення рядків означає множення $A$ на матрицю перестановки $P$:
$PA \\Rightarrow A'$
Наприклад:
\\begin{align} \\begin{pmatrix} 0 & 1 \\\\ 1 & 0 \\end{pmatrix} \\begin{pmatrix} 1 & 4 \\\\ 2 & 3 \\end{pmatrix} \\Rightarrow \\begin{pmatrix} 2 & 3 \\\\ 1 & 4 \\end{pmatrix} \\end{align}
Алгоритм розкладки застосовується тоді до перерозміщеної матриці так, щоб
$PA = LU$
# --instructions--
Завдання полягає в тому, щоб реалізувати процедуру, яка знайде матрицю nxn $A$ і поверне нижчу трикутну матрицю $L$, верхню трикутну матрицю $U$ і матрицю перестановки $P$, так, щоб розв'язати вищезгадане рівняння. Повернене значення має бути у вигляді `[L, U, P]`.
# --hints--
`luDecomposition` повинне бути функцією.
```js
assert(typeof luDecomposition == 'function');
```
`luDecomposition([[1, 3, 5], [2, 4, 7], [1, 1, 0]])` повинен повернути масив.
```js
assert(
Array.isArray(
luDecomposition([
[1, 3, 5],
[2, 4, 7],
[1, 1, 0]
])
)
);
```
`luDecomposition([[1, 3, 5], [2, 4, 7], [1, 1, 0]])` повинен повернути `[[[1, 0, 0], [0.5, 1, 0], [0.5, -1, 1]], [[2, 4, 7], [0, 1, 1.5], [0, 0, -2]], [[0, 1, 0], [1, 0, 0], [0, 0, 1]]]`.
```js
assert.deepEqual(
luDecomposition([
[1, 3, 5],
[2, 4, 7],
[1, 1, 0]
]),
[
[
[1, 0, 0],
[0.5, 1, 0],
[0.5, -1, 1]
],
[
[2, 4, 7],
[0, 1, 1.5],
[0, 0, -2]
],
[
[0, 1, 0],
[1, 0, 0],
[0, 0, 1]
]
]
);
```
`luDecomposition([[11, 9, 24, 2], [1, 5, 2, 6], [3, 17, 18, 1], [2, 5, 7, 1]])` повинен повернути `[[[1, 0, 0, 0], [0.2727272727272727, 1, 0, 0], [0.09090909090909091, 0.2875, 1, 0], [0.18181818181818182, 0.23124999999999996, 0.0035971223021580693, 1]], [[11, 9, 24, 2], [0, 14.545454545454547, 11.454545454545455, 0.4545454545454546], [0, 0, -3.4749999999999996, 5.6875], [0, 0, 0, 0.510791366906476]], [[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]]]`.
```js
assert.deepEqual(
luDecomposition([
[11, 9, 24, 2],
[1, 5, 2, 6],
[3, 17, 18, 1],
[2, 5, 7, 1]
]),
[
[
[1, 0, 0, 0],
[0.2727272727272727, 1, 0, 0],
[0.09090909090909091, 0.2875, 1, 0],
[0.18181818181818182, 0.23124999999999996, 0.0035971223021580693, 1]
],
[
[11, 9, 24, 2],
[0, 14.545454545454547, 11.454545454545455, 0.4545454545454546],
[0, 0, -3.4749999999999996, 5.6875],
[0, 0, 0, 0.510791366906476]
],
[
[1, 0, 0, 0],
[0, 0, 1, 0],
[0, 1, 0, 0],
[0, 0, 0, 1]
]
]
);
```
`luDecomposition([[1, 1, 1], [4, 3, -1], [3, 5, 3]])` повинен повернути `[[[1, 0, 0], [0.75, 1, 0], [0.25, 0.09090909090909091, 1]], [[4, 3, -1], [0, 2.75, 3.75], [0, 0, 0.9090909090909091]], [[0, 1, 0], [0, 0, 1], [1, 0, 0]]]`.
```js
assert.deepEqual(
luDecomposition([
[1, 1, 1],
[4, 3, -1],
[3, 5, 3]
]),
[
[
[1, 0, 0],
[0.75, 1, 0],
[0.25, 0.09090909090909091, 1]
],
[
[4, 3, -1],
[0, 2.75, 3.75],
[0, 0, 0.9090909090909091]
],
[
[0, 1, 0],
[0, 0, 1],
[1, 0, 0]
]
]
);
```
`luDecomposition([[1, -2, 3], [2, -5, 12], [0, 2, -10]])` має повернути `[[[1, 0, 0], [0, 1, 0], [0.5, 0.25, 1]], [[2, -5, 12], [0, 2, -10], [0, 0, -0.5]], [[0, 1, 0], [0, 0, 1], [1, 0, 0]]]`.
```js
assert.deepEqual(
luDecomposition([
[1, -2, 3],
[2, -5, 12],
[0, 2, -10]
]),
[
[
[1, 0, 0],
[0, 1, 0],
[0.5, 0.25, 1]
],
[
[2, -5, 12],
[0, 2, -10],
[0, 0, -0.5]
],
[
[0, 1, 0],
[0, 0, 1],
[1, 0, 0]
]
]
);
```
# --seed--
## --seed-contents--
```js
function luDecomposition(A) {
}
```
# --solutions--
```js
function luDecomposition(A) {
function dotProduct(a, b) {
var sum = 0;
for (var i = 0; i < a.length; i++)
sum += a[i] * b[i]
return sum;
}
function matrixMul(A, B) {
var result = new Array(A.length);
for (var i = 0; i < A.length; i++)
result[i] = new Array(B[0].length)
var aux = new Array(B.length);
for (var j = 0; j < B[0].length; j++) {
for (var k = 0; k < B.length; k++)
aux[k] = B[k][j];
for (var i = 0; i < A.length; i++)
result[i][j] = dotProduct(A[i], aux);
}
return result;
}
function pivotize(m) {
var n = m.length;
var id = new Array(n);
for (var i = 0; i < n; i++) {
id[i] = new Array(n);
id[i].fill(0)
id[i][i] = 1;
}
for (var i = 0; i < n; i++) {
var maxm = m[i][i];
var row = i;
for (var j = i; j < n; j++)
if (m[j][i] > maxm) {
maxm = m[j][i];
row = j;
}
if (i != row) {
var tmp = id[i];
id[i] = id[row];
id[row] = tmp;
}
}
return id;
}
var n = A.length;
var L = new Array(n);
for (var i = 0; i < n; i++) { L[i] = new Array(n); L[i].fill(0) }
var U = new Array(n);
for (var i = 0; i < n; i++) { U[i] = new Array(n); U[i].fill(0) }
var P = pivotize(A);
var A2 = matrixMul(P, A);
for (var j = 0; j < n; j++) {
L[j][j] = 1;
for (var i = 0; i < j + 1; i++) {
var s1 = 0;
for (var k = 0; k < i; k++)
s1 += U[k][j] * L[i][k];
U[i][j] = A2[i][j] - s1;
}
for (var i = j; i < n; i++) {
var s2 = 0;
for (var k = 0; k < j; k++)
s2 += U[k][j] * L[i][k];
L[i][j] = (A2[i][j] - s2) / U[j][j];
}
}
return [L, U, P];
}
```

Some files were not shown because too many files have changed in this diff Show More