Created
January 13, 2013 01:07
-
-
Save gerardpaapu/4521537 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
// You have a sentence with several words with spaces | |
// removed and words having their character order | |
// shuffled. You have a dictionary. Write an algorithm | |
// to produce the sentence back with spaces and words | |
// with normal character order | |
function Result(){} | |
function Success(words, remaining) { | |
this.words = words; | |
this.remaining = remaining; | |
} | |
Success.prototype = new Result(); | |
function Failure(source) { | |
this.source = source; | |
} | |
Failure.prototype = new Result(); | |
function readWordFrom(word) { | |
function canonize(w) { | |
var arr = w.split(''); | |
arr.sort(); | |
return arr.join(''); | |
} | |
return function readWord(source) { | |
var word_key = canonize(word); | |
var source_key = canonize(source.slice(0, word.length)); | |
if (word_key === source_key) { | |
return new Success([word], source.slice(word.length)); | |
} else { | |
return new Failure(source); | |
} | |
}; | |
} | |
function readOneOf(dictionary) { | |
return function read(source) { | |
var i = dictionary.length, | |
result; | |
while (i--) { | |
result = readWordFrom(dictionary[i])(source); | |
if (result instanceof Success) { | |
return result; | |
} | |
} | |
return new Failure(source); | |
}; | |
} | |
function zeroOrMore(parser) { | |
return function (source) { | |
var results = []; | |
var result; | |
while ((result = parser(source)) instanceof Success) { | |
[].push.apply(results, result.words); | |
source = result.remaining; | |
} | |
return new Success(results, source); | |
}; | |
} | |
function exactly(parser) { | |
return function (source) { | |
var result = parser(source), | |
isComplete; | |
if (result instanceof Success && | |
result.remaining === '') { | |
return result; | |
} else { | |
return new Failure(source); | |
} | |
}; | |
} | |
function readWords(dictionary) { | |
return exactly(zeroOrMore(readOneOf(dictionary))); | |
} | |
exports.readWords = function (dictionary, source) { | |
var result = readWords(dictionary)(source); | |
if (result instanceof Success) { | |
return result.words; | |
} else { | |
throw new Error('Source is not composed of words from this dictionary'); | |
} | |
} | |
(function runTests() { | |
var assert = require('assert'); | |
assert.ok(readWordFrom('okay')('okayrest') instanceof Success); | |
assert.deepEqual(readWordFrom('okay')('okayrest').words, ['okay']); | |
assert.deepEqual(readWordFrom('okay')('okayrest').remaining, 'rest'); | |
assert.ok(readWordFrom('okay')('notokay') instanceof Failure); | |
assert.deepEqual(readWordFrom('okay')('notokay').source, 'notokay'); | |
// read yes, no or maybe from 'yesrest' | |
assert.ok(readOneOf(['yes', 'no', 'maybe'])('yesrest') instanceof Success); | |
assert.deepEqual(readOneOf(['yes', 'no', 'maybe'])('yesrest').words, ['yes']); | |
assert.deepEqual(readOneOf(['yes', 'no', 'maybe'])('yesrest').remaining, 'rest'); | |
// read yes, no or maybe from 'norest' | |
assert.ok(readOneOf(['yes', 'no', 'maybe'])('norest') instanceof Success); | |
assert.deepEqual(readOneOf(['yes', 'no', 'maybe'])('norest').words, ['no']); | |
assert.deepEqual(readOneOf(['yes', 'no', 'maybe'])('norest').remaining, 'rest'); | |
// read yes, no or maybe from 'mayberest' | |
assert.ok(readOneOf(['yes', 'no', 'maybe'])('mayberest') instanceof Success); | |
assert.deepEqual(readOneOf(['yes', 'no', 'maybe'])('mayberest').words, ['maybe']); | |
assert.deepEqual(readOneOf(['yes', 'no', 'maybe'])('mayberest').remaining, 'rest'); | |
// read yes, no, or maybe from 'failrest' | |
assert.ok(readOneOf(['yes', 'no', 'maybe'])('failrest') instanceof Failure); | |
assert.deepEqual(readOneOf(['yes', 'no', 'maybe'])('failrest').source, 'failrest'); | |
var dictionary = ['one', 'two', 'three']; | |
assert.ok(readWords(dictionary)('fail') instanceof Failure); | |
assert.ok(readWords(dictionary)('onetwo') instanceof Success); | |
assert.deepEqual(readWords(dictionary)('onetwo').words, | |
['one', 'two']); | |
assert.ok(readWords(dictionary)('oenwot') instanceof Success); | |
assert.deepEqual(readWords(dictionary)('oenwot').words, | |
['one', 'two']); | |
assert.ok(readWords(dictionary)('oenwotfail') instanceof Failure); | |
assert.deepEqual(readWords(dictionary)('oenwotfail').source, 'oenwotfail'); | |
}()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment