2

I have a string 'racecarzz' and I would like to generate all possible combinations of each character from that string that can be read the same way backward and forward (Palindrome).

Check for Palindromes is not difficult string.split('').reverse().join('') but generating the possible combinations is quite challenging for me.

input:

str = 'racecarzz'

output:

arr = ['rar', 'cec', 'raar', 'caac', 'craarc', 'racecar', 'raczezcar', 'zracecarz', ...]`

I've tried the solution for get-all-combinations-for-a-string but it's still missing some like 'zracecarz', 'raczezcar', etc...

    var combinations = function (string) {
    var result = [];
    var loop = function (start,depth,prefix) {
        for (var i=start; i<string.length; i++) {
            var next = prefix+string[i];
            if (depth > 0) {
                loop(i+1,depth-1,next);
            } else {
                //check for Palindrome
                if (next == next.split('').reverse().join('')) {
                    result.push(next);
                }
            }
        }
    }
    for (var i=0; i<string.length; i++) {
        loop(0,i,'');
    }
    //remove duplicate
    result = result.filter(function(val, ind){
      return result.indexOf(val)==ind;
    });
    return result;
}
document.querySelector('#demo').innerHTML = combinations('racecarzz').join('<br>');
<div id="demo"></div>

Above returns:

["r", "a", "c", "e", "c", "a", "r", "z", "z", "rr", "aa", "cc", "zz", "rar", "rcr", "rer", "rcr", "rar", "aca", "aea", "aca", "cec", "raar", "rccr", "acca", "racar", "raear", "racar", "rcecr", "aceca", "raccar", "racecar"]

Ref: https://jsfiddle.net/f77g15tx/1/

aznmunkey
  • 337
  • 1
  • 4
  • 7
  • _"but generating the possible combinations is quite challenging for me."_ Which portion of the code and or algorithm process are you experiencing issues at? Can you include the code and or algorithms that you have tried to solve inquiry? – guest271314 Aug 07 '17 at 01:24
  • @RobbyCornelissen Where is "palindrome" mentioned at linked Question? – guest271314 Aug 07 '17 at 01:30
  • you can find all permutation, and check for palindrome one by one – Zhang Bruce Aug 07 '17 at 01:31
  • @guest271314 OP states: *Check for Palindromes is not difficult [...] but generating the possible combinations is quite challenging for me.* – Robby Cornelissen Aug 07 '17 at 01:31
  • @RobbyCornelissen OP is trying to generate the palindromes. At least that is the gist of the Question. OP has not presented any evidence of effort as to a coding solution or algorithm towards that requirement at the text of the original Question. Note also that combinations are not permutations. – guest271314 Aug 07 '17 at 01:32
  • @guest271314 Fair point. Retracted my close vote. – Robby Cornelissen Aug 07 '17 at 01:37
  • @RobbyCornelissen yes, the combinations i'm trying to generate are not permutations as they are not always 9 characters long. – aznmunkey Aug 07 '17 at 01:37
  • @guest271314 _"but generating the possible combinations is quite challenging for me."_ i've tried to work off from permutations like this one [link](https://stackoverflow.com/a/40316884/3521546) but no luck – aznmunkey Aug 07 '17 at 01:39
  • @aznmunkey The length of the set is does not determine whether or not a set is a permutation or combination. You actually are trying to generate permutations, that is, that is the requirement of the Question. _"When the order doesn't matter, it is a Combination. When the order does matter it is a Permutation."_ [Combinations and Permutations - What's the Difference?](https://www.mathsisfun.com/combinatorics/combinations-permutations.html). Can you include the code that you have tried to solve own inquiry at Question? See https://stackoverflow.com/help/mcve – guest271314 Aug 07 '17 at 01:39
  • @RobbyCornelissen That does not mean to convey OP has put forth, and can demonstrate by reproduction, the effort necessary to resolve own inquiry, besides sharing a link to a Question and Answer. Permutations do not order themselves. Pure code and or an algorithm to achieve requirement by means of code are a prerequisite given the subject matter. – guest271314 Aug 07 '17 at 01:44
  • @guest271314 I agree it's not a good question, but that's not really a duplicate. Generating all combinations and then checking whether they are palindromes is only one option, and not a very good one at that. – m69's been on strike for years Aug 07 '17 at 01:59
  • @potatopeelings Where is "palindrome" generation an Answer at linked Question? – guest271314 Aug 07 '17 at 02:00
  • @m69 Agree that present Question is not a duplicate of linked Question. Though from perspective here, is applicable as to _"Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: [How to create a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve)."_ Unless your interpretation of the above is that it is not applicable to the present Question? – guest271314 Aug 07 '17 at 02:01
  • 1
    @guest271314 Apparently you were lumped together with potatopeelings as having voted for the duplicate; it's confusing when SO does that. My comment was directed at him. – m69's been on strike for years Aug 07 '17 at 02:05
  • @m69 Agree. The reason for the "close" "vote", if any, could be separately listed. Similar to the "add", "save" feature of duplicate Question editor. The user whom cast "duplicate" vote has not responded to direct question at comment as to how the linked Question is related to present Question. The linked Question and Answer are unfounded as to being related to the current Question, they are not related. That is clear. Not sure how two separate users could determine that any Question simply by virtue of containing the term "permutation" is a duplicate target? – guest271314 Aug 07 '17 at 02:09
  • @m69 You could vote to reopen the Question. Then we will be back to OP demonstrating some form of effort as to resolving own inquiry. At least how they generated `arr` at OP; at least where they copied `arr` from, if that is the case. – guest271314 Aug 07 '17 at 02:15
  • @m69 We have verified effort. Voted to "reopen". – guest271314 Aug 07 '17 at 02:18
  • @aznmunkey You can use stacksnippets https://stackoverflow.blog/2014/09/16/introducing-runnable-javascript-css-and-html-code-snippets/ to run the code at your Question – guest271314 Aug 07 '17 at 02:19
  • @aznmunkey: If the order of characters in string matters, then I have a solution which can get you all possible `palindromic substrings` from a given string. For getting all combinations which are palindromic, I think you would first need to generate all combinations of strings that can be formed from this string and then generate all the permutations of those substrings as well and then check each of them for palindrome. – CodeHunter Aug 07 '17 at 02:30

1 Answers1

2

If you want to generate just the palindromes (without first having to generate every possible combination of all the characters and then filtering out the non-palindromes), split the characters in the input into two groups, depending on how often they occur:

input:   racecarzz
singles: e
doubles: carz

Then, generate every combination with characters from doubles:

c, a, r, z, ca, cr, cz, ac, ar, az ... zrca, zrac  

Then, with each of these combinations, create 3 palindromes: one without repeating the last character, one repeating the last character, and one with the single character in the middle:

c    -> c, cc, cec
ca   -> cac, caac, caeac
car  -> carac, carrac, carerac
carz -> carzrac, carzzrac, carzezrac
...

If there are more than one singles, create palindromes with each of these singles:

car -> carac, carrac, carerac, carfrac, cargrac ...  

Don't forget to add the single characters by themselves; "e" is also a palindrome.

If a character occurs 3 times, add it once to the doubles and once to the singles. If it occurs 4 times, add it twice to the doubles, and so on... (This will create duplicate output; if you only want unique solutions, you'll have to avoid duplicates while generating the combinations, and check the last character in combinations against the singles while generating the palindromes.)


This is a code example of the basic version:

function splitInput(str) {
    var singles = [], doubles = [];
    for (var i in str) {
        var char = str.charAt(i);
        var pos = singles.indexOf(char);               // check if already in singles
        if (pos == -1) singles.push(char);             // add to singles
        else doubles.push(singles.splice(pos, 1)[0]);  // move to doubles
    }
    return {singles: singles, doubles: doubles};
}

function generateCombinations(set) {
    var combis = [];
    addChar([], set);               // start recursion with empty partial and full set
    return combis;

    function addChar(partial, set) {
        for (var i in set) {
            var setCopy = set.slice();
            var parCopy = partial.concat(setCopy.splice(i, 1)); // add char to partial
            combis.push(parCopy);
            if (setCopy.length) addChar(parCopy, setCopy);    // recurse if chars left
        }
    }
}

function generatePalindromes(combis, singles) {
    var palins = singles.slice();                      // each single is a palindrome
    for (var i in combis) {
        var pos = combis[i].length;
        var pal = combis[i].concat([' ']);             // add space for single
        pal = pal.concat(combis[i].reverse());         // add reverse
        for (var j in singles) {
            pal.splice(pos, 1, singles[j]);            // insert single in the middle
            palins.push(pal.join(''));
        }
        pal.splice(pos, 1); palins.push(pal.join('')); // remove single
        pal.splice(pos, 1); palins.push(pal.join('')); // remove repeated last char
    }
    return palins;
}

function palindromeCombinations(input) {
    var sets = splitInput(input);
    var combis = generateCombinations(sets.doubles);
    return generatePalindromes(combis, sets.singles);
}

document.write("racecarzz &rarr; " + palindromeCombinations("racecarzz"));

If characters can occur 3 or more times in the input, and you want to generate only unique solutions, adapt the code to:

  • When generating the combinations, skip duplicate characters when iterating over the set.
  • When generating the palindromes, skip the one without repeated last character if that last character is one of the singles.

This requires just a few lines to be changed:

function splitInput(str) {
    var singles = [], doubles = [];
    for (var i in str) {
        var char = str.charAt(i);
        var pos = singles.indexOf(char);               // check if already in singles
        if (pos == -1) singles.push(char);             // add to singles
        else doubles.push(singles.splice(pos, 1)[0]);  // move to doubles
    }
    return {singles: singles, doubles: doubles};
}

function generateCombinations(set) {
    var combis = [];
    addChar([], set);               // start recursion with empty partial and full set
    return combis;

    function addChar(partial, set) {
        for (var i = 0; i < set.length; i++) {              // instead of for i in set
            if (set.indexOf(set[i]) != i) continue;       // skip duplicate characters
            var setCopy = set.slice();
            var parCopy = partial.concat(setCopy.splice(i, 1)); // add char to partial
            combis.push(parCopy);
            if (setCopy.length) addChar(parCopy, setCopy);    // recurse if chars left
        }
    }
}

function generatePalindromes(combis, singles) {
    var palins = singles.slice();                      // each single is a palindrome
    for (var i in combis) {
        var pos = combis[i].length;
        var pal = combis[i].concat([' ']);             // add space for single
        pal = pal.concat(combis[i].reverse());         // add reverse
        for (var j in singles) {
            pal.splice(pos, 1, singles[j]);            // insert single in the middle
            palins.push(pal.join(''));
        }
        pal.splice(pos, 1); palins.push(pal.join('')); // remove single
        if (singles.indexOf(pal.splice(pos, 1)[0]) == -1) { // if last not in singles
            palins.push(pal.join(''));                 // without repeated last char
        }
    }
    return palins;
}

function palindromeCombinations(input) {
    var sets = splitInput(input);
    var combis = generateCombinations(sets.doubles);
    return generatePalindromes(combis, sets.singles);
}

document.write("rarerara &rarr; " + palindromeCombinations("rarerara"));
  • 1
    Like magic. Thanks! I added the following to sort the array by length and then alphabetically return dataSet.sort(function(a, b){ return a.length-b.length || a.localeCompare(b); }); – aznmunkey Aug 08 '17 at 04:32
  • @aznmunkey I added a code example that generates only unique solutions in case the input contains characters that occur 3 or more times. – m69's been on strike for years Aug 08 '17 at 12:11