Skip to content

Instantly share code, notes, and snippets.

@emacdona
Last active September 26, 2021 01:46
Show Gist options
  • Save emacdona/942fd29206fa18e40c11dc99fa2f7984 to your computer and use it in GitHub Desktop.
Save emacdona/942fd29206fa18e40c11dc99fa2f7984 to your computer and use it in GitHub Desktop.
#!/usr/bin/env node
function testInputs(f, ...inputs){
inputs.forEach( i =>
console.log(`${i} becomes: ${f(i)}`)
);
}
// Quick and easy solution.
// Problems:
// Doesn't recognize consonant clusters
(function(){
console.log("Solution 1");
let vowels = "aeiou";
function pigLatin(word){
let firstCharacter = word.toLowerCase().charAt(0);
let restOfString = word.toLowerCase().substring(1);
// starts with a vowel...
if(vowels.includes(firstCharacter)){
return restOfString.concat("way");
}
// starts with a consonant...
else{
return restOfString.concat(
firstCharacter, "ay"
);
}
}
testInputs( pigLatin,
"apple",
"banana",
"chair",
"Christmas"
);
})();
// Quick and easy solution.
(function(){
console.log("");
console.log("Solution 2");
let vowels = "aeiou";
// order matters here! Don't want "ch" to match strings
// that start with "chr"
let consonantClusters = ["chr", "ch"];
function pigLatin(word){
let lcWord = word.toLowerCase();
let firstCharacter = lcWord.charAt(0);
let restOfString = lcWord.substring(1);
// starts with a vowel...
if(vowels.includes(firstCharacter)){
return restOfString.concat("way");
}
// starts with a consonant...
else {
// First, check if it starts with a cluster. Can't
// use forEach() here b/c we want to return from
// pigLatin(), not the lambda.
for(let i=0; i < consonantClusters.length; i++){
let cluster = consonantClusters[i];
if(lcWord.startsWith(cluster)){
return lcWord
.substring(cluster.length)
.concat(cluster, "ay");
}
}
// Doesn't start with a cluster? then it must
// start with a single consonant
return restOfString.concat(
firstCharacter, "ay"
);
}
}
testInputs( pigLatin,
"apple",
"banana",
"chair",
"Christmas"
);
})();
(function(){
console.log("");
console.log("Solution 3");
let vowels = "aeiou";
let consonantClusters = ["chr", "ch"];
function pigLatin(word){
let lcWord = word.toLowerCase();
let firstCharacter = lcWord.charAt(0);
let restOfString = lcWord.substring(1);
// starts with a vowel...
if(vowels.includes(firstCharacter)){
return restOfString.concat("way");
}
let matchingClusters = consonantClusters
.filter(c => lcWord.startsWith(c));
if(matchingClusters.length > 0){
let matchingCluster = matchingClusters[0];
return lcWord
.substring(matchingCluster.length)
.concat(matchingCluster, "ay");
}
else{
return restOfString.concat(
firstCharacter, "ay"
);
}
}
testInputs( pigLatin,
"apple",
"banana",
"chair",
"Christmas"
);
})();
// The really slick (and very hard to understand) solution
// It uses dynamically built Regular Expressions
// VERY advanced
(function(){
console.log("");
console.log("Solution 4");
let vowels = ["a", "e", "i", "o", "u"];
let consonantClusters = ["chr", "ch"];
function buildRe(ary, template){
let re = "^(".concat(ary.join("|"), ")(.*)$");
return {
"regex": new RegExp(re, "i"),
"template": template
};
}
let regexes = [
buildRe(vowels, "$2way"),
buildRe(consonantClusters, "$2$1ay"),
buildRe(["."], "$2$1ay")
];
function pigLatin(word){
let regex = regexes
.find(re => word.match(re.regex));
return word.replace(
regex.regex,
regex.template
).toLowerCase();
}
testInputs( pigLatin,
"apple",
"banana",
"chair",
"Christmas"
);
})();
// Previous solution made even more slick by removing some
// intermediate variables
// EXTREMELY advanced.
(function(){
console.log("");
console.log("Solution 5");
function pigLatin(word){
return [
[["a", "e", "i", "o", "u"], "$2way"],
[["chr", "ch"], "$2$1ay"],
[["."], "$2$1ay"]
]
.map( args =>
function(ary, template){
// Too hard to think about how "this" gets set
let t = {
regex: new RegExp(
"^(".concat(ary.join("|"), ")(.*)$"),
"i"
),
template: template,
transform(word) {
return word.replace(
t.regex, t.template
).toLowerCase();
}
};
return t;
}.apply(null, args)
)
.find(re => word.match(re.regex))
.transform(word);
}
testInputs( pigLatin,
"apple",
"banana",
"chair",
"Christmas"
);
})();
// Now our thoughts can move to generalization...
(function(){
console.log("");
console.log("Solution 6");
// A function that will build other functions that rearrange strings that have fixed prefixes according to the given
// set of rules.
function fixedPrefixStringRearrangeBuilder(rules){
return (word) =>
rules
.map( args =>
function(ary, template){
// Too hard to think about how "this" gets set
let t = {
regex: new RegExp(
"^(".concat(ary.join("|"), ")(.*)$"),
"i"
),
template: template,
transform(word) {
return word.replace(
t.regex, t.template
).toLowerCase();
}
};
return t;
}.apply(null, args)
)
.find(re => word.match(re.regex))
.transform(word);
}
let pigLatin = fixedPrefixStringRearrangeBuilder([
[["a", "e", "i", "o", "u"], "$2way"],
[["chr", "ch"], "$2$1ay"],
[["."], "$2$1ay"]
]);
let removeFirstCharacter = fixedPrefixStringRearrangeBuilder([
[["."], "$2"]
]);
let doubleFirstLetterIfCElseRemove= fixedPrefixStringRearrangeBuilder([
[["c"], "$1$1$2"],
[["."], "$2"]
]);
console.log("");
console.log("Pig Latin:");
testInputs( pigLatin,
"apple",
"banana",
"chair",
"Christmas"
);
console.log("");
console.log("Remove First Character:");
testInputs( removeFirstCharacter,
"apple",
"banana",
"chair",
"Christmas"
);
console.log("");
console.log("Double first letter if 'C', otherwise remove first letter:");
testInputs( doubleFirstLetterIfCElseRemove,
"apple",
"banana",
"chair",
"Christmas"
);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment