Skip to content

Instantly share code, notes, and snippets.

@Beraliv
Last active April 10, 2018 16:51
Show Gist options
  • Save Beraliv/cdbc524b9d0dd3c1a3a3c97dc58a59ee to your computer and use it in GitHub Desktop.
Save Beraliv/cdbc524b9d0dd3c1a3a3c97dc58a59ee to your computer and use it in GitHub Desktop.
Task 84. UniLecs. Find the number of anagrams.
// it can be optimised via lazy evaluation or cached values
function factorial(n) {
if (n < 0) {
throw new TypeError('n should be non-negative')
}
if (n < 2) {
return 1
}
return n * factorial(n - 1)
}
// can be optimised as well
// k-permutations of n, link: https://en.wikipedia.org/wiki/Permutation
function permutations(n, k) {
return factorial(n) / (factorial(n - k) * factorial(k))
}
// count the quantity of each letter in a word
function lettersIn(word) {
const hash = {}
for (let ch of word) {
hash[ch] = (hash[ch] || 0) + 1
}
return Object.values(hash)
}
function anagramNumber(word) {
const ks = lettersIn(word)
const [_, quantity] = ks.reduce(
// n is a number of free elements where we can place k-letters (initial value is word.length)
// k is a number of letters which need to be placed (initial value is 1)
// q is a quantity of pre-calculated placements which we already calculated
([n, q], k) => [n - k, q * permutations(n, k)],
[word.length, 1]
)
return quantity
}
console.log(anagramNumber('линия')) // 60
console.log(anagramNumber('вектор')) // 720
console.log(anagramNumber('парабола')) // 6720
console.log(anagramNumber('математика')) // 151200
console.log(anagramNumber('биссектриса')) // 3326400
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment