From 85b7d3ded2d260d1eb5b803dbc5eeb576e716e93 Mon Sep 17 00:00:00 2001 From: Smriti Date: Thu, 19 Mar 2020 18:54:53 +0530 Subject: [PATCH] day10: solutions - object-invert - boolean-expression-evaluator - curry --- .../boolean-expression-evaluator/README.md | 3 + .../booleanExpressionEvaluator.js | 14 +++++ .../booleanExpressionEvaluator.test.js | 47 ++++++++++++++++ js-exercises/curry/README.md | 12 ++++ js-exercises/curry/curry.js | 12 ++++ js-exercises/curry/curry.test.js | 56 +++++++++++++++++++ js-exercises/curry/t1.js | 0 js-exercises/object-invert/README.md | 3 + js-exercises/object-invert/objectInvert.js | 20 +++++++ .../object-invert/objectInvert.test.js | 21 +++++++ 10 files changed, 188 insertions(+) create mode 100644 js-exercises/boolean-expression-evaluator/README.md create mode 100644 js-exercises/boolean-expression-evaluator/booleanExpressionEvaluator.js create mode 100644 js-exercises/boolean-expression-evaluator/booleanExpressionEvaluator.test.js create mode 100644 js-exercises/curry/README.md create mode 100644 js-exercises/curry/curry.js create mode 100644 js-exercises/curry/curry.test.js create mode 100644 js-exercises/curry/t1.js create mode 100644 js-exercises/object-invert/README.md create mode 100644 js-exercises/object-invert/objectInvert.js create mode 100644 js-exercises/object-invert/objectInvert.test.js diff --git a/js-exercises/boolean-expression-evaluator/README.md b/js-exercises/boolean-expression-evaluator/README.md new file mode 100644 index 00000000..b504a5ed --- /dev/null +++ b/js-exercises/boolean-expression-evaluator/README.md @@ -0,0 +1,3 @@ +## Instructions + +Write a `booleanExpressionEvaluator` method which evaluates boolean expressions. Refer to the test cases for more info. \ No newline at end of file diff --git a/js-exercises/boolean-expression-evaluator/booleanExpressionEvaluator.js b/js-exercises/boolean-expression-evaluator/booleanExpressionEvaluator.js new file mode 100644 index 00000000..cef37aa2 --- /dev/null +++ b/js-exercises/boolean-expression-evaluator/booleanExpressionEvaluator.js @@ -0,0 +1,14 @@ +const possibleValues = ['true', 'false', '!true', '!false', '^', '&', '|']; + +const isGarbagevalue = (expression) => { + const expressionArr = expression.split(' '); + return expressionArr.every((value) => possibleValues.includes(value)); +}; + +function booleanExpressionEvaluator(expression) { + if (typeof expression !== 'string') throw Error(`Expected String, received ${typeof expression}`); + if (!isGarbagevalue(expression)) throw Error('Expected the expression to be compose of - true, false, !, ^, &, !'); + return !!eval(expression); +} + +export { booleanExpressionEvaluator }; diff --git a/js-exercises/boolean-expression-evaluator/booleanExpressionEvaluator.test.js b/js-exercises/boolean-expression-evaluator/booleanExpressionEvaluator.test.js new file mode 100644 index 00000000..4b8e726d --- /dev/null +++ b/js-exercises/boolean-expression-evaluator/booleanExpressionEvaluator.test.js @@ -0,0 +1,47 @@ +import { booleanExpressionEvaluator } from './booleanExpressionEvaluator'; + +describe('booleanExpressionEvaluator', () => { + it('return the evaulated result', () => { + // simple expressions + expect(booleanExpressionEvaluator('!true')).toEqual(false); + expect(booleanExpressionEvaluator('!false')).toEqual(true); + expect(booleanExpressionEvaluator('false & true')).toEqual(false); + expect(booleanExpressionEvaluator('false & false')).toEqual(false); + expect(booleanExpressionEvaluator('true & true')).toEqual(true); + expect(booleanExpressionEvaluator('true | true')).toEqual(true); + expect(booleanExpressionEvaluator('true | false')).toEqual(true); + expect(booleanExpressionEvaluator('false | false')).toEqual(false); + expect(booleanExpressionEvaluator('true ^ true')).toEqual(false); + expect(booleanExpressionEvaluator('false ^ false')).toEqual(false); + + // complex expressions + expect(booleanExpressionEvaluator('true & false | true')).toEqual(true); + expect(booleanExpressionEvaluator('true & !false')).toEqual(true); + expect(booleanExpressionEvaluator('false ^ true')).toEqual(true); + expect(booleanExpressionEvaluator('false ^ true | false')).toEqual(true); + expect(booleanExpressionEvaluator('true ^ true | false')).toEqual(false); + }); + + it('throws error when expression contains parameters other than true or false', () => { + expect(() => booleanExpressionEvaluator('!(abc)')).toThrow(); + expect(() => booleanExpressionEvaluator('true & abc')).toThrow(); + expect(() => booleanExpressionEvaluator('true & abc | false')).toThrow(); + expect(() => booleanExpressionEvaluator('abc & abc | abc')).toThrow(); + }); + + it('throws error when expression contains parameters other than & or | or ^', () => { + expect(() => booleanExpressionEvaluator('~(true)')).toThrow(); + expect(() => booleanExpressionEvaluator('true && abc')).toThrow(); + expect(() => booleanExpressionEvaluator('true || false')).toThrow(); + expect(() => booleanExpressionEvaluator('true * false')).toThrow(); + }); + + it('throws error when expression is not string', () => { + expect(() => booleanExpressionEvaluator(12)).toThrow(); + expect(() => booleanExpressionEvaluator([])).toThrow(); + expect(() => booleanExpressionEvaluator({})).toThrow(); + expect(() => booleanExpressionEvaluator(NaN)).toThrow(); + expect(() => booleanExpressionEvaluator(null)).toThrow(); + expect(() => booleanExpressionEvaluator()).toThrow(); + }); +}); diff --git a/js-exercises/curry/README.md b/js-exercises/curry/README.md new file mode 100644 index 00000000..e545c4d8 --- /dev/null +++ b/js-exercises/curry/README.md @@ -0,0 +1,12 @@ +Here's the basic usage of the function that you'll be creating: + +function add(a, b) { + return a + b; +} +```js +const curriedAdd = curry(add); // <- this is the curry function +console.log( curriedAdd(1)(2) ); // 3 +``` +See 'curry' tests for further info of the requirement + +Read more about it here - [Currying](https://en.wikipedia.org/wiki/Currying) \ No newline at end of file diff --git a/js-exercises/curry/curry.js b/js-exercises/curry/curry.js new file mode 100644 index 00000000..ad375c79 --- /dev/null +++ b/js-exercises/curry/curry.js @@ -0,0 +1,12 @@ +function curry(func) { + return function curried(...args) { + if (args.length >= func.length) { + return func.apply(this, args); + } + return (...args2) => curried.apply(this, args.concat(args2)); + }; +} + +export { + curry, +}; diff --git a/js-exercises/curry/curry.test.js b/js-exercises/curry/curry.test.js new file mode 100644 index 00000000..016c5506 --- /dev/null +++ b/js-exercises/curry/curry.test.js @@ -0,0 +1,56 @@ +import { curry } from './curry'; + +describe('curry', () => { + test('curries the function at least once', () => { + const add = curry((a, b) => { + return a + b; + }); + expect(add(1)(2)).toBe(3); + }); + + test('curries the function even with a single argument', () => { + const output = curry((n) => { + return n; + }); + expect(output(1)).toBe(1); + }); + + test('curries the function until the arguments needed are given at least once', () => { + const add = curry((a, b, c) => { + return a + b + c; + }); + expect(add(1, 2)(3)).toBe(6); + }); + + test('curries the function until the arguments needed are given multiple times', () => { + const add = curry((a, b, c) => { + return a + b + c; + }); + expect(add(1)(2)(3)).toBe(6); + }); + + test("doesn't share state between calls", () => { + const add = curry((a, b, c) => { + return a + b + c; + }); + expect(add(1)(2)(3)).toBe(6); + expect(add(2)(3)(4)).toBe(9); + }); + + test("doesn't only work with addition", () => { + const merge = curry((a, b, c) => { + return [a, b, c].join(', '); + }); + expect(merge('1')(2)(3)).toBe('1, 2, 3'); + }); + + test("doesn't share state between inner calls", () => { + const add = curry((a, b, c, d) => { + return a + b + c + d; + }); + const firstTwo = add(1)(2); + expect(firstTwo(3)(4)).toBe(10); + const firstThree = firstTwo(5); + expect(firstThree(6)).toBe(14); + }); +}); diff --git a/js-exercises/curry/t1.js b/js-exercises/curry/t1.js new file mode 100644 index 00000000..e69de29b diff --git a/js-exercises/object-invert/README.md b/js-exercises/object-invert/README.md new file mode 100644 index 00000000..2303f0ae --- /dev/null +++ b/js-exercises/object-invert/README.md @@ -0,0 +1,3 @@ +## Instructions + +`objectInvert` should return an object where the keys and values have been switched \ No newline at end of file diff --git a/js-exercises/object-invert/objectInvert.js b/js-exercises/object-invert/objectInvert.js new file mode 100644 index 00000000..b034fb69 --- /dev/null +++ b/js-exercises/object-invert/objectInvert.js @@ -0,0 +1,20 @@ +const makeObjectFromEntries = arr => Object.assign({}, ...Array.from(arr, ([k, v]) => ({ [k]: v }))); // Object.fromEntries is not supported; +const toEntries = Object.entries; +const map = mapFn => data => data.map(mapFn); +const swap = map(([i, j]) => [j, i]); + +const compose = (...fns) => x => fns.reduce((v, f) => f(v), x); + + +function objectInvert(obj) { + return compose( + toEntries, + swap, + makeObjectFromEntries, + )(obj); +} + + +export { + objectInvert, +}; diff --git a/js-exercises/object-invert/objectInvert.test.js b/js-exercises/object-invert/objectInvert.test.js new file mode 100644 index 00000000..68bacd46 --- /dev/null +++ b/js-exercises/object-invert/objectInvert.test.js @@ -0,0 +1,21 @@ +import { objectInvert } from './objectInvert'; + +describe('objectInvert', () => { + it('should return an object', () => { + const obj = { + hi: 'hi', + }; + const result = objectInvert(obj); + expect(Array.isArray(result)).toBe(false); + expect(typeof result).toBe('object'); + }); + it('should return an object where the keys and values have been switched', () => { + const obj = { + x: 'hi', + y: 'sup', + z: 'yo', + }; + const result = objectInvert(obj); + expect(result).toEqual({ hi: 'x', sup: 'y', yo: 'z' }); + }); +});