简体   繁体   中英

How to find all possible combinations in 2dArray with given string

let's say I have simple 2d array

let array2d = [
   ['a','a','b'],
   ['a','b','c'],
   ['a','c','a']
]

and a simple string with random length, for example:

let string = 'abc';

How can I find all possible combinations of that string in given array where order matters?

so in this example result should be like that:

result = [
  [
     ['*','a','*'],
     ['a','b','*'],
     ['a','c','a']
  ],
  [
     ['*','a','*'],
     ['a','b','c'],
     ['a','*','a']
  ],
  [
     ['*','a','b'],
     ['a','*','*'],
     ['a','c','a']
  ],
  [
     ['*','a','b'],
     ['a','*','c'],
     ['a','*','a']
  ],
  [
     ['a','*','*'],
     ['a','b','*'],
     ['a','c','a']
  ],
  [
     ['a','*','*'],
     ['a','b','c'],
     ['a','*','a']
  ],
  [
     ['a','*','b'],
     ['a','*','*'],
     ['a','c','a']
  ],
  [
     ['a','*','b'],
     ['a','*','c'],
     ['a','*','a']
  ],
  [
     ['a','a','b'],
     ['*','*','*'],
     ['a','c','a']
  ],
  [
     ['a','a','b'],
     ['*','*','c'],
     ['a','*','a']
  ],
]

I have some thoughts on this one but i'm really not sure about those.

  1. I thought about using array of coordinates for each letter in string, but I haven't figured out how to use it for random length of string
  2. It might be easier to flatten array to 1 dimension and find indexes there. After that return the array back to 2 dimensions.

