Last active
October 29, 2017 20:43
-
-
Save Tahseenm/4bc023896bebc9d654fed44b5e4bf1f6 to your computer and use it in GitHub Desktop.
Little Javascript Problem Solution
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* -------------------------------------------------------------------------- *\ | |
* Solution | |
\* -------------------------------------------------------------------------- */ | |
/** :: (val: any) -> boolean */ | |
const isNull = val => val === null | |
/** :: (list: Function, start: number) -> Function */ | |
const slice = (list, start = 0) => idx => list(idx + start) | |
/** :: (list: Function) -> number */ | |
const length = list => (function getLen(list, len = 0) { | |
return isNull(list(0)) ? len : getLen(slice(list, 1), len + 1) | |
})(list) | |
/** :: (min: number, max: number) -> (idx: number) -> number | null */ | |
const range = (min, max) => idx => (idx >= 0 && min + idx <= max) ? min + idx : null | |
/** :: (list: Function, iteratee: Function) -> Function */ | |
const map = (list, fn) => idx => !isNull(list(idx)) ? fn(list(idx)) : null | |
/** :: (list: Function) -> Function */ | |
const reverse = list => idx => list(length(list) - 1 - idx) | |
/** :: (list: Function, iteratee: Function) -> void */ | |
const forEach = (list, iteratee) => { | |
if (isNull(list(0))) return | |
iteratee(list(0)) | |
return forEach(slice(list, 1), iteratee) | |
} | |
/** | |
* Test :) | |
*/ | |
const nums = reverse(map(range(1, 10), n => n ** 2)) | |
forEach(nums, console.log) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* -------------------------------------------------------------------------- *\ | |
* Helpers | |
\* -------------------------------------------------------------------------- */ | |
/** :: (val: any) -> boolean */ | |
const isNull = val => val === null | |
/** :: (list: Function) -> number */ | |
const first = list => list(0) | |
/** :: (list: Function, start: number?) -> Function */ | |
const sliceFrom = (list, start = 0) => | |
idx => list(idx + start) | |
/** :: (list: Function) -> number */ | |
const length = list => (function getLength(list, len = 0) { | |
return isNull(first(list)) ? len : getLength(sliceFrom(list, 1), len + 1) | |
}(list)) | |
/* -------------------------------------------------------------------------- *\ | |
* An interesting Javascript Problem | |
\* -------------------------------------------------------------------------- */ | |
/** :: (min: number, max: number) -> (idx: number) -> number | null */ | |
const range = (min, max) => | |
idx => idx >= 0 && (min + idx) <= max ? min + idx : null | |
/** :: (iteratee: Function) -> (list: Function) -> Function */ | |
const map = iteratee => list => | |
idx => !isNull(list(idx)) ? iteratee(list(idx)) : null | |
/** :: (list: Function) -> Function */ | |
const reverse = list => | |
idx => list(length(list) - 1 - idx) | |
/** :: (iteratee: Function) -> (list: Function) -> void */ | |
const forEach = (iteratee) => (list) => { | |
if (isNull(first(list))) return | |
iteratee(first(list)) | |
return forEach(iteratee)(sliceFrom(list, 1)) | |
} | |
/** :: (f: Function, g: Function, h: Function) -> Function */ | |
const pipe = (f, g, h) => (x, y) => h(g(f(x, y))) | |
/** | |
* Let's Test it ! | |
*/ | |
const printEach = forEach(console.log) | |
const nums = pipe( | |
range, | |
map(n => n ** 2), | |
reverse, | |
)(1, 10) | |
printEach(nums) /** Should Output: | |
* 100 | |
* 81 | |
* 64 | |
* 49 | |
* 36 | |
* 25 | |
* 16 | |
* 9 | |
* 4 | |
* 1 | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ------------------------------------------------------------------------------ *\ | |
* Solution 2 | |
\* ------------------------------------------------------------------------------ */ | |
/** | |
* @param {number} min | |
* @param {number} min | |
* @returns {Function} | |
* | |
* @example | |
* const f = range(1, 3) | |
* f() // -> 1 | |
* f() // -> 2 | |
* f() // -> 3 | |
* f() // -> null | |
* f() // -> 3 | |
* ... | |
*/ | |
const range = (min, max) => { | |
let cursor = min | |
let inc = true | |
const get = () => { | |
// Incrementing | |
if (inc) { | |
if (cursor > max) { | |
cursor = max | |
inc = false | |
return null | |
} | |
else return cursor++ | |
} | |
// Decrementing | |
else { | |
if (cursor < min) { | |
cursor = min | |
inc = true | |
return null | |
} | |
else return cursor-- | |
} | |
} | |
return get | |
} | |
const reverse = collection => collection() !== null ? reverse(collection) : collection | |
const forEach = (collection, iteratee) => { | |
for (let item = collection(); item !== null; item = collection()) | |
iteratee(item) | |
} | |
const map = (collection, iteratee) => () => { | |
let item = collection() | |
item = item !== null ? iteratee(item) : item | |
return item | |
} | |
/** | |
* No Array's, Objects, Strings or methods used :) | |
*/ | |
const numbers = reverse(map(range(1, 10), n => n ** 2)) | |
forEach(numbers, console.log.bind(console)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ------------------------------------------------------------------------------ *\ | |
* Old String Solution | |
\* ------------------------------------------------------------------------------ */ | |
/** Get string length */ | |
const strLen = (s) => { | |
let length = -1 | |
while (s[++length]) {} | |
return length | |
} | |
/** | |
* @param {number} min | |
* @param {number} max | |
* @returns {string} | |
* | |
* @example | |
* range(1, 5) // -> "1,2,3,4,5," | |
*/ | |
const range = (min, max) => (min < max) | |
? `${min},${range(++min, max)}` | |
: `${max},` | |
const forEach = (collection, iteratee) => { | |
let num = '' | |
for (let i = 0; i < strLen(collection); i += 1) { | |
if (collection[i] === ',') { | |
iteratee(parseInt(num)) | |
} | |
else num += range[i] | |
} | |
} | |
const map = (collection, iteratee) => { | |
let newCollection = '' | |
forEach(collection, num => newCollection += `${iteratee(num)},`) | |
return newCollection | |
} | |
const reverse = (collection) => { | |
let newCollection = '' | |
forEach(collection, num => newCollection = `${num},${newCollection}`) | |
return newCollection | |
} | |
/** | |
* Meets all restrictions apart from [] characters for strings :( | |
*/ | |
const numbers = reverse(map(range(1, 10), n => n ** 2)) | |
forEach(numbers, console.log.bind(console)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment