I wanted to practice functional programming (FP) without using any library but using vanilla JavaScript only. So I took a problem from Advent of Code (the 2nd part of Day 4)
You can only access the 2nd part if you type in the solution for the 1st part: 466
or look at my solution for part 1
--- Part Two --- For added security, yet another system policy has been put in place. Now, a valid passphrase must contain no two words that are anagrams of each other - that is, a passphrase is invalid if any word's letters can be rearranged to form any other word in the passphrase.
For example:
- abcde fghij is a valid passphrase.
- abcde xyz ecdab is not valid - the letters from the third word can be rearranged to form the first word.
- a ab abc abd abf abj is a valid passphrase, because all letters need to be used when forming another word.
- iiii oiii ooii oooi oooo is valid.
- oiii ioii iioi iiio is not valid - any of these words can be rearranged to form any other word. Under this new system policy, how many passphrases are valid?
My solution in FP:
const INPUT =
`pphsv ojtou brvhsj cer ntfhlra udeh ccgtyzc zoyzmh jum lugbnk
spjb xkkak anuvk ejoklh nyerw bsjp zxuq vcwitnd xxtjmjg zfgq xkpf
...
juo pmiyoh xxk myphio ogfyf dovlmwm moevao qqxidn`;
const get = input => input.split('\n');
const countDuplicate = words => words.reduce((acc, word) => {
return Object.assign(acc, {[word]: (acc[word] || 0) + 1});
}, {});
const onlyUniqueWords = phrases => {
const words = phrases.split(' ');
const duplicateWords = countDuplicate(words);
return !Object.values(duplicateWords).some(w => w > 1);
};
const sortWords = words => words.map(word => word.split('').sort().join(''));
const noAnagrams = phrases => {
const words = phrases.split(' ');
const sortedWords = sortWords(words).sort().join(' ');
return onlyUniqueWords(sortedWords);
};
const phrasesWithNoAnagrams = get(INPUT)
.filter(noAnagrams);
console.log("solution ", phrasesWithNoAnagrams.length);
Is there a better way to write it in FP with pure JavaScript, i.e. no additional FP library? Any other improvement suggestions are welcomed.
Object.assign
when you're only adding a single property to it? Please tell me you're not doing that just because it's "functional?" \$\endgroup\$const hasAnagram = input=>input.split(' ').map(i=>i.split('').sort().join('')).sort().reduce((ac,cv,id,ar)=>ac || (id && ar[id-1] === cv), false);
\$\endgroup\$