Fun little exercise actually, your thought nr. 2 was in the right direction. What I did was splitting up the task in two, 1. finding all the character locations, 2. recursively put together all the combinations.

 let array2d = [["a", "a", "b"], ["a", "b", "c"], ["a", "c", "a"]]; let string = "abc"; var chars = string.split(""); //Convert string to [ 'a', 'b', 'c' ] var dataAsString = array2d.map(function(d) { return d[0] + d[1] + d[2]; }); let concatedArrayString = dataAsString.join(""); //Convert array2d to "aababcaca" let locations = findAllCharLocations(chars, concatedArrayString); // returns { a: [ 0, 1, 3, 6, 8 ], b: [ 2, 4 ], c: [ 5, 7 ] } var result = []; recursiveFindAllCombinations(0, array2d, locations, []); console.log(result); // The result is: // [ [ [ '*', 'a', '*' ], [ 'a', 'b', '*' ], [ 'a', 'c', 'a' ] ], // [ [ '*', 'a', '*' ], [ 'a', 'b', 'c' ], [ 'a', '*', 'a' ] ], // [ [ '*', 'a', 'b' ], [ 'a', '*', '*' ], [ 'a', 'c', 'a' ] ], // [ [ '*', 'a', 'b' ], [ 'a', '*', 'c' ], [ 'a', '*', 'a' ] ], // [ [ 'a', '*', '*' ], [ 'a', 'b', '*' ], [ 'a', 'c', 'a' ] ], // [ [ 'a', '*', '*' ], [ 'a', 'b', 'c' ], [ 'a', '*', 'a' ] ], // [ [ 'a', '*', 'b' ], [ 'a', '*', '*' ], [ 'a', 'c', 'a' ] ], // [ [ 'a', '*', 'b' ], [ 'a', '*', 'c' ], [ 'a', '*', 'a' ] ], // [ [ 'a', 'a', '*' ], [ '*', 'b', '*' ], [ 'a', 'c', 'a' ] ], // [ [ 'a', 'a', '*' ], [ '*', 'b', 'c' ], [ 'a', '*', 'a' ] ], // [ [ 'a', 'a', 'b' ], [ '*', '*', '*' ], [ 'a', 'c', 'a' ] ], // [ [ 'a', 'a', 'b' ], [ '*', '*', 'c' ], [ 'a', '*', 'a' ] ], // [ [ 'a', 'a', '*' ], [ 'a', 'b', '*' ], [ '*', 'c', 'a' ] ], // [ [ 'a', 'a', '*' ], [ 'a', 'b', 'c' ], [ '*', '*', 'a' ] ], // [ [ 'a', 'a', 'b' ], [ 'a', '*', '*' ], [ '*', 'c', 'a' ] ], // [ [ 'a', 'a', 'b' ], [ 'a', '*', 'c' ], [ '*', '*', 'a' ] ], // [ [ 'a', 'a', '*' ], [ 'a', 'b', '*' ], [ 'a', 'c', '*' ] ], // [ [ 'a', 'a', '*' ], [ 'a', 'b', 'c' ], [ 'a', '*', '*' ] ], // [ [ 'a', 'a', 'b' ], [ 'a', '*', '*' ], [ 'a', 'c', '*' ] ], // [ [ 'a', 'a', 'b' ], [ 'a', '*', 'c' ], [ 'a', '*', '*' ] ] ] //Recursivly find all the combinations of a character at index, character array which is modified, function recursiveFindAllCombinations( charIndex, characterArray, locations, currentCharIndexArray ) { //Copy the character array since we modifying it but dont want the other references to change let charArray = characterArray.map(function(arr) { return arr.slice(); }); //The current char let char = chars[charIndex]; //For each location the character is found for (var index = 0; index < locations[char].length; index++) { //Copy the char index array var newCharIndexArray = currentCharIndexArray.slice(); var isAnOption = true; //Check and see if the new value is valid compared to the already choosen values. for (var check = 0; check < newCharIndexArray.length; check++) { let value = newCharIndexArray[check]; if (value > locations[char][index]) { isAnOption = false; } } if (isAnOption) { //Example the first 'a' is found at // x = 0 % 3 = 0 // y = Math.floor(0 / 3) = 0 let x = locations[char][index] % array2d.length; let y = Math.floor(locations[char][index] / array2d.length); //Paint that location as found charArray[y][x] = "*"; newCharIndexArray.push(locations[char][index]); //If there is more chars call recursively if (chars[charIndex + 1]) { //Use the next character in line recursiveFindAllCombinations( charIndex + 1, charArray, locations, newCharIndexArray ); } else { //Since no more recursiv calls to do, push a copy of the charArray. result.push( charArray.map(function(arr) { return arr.slice(); }) ); } //Reset the charArray charArray[y][x] = char; } } } //Find all the char locations //Example returning : { a: [ 0, 1, 3, 6, 8 ], b: [ 2, 4 ], c: [ 5, 7 ] } function findAllCharLocations(chars, concatedArrayString) { let charsCopy = chars.slice(0); //Make a copy on the char array. var locations = {}; //Initiate the locations array { a: [], b: [], c: [] } for (var charIndex = 0; charIndex < charsCopy.length; charIndex++) { locations[charsCopy[charIndex]] = []; } var counter = 0; //As long as we havent found all the chars in 2d array continue while (counter != chars.length) { //Store the chars which we are done with and remove them after the loop. var charsToRemove = []; //Go through each char. for (var index = 0; index < charsCopy.length; index++) { let char = charsCopy[index]; //Get the last index of that specific character, if nothing found yet this will be NaN. let lastIndexOfChar = locations[char][locations[char].length - 1]; //Get the index of the next character let indexOfChar = concatedArrayString.indexOf(char, lastIndexOfChar + 1); //If a character was found push it to the location array if (indexOfChar != -1) { locations[char].push(indexOfChar); } else { //Since the character was not found remove it from the char array and let our counter know one less char to find. counter++; charsToRemove.push(char); } } //Do the removal of characters no longer found in the string. for (var index = 0; index < charsToRemove.length; index++) { charsCopy.splice(charsCopy.indexOf(charsToRemove[index]), 1); } } return locations; } 

I dont think this is the optimal way of doing it, so if speed is of the essence, you might need to optimize it, or if anybody else can help out?

I dont think I implemented the function recursiveFindAllCombinations correctly, since it uses the global variable result, I just didn't manage to figure out how to incorporate it with the recursive function, let me know if you can!

Edit #1

Changed the function recursiveFindAllCombinations to take into account the values must be in the desired order.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM