From 10c753b66fc124045c25a6aca208315e9fd2813d Mon Sep 17 00:00:00 2001 From: Oleksandr Avoiants Date: Fri, 15 Nov 2019 00:14:20 +0200 Subject: [PATCH 1/4] Possible Exercises --- Exercises/2-closure.js | 25 +++++++++++++++++++++++ Exercises/2-closure.test | 16 +++++++++++++++ Exercises/3-lambda.js | 11 ++++++++++ Exercises/3-lambda.test | 21 ++++++++++++++++++++ Exercises/4-bind.js | 35 ++++++++++++++++++++++++++++++++ Exercises/4-bind.test | 16 +++++++++++++++ Exercises/5-curry.js | 24 ++++++++++++++++++++++ Exercises/5-curry.test | 42 +++++++++++++++++++++++++++++++++++++++ Exercises/6-chaining.js | 15 ++++++++++++++ Exercises/6-chaining.test | 18 +++++++++++++++++ 10 files changed, 223 insertions(+) create mode 100644 Exercises/2-closure.js create mode 100644 Exercises/2-closure.test create mode 100644 Exercises/3-lambda.js create mode 100644 Exercises/3-lambda.test create mode 100644 Exercises/4-bind.js create mode 100644 Exercises/4-bind.test create mode 100644 Exercises/5-curry.js create mode 100644 Exercises/5-curry.test create mode 100644 Exercises/6-chaining.js create mode 100644 Exercises/6-chaining.test diff --git a/Exercises/2-closure.js b/Exercises/2-closure.js new file mode 100644 index 0000000..3f9aab2 --- /dev/null +++ b/Exercises/2-closure.js @@ -0,0 +1,25 @@ +'use strict'; + +const coffee = (volume, strength) => + (`Coffee volume: ${volume}ml, strength: ${strength}`); + +const defineCoffeeType = volume => strength => coffee(volume, strength); + +// Use function defineCoffeeType to define new coffee types. +// Define coffee type espresso which volume should equal 50ml. +// Define coffee type americano which volume should equal 150ml. + +const espresso = null; +const americano = null; + +// Set names for anonymous functions (for tests). +if (typeof espresso === 'function') { + Object.defineProperty(espresso, 'name', + { value: 'espresso', configurable: true }); +} +if (typeof americano === 'function') { + Object.defineProperty(americano, 'name', + { value: 'americano', configurable: true }); +} + +module.exports = { espresso, americano }; diff --git a/Exercises/2-closure.test b/Exercises/2-closure.test new file mode 100644 index 0000000..f11cc0f --- /dev/null +++ b/Exercises/2-closure.test @@ -0,0 +1,16 @@ +([{ + name: 'espresso', + length: [30, 70], + cases: [ + ['medium', 'Coffee volume: 50ml, strength: medium'], + ['strong', 'Coffee volume: 50ml, strength: strong'], + ] +}, +{ + name: 'americano', + length: [30, 70], + cases: [ + ['medium', 'Coffee volume: 150ml, strength: medium'], + ['strong', 'Coffee volume: 150ml, strength: strong'], + ] +}]) diff --git a/Exercises/3-lambda.js b/Exercises/3-lambda.js new file mode 100644 index 0000000..994caa8 --- /dev/null +++ b/Exercises/3-lambda.js @@ -0,0 +1,11 @@ +'use strict'; + +const tagged = (pref, str) => `[${pref}] ${str}`; + +// Define function tagDate that prepends current date to the string. +// E.g. tagDate('My String') === '[2019-11-14] My String' +// Use function tagged to implement tagDate. + +const tagDate = null; + +module.exports = { tagDate }; diff --git a/Exercises/3-lambda.test b/Exercises/3-lambda.test new file mode 100644 index 0000000..d8dbc6e --- /dev/null +++ b/Exercises/3-lambda.test @@ -0,0 +1,21 @@ +({ + name: 'tagDate', + length: [150, 400], + test: tagDate => { + { + const today = new Date(); + const dd = String(today.getDate()).padStart(2, '0'); + const mm = String(today.getMonth() + 1).padStart(2, '0'); + const yyyy = today.getFullYear(); + const expected = `[${yyyy}-${mm}-${dd}] Test`; + const y = tagDate('Test'); + if (y !== expected) { + throw new Error(`tagDate('Test') === ${y} expected: ${expected}`); + } + } + { + const src = tagDate.toString(); + if (!src.includes('tagged(')) throw new Error('Use function tagged to implement tagDate'); + } + } +}) diff --git a/Exercises/4-bind.js b/Exercises/4-bind.js new file mode 100644 index 0000000..4d869ba --- /dev/null +++ b/Exercises/4-bind.js @@ -0,0 +1,35 @@ +'use strict'; + +/* + Generalized mean (Hölder mean) + Given n numbers a₁, a₂, ... an + Define Hk (for k != 0) as the k-th root of the arithmetic mean + of the k-th power of a set of numbers + ____________________________ + Hk = ᵏ√ (a₁ᵏ + a₂ᵏ + ... + anᵏ) / n +*/ + +const H = (exp, ...args) => { + const sum = args.reduce((s, a) => (s + Math.pow(a, exp)), 0); + const avg = sum / args.length; + return Math.pow(avg, (1 / exp)); +}; + +// Use method bind() to create new functions from function H. +// Create function `average` that returns arithmetic mean (H₁) of the arguments. +// Create function `rootMeanSquare` that returns quadratic mean (H₂). + +const average = null; +const rootMeanSquare = null; + +// Set names for anonymous functions (for tests). +if (typeof average === 'function') { + Object.defineProperty(average, 'name', + { value: 'average', configurable: true }); +} +if (typeof rootMeanSquare === 'function') { + Object.defineProperty(rootMeanSquare, 'name', + { value: 'rootMeanSquare', configurable: true }); +} + +module.exports = { average, rootMeanSquare }; diff --git a/Exercises/4-bind.test b/Exercises/4-bind.test new file mode 100644 index 0000000..c280276 --- /dev/null +++ b/Exercises/4-bind.test @@ -0,0 +1,16 @@ +([{ + name: 'rootMeanSquare', + length: [10, 70], + cases: [ + [7, 1, 5], + [4, 4, 4, 4], + ] +}, +{ + name: 'average', + length: [10, 70], + cases: [ + [3, 4, 6, 7, 5], + [4, 4, 4, 4], + ] +}]) diff --git a/Exercises/5-curry.js b/Exercises/5-curry.js new file mode 100644 index 0000000..7413db2 --- /dev/null +++ b/Exercises/5-curry.js @@ -0,0 +1,24 @@ +'use strict'; + +// Check 4 digit pin. +const checkPin = (ch1, ch2, ch3, ch4) => + ([ch1, ch2, ch3, ch4].join('') === '4967'); + +const curry = fn => (...args) => + (fn.length > args.length ? + (...args2) => + curry(fn)(...args, ...args2) : + fn(...args)); + +// Use function curry to define function press +// that allows to enter pin code by one character, +// e.g. press('3')('4')('5')('6') + +const press = null; + +// Set name for anonymous function (for tests). +if (typeof press === 'function') { + Object.defineProperty(press, 'name', { value: 'press', configurable: true }); +} + +module.exports = { press }; diff --git a/Exercises/5-curry.test b/Exercises/5-curry.test new file mode 100644 index 0000000..6612626 --- /dev/null +++ b/Exercises/5-curry.test @@ -0,0 +1,42 @@ +({ + name: 'press', + length: [50, 200], + test: press => { + { + const f1 = press('1'); + if (typeof f1 !== 'function') { + throw new Error(`Expected press('1') to be a function.`); + } + } + { + const f2 = press('1')('2'); + if (typeof f2 !== 'function') { + throw new Error(`Expected press('1')('2') to be a function.`); + } + } + { + const f3 = press('1')('2')('3'); + if (typeof f3 !== 'function') { + throw new Error(`Expected press('1')('2')('3') to be a function.`); + } + } + { + const e4 = press('1')('2')('3')('4'); + if (typeof e4 !== 'boolean') { + throw new Error(`Expected press('1')('2')('3')('4') to be a boolean.`); + } + } + { + const res = press('1')('2')('3')('4'); + if (res) { + throw new Error(`Expected false when entered wrong pin code.`); + } + } + { + const res = press('4')('9')('6')('7'); + if (!res) { + throw new Error(`Expected true when entered correct pin code.`); + } + } + } +}) diff --git a/Exercises/6-chaining.js b/Exercises/6-chaining.js new file mode 100644 index 0000000..9467775 --- /dev/null +++ b/Exercises/6-chaining.js @@ -0,0 +1,15 @@ +'use strict'; + +// Check 4 digit pin. +const checkPin = (ch1, ch2, ch3, ch4) => + ([ch1, ch2, ch3, ch4].join('') === '4967'); + +// Impement function press +// that allows to enter pin code by one character, +// e.g. press('3').press('4').press('5').press('6') +// +// For hint use https://github.com/HowProgrammingWorks/Cheatsheet + +const press = null; + +module.exports = { press }; diff --git a/Exercises/6-chaining.test b/Exercises/6-chaining.test new file mode 100644 index 0000000..01d82a8 --- /dev/null +++ b/Exercises/6-chaining.test @@ -0,0 +1,18 @@ +({ + name: 'press', + length: [50, 200], + test: press => { + { + const res = press('1').press('2').press('3').press('4'); + if (res) { + throw new Error(`Expected false when entered wrong pin code.`); + } + } + { + const res = press('4').press('9').press('6').press('7'); + if (!res) { + throw new Error(`Expected true when entered correct pin code.`); + } + } + } +}) From c0d310e2f1ca2fb978d5ebb0a92dd88207cc678a Mon Sep 17 00:00:00 2001 From: Oleksandr Avoiants Date: Fri, 15 Nov 2019 09:28:03 +0200 Subject: [PATCH 2/4] Change curry exercise --- Exercises/5-curry.js | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/Exercises/5-curry.js b/Exercises/5-curry.js index 7413db2..48104f7 100644 --- a/Exercises/5-curry.js +++ b/Exercises/5-curry.js @@ -1,20 +1,17 @@ 'use strict'; // Check 4 digit pin. -const checkPin = (ch1, ch2, ch3, ch4) => - ([ch1, ch2, ch3, ch4].join('') === '4967'); +const checkPin = (...code) => + (code.join('') === '4967'); -const curry = fn => (...args) => - (fn.length > args.length ? - (...args2) => - curry(fn)(...args, ...args2) : - fn(...args)); +// Define function curry that accepts the length of the function +// (amount of function arguments) and the function. -// Use function curry to define function press -// that allows to enter pin code by one character, -// e.g. press('3')('4')('5')('6') +const curry = (length, fn) => (...args) => null; -const press = null; +// Allows to enter pin code by one character, +// Usage: press('3')('4')('5')('6') +const press = curry(4, checkPin); // Set name for anonymous function (for tests). if (typeof press === 'function') { From 5d35a4a6f23bc002e05585cbb1901af288e56ef8 Mon Sep 17 00:00:00 2001 From: Oleksandr Avoiants Date: Mon, 6 Jan 2020 20:37:37 +0200 Subject: [PATCH 3/4] PR comments: - use new hpw; - remove setting names for anonymous functions for old hpw; - remove unnecessary parentheses; - refactor constructing current date string. --- Exercises/2-closure.js | 12 +----------- Exercises/2-closure.test | 4 ++-- Exercises/3-lambda.test | 7 ++----- Exercises/4-bind.js | 10 ---------- Exercises/5-curry.js | 7 +------ Exercises/6-chaining.js | 2 +- 6 files changed, 7 insertions(+), 35 deletions(-) diff --git a/Exercises/2-closure.js b/Exercises/2-closure.js index 3f9aab2..d6f2435 100644 --- a/Exercises/2-closure.js +++ b/Exercises/2-closure.js @@ -1,7 +1,7 @@ 'use strict'; const coffee = (volume, strength) => - (`Coffee volume: ${volume}ml, strength: ${strength}`); + `Coffee volume: ${volume}ml, strength: ${strength}`; const defineCoffeeType = volume => strength => coffee(volume, strength); @@ -12,14 +12,4 @@ const defineCoffeeType = volume => strength => coffee(volume, strength); const espresso = null; const americano = null; -// Set names for anonymous functions (for tests). -if (typeof espresso === 'function') { - Object.defineProperty(espresso, 'name', - { value: 'espresso', configurable: true }); -} -if (typeof americano === 'function') { - Object.defineProperty(americano, 'name', - { value: 'americano', configurable: true }); -} - module.exports = { espresso, americano }; diff --git a/Exercises/2-closure.test b/Exercises/2-closure.test index f11cc0f..13fcfa1 100644 --- a/Exercises/2-closure.test +++ b/Exercises/2-closure.test @@ -1,4 +1,4 @@ -([{ +[{ name: 'espresso', length: [30, 70], cases: [ @@ -13,4 +13,4 @@ ['medium', 'Coffee volume: 150ml, strength: medium'], ['strong', 'Coffee volume: 150ml, strength: strong'], ] -}]) +}] diff --git a/Exercises/3-lambda.test b/Exercises/3-lambda.test index d8dbc6e..4347aed 100644 --- a/Exercises/3-lambda.test +++ b/Exercises/3-lambda.test @@ -3,11 +3,8 @@ length: [150, 400], test: tagDate => { { - const today = new Date(); - const dd = String(today.getDate()).padStart(2, '0'); - const mm = String(today.getMonth() + 1).padStart(2, '0'); - const yyyy = today.getFullYear(); - const expected = `[${yyyy}-${mm}-${dd}] Test`; + const date = new Date().toISOString().substring(0, 10); + const expected = `[${date}] Test`; const y = tagDate('Test'); if (y !== expected) { throw new Error(`tagDate('Test') === ${y} expected: ${expected}`); diff --git a/Exercises/4-bind.js b/Exercises/4-bind.js index 4d869ba..1d1849a 100644 --- a/Exercises/4-bind.js +++ b/Exercises/4-bind.js @@ -22,14 +22,4 @@ const H = (exp, ...args) => { const average = null; const rootMeanSquare = null; -// Set names for anonymous functions (for tests). -if (typeof average === 'function') { - Object.defineProperty(average, 'name', - { value: 'average', configurable: true }); -} -if (typeof rootMeanSquare === 'function') { - Object.defineProperty(rootMeanSquare, 'name', - { value: 'rootMeanSquare', configurable: true }); -} - module.exports = { average, rootMeanSquare }; diff --git a/Exercises/5-curry.js b/Exercises/5-curry.js index 48104f7..0b0f485 100644 --- a/Exercises/5-curry.js +++ b/Exercises/5-curry.js @@ -2,7 +2,7 @@ // Check 4 digit pin. const checkPin = (...code) => - (code.join('') === '4967'); + code.join('') === '4967'; // Define function curry that accepts the length of the function // (amount of function arguments) and the function. @@ -13,9 +13,4 @@ const curry = (length, fn) => (...args) => null; // Usage: press('3')('4')('5')('6') const press = curry(4, checkPin); -// Set name for anonymous function (for tests). -if (typeof press === 'function') { - Object.defineProperty(press, 'name', { value: 'press', configurable: true }); -} - module.exports = { press }; diff --git a/Exercises/6-chaining.js b/Exercises/6-chaining.js index 9467775..ca3e7f5 100644 --- a/Exercises/6-chaining.js +++ b/Exercises/6-chaining.js @@ -2,7 +2,7 @@ // Check 4 digit pin. const checkPin = (ch1, ch2, ch3, ch4) => - ([ch1, ch2, ch3, ch4].join('') === '4967'); + [ch1, ch2, ch3, ch4].join('') === '4967'; // Impement function press // that allows to enter pin code by one character, From e91b30a134e33311056a9dd5a21d4ea861da4dcd Mon Sep 17 00:00:00 2001 From: Oleksandr Avoiants Date: Sat, 11 Jan 2020 02:26:06 +0200 Subject: [PATCH 4/4] PR comments. Move expected pin code out of checkPin function --- Exercises/5-curry.js | 4 ++-- Exercises/6-chaining.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Exercises/5-curry.js b/Exercises/5-curry.js index 0b0f485..e175699 100644 --- a/Exercises/5-curry.js +++ b/Exercises/5-curry.js @@ -1,8 +1,8 @@ 'use strict'; // Check 4 digit pin. -const checkPin = (...code) => - code.join('') === '4967'; +const EXPECTED_PIN = '4967'; +const checkPin = (...code) => code.join('') === EXPECTED_PIN; // Define function curry that accepts the length of the function // (amount of function arguments) and the function. diff --git a/Exercises/6-chaining.js b/Exercises/6-chaining.js index ca3e7f5..b0b2d26 100644 --- a/Exercises/6-chaining.js +++ b/Exercises/6-chaining.js @@ -1,8 +1,8 @@ 'use strict'; // Check 4 digit pin. -const checkPin = (ch1, ch2, ch3, ch4) => - [ch1, ch2, ch3, ch4].join('') === '4967'; +const EXPECTED_PIN = '4967'; +const checkPin = (...code) => code.join('') === EXPECTED_PIN; // Impement function press // that allows to enter pin code by one character,