0

Through youtube, I've learned to obtain a multi-dimensional output of permutations using recursion, i.e anagrams with passing in an array of letters as an argument (i.e ['a', 'b', 'c']) but is there a way to modify the code to pass in a string instead 'abc' to obtain the output below??

Into [ 'abc', 'bac', bca', 'acb', 'cab', 'cba' ]

This is my code. Is there a way to modify to obtain the desired result, using a string as the argument(i.e 'abc')? Thank you, much appreciated

function anagrams(inputString){
  if(inputString.length ===0) return [[]];
  const stringArr = inputString;
  const firstEl = stringArr[0];
  const restArr = stringArr.slice(1);
  const anagramWithoutFirst = anagrams(restArr);
  const masterArr = [];

  anagramWithoutFirst.forEach(anagram => {
    for (let i=0; i<=anagram.length; i++){
      const anagramWithFirst = [...anagram.slice(0, i), firstEl, ...anagram.slice(i)]
      masterArr.push(anagramWithFirst)
    }
  })
  return masterArr
}

console.log(anagrams(['a', 'b', 'c']))

1
  • Is there a problem with mapping the result on join, e.g. anagrams(['a', 'b', 'c']).map(e => e.join(""))? Commented Mar 22, 2022 at 13:59

1 Answer 1

1

This can be achieved using a higher order function which takes in the original function and returns a new function which splits the text up, calls the original function then joins the result back together

function anagrams(inputString){
  if(inputString.length ===0) return [[]];
  const stringArr = inputString;
  const firstEl = stringArr[0];
  const restArr = stringArr.slice(1);
  const anagramWithoutFirst = anagrams(restArr);
  const masterArr = [];

  anagramWithoutFirst.forEach(anagram => {
    for (let i=0; i<=anagram.length; i++){
      const anagramWithFirst = [...anagram.slice(0, i), firstEl, ...anagram.slice(i)]
      masterArr.push(anagramWithFirst)
    }
  })
  return masterArr
}

function splitAndUnsplit(f) {
  return (str) => (f(str.split('')).map(xs => xs.join('')))
}

console.log(splitAndUnsplit(anagrams)('abc'))
console.log(anagrams(['a', 'b', 'c']))

Edit:

To expand on @Scott Sauyet's great comment, we need two sets of parens as we are calling two functions.


function splitAndUnsplit(f) {
  return function(str){
    const inputArr  = str.split('') 
    const outputArr = f(inputArr)
    const outputStr = outputArr.map(xs => xs.join('')))
    return outputStr
  }
}

The first set of parens is used to create a function which will accept and return a string, and the second set is required to call that function with a supplied value

Sign up to request clarification or add additional context in comments.

2 Comments

Heya Alex! Thank you for your response. when you are console.logging the splitAndUnsplit, why are there two sets of parens? and not like anagrams('abc')
That's how the higher-order function works. splitAndUnsplit(anagrams) returns a function which itself takes your initial string. You could name it and then call it, like const stranagram = splitAndUnsplit (anagram) and then call it with stranagram ('abc'). But you can also call it directly. An alternative would be const stranagram = (s) => anagram (s.split ('')) .map (xs => xs.join('')). But Alex extracted that pattern into a reusable function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.