-3

Try to give an alternative in this question WITHOUT LOOPING! Just using indexOf and some integer math

Get coordinates of an element in multidimentional array in Javascript

The code below seemed promising but fails.

Anyone with better math skills feel like fixing it?

var letterVariations = [ 
        [' ','0','1','2','3','4','5','6','7','8','9'],
        ['A','a','B','b','C','c','D','d','E','e',';'],
        ['Â','â','F','f','G','g','H','h','Ê','ê',':'],
        ['À','à','I','i','J','j','K','k','È','è','.'],
        ['L','l','Î','î','M','m','N','n','É','é','?'],
        ['O','o','Ï','ï','P','p','Q','q','R','r','!'],
        ['Ô','ô','S','s','T','t','U','u','V','v','“'],
        ['W','w','X','x','Y','y','Ù','ù','Z','z','”'],
        ['@','&','#','[','(','/',')',']','+','=','-'],
    ];

var string = JSON.stringify(letterVariations);
var pos = string.indexOf("u")
console.log(Math.floor((pos/10)%9),pos%10)

// fails, how to fix?
pos = string.indexOf("M")
console.log(Math.floor((pos/10)%9),pos%10)
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • What are you trying to do with "`% 8`"? – Scott Sauyet Mar 13 '19 at 15:49
  • JSON.strinigfy gives you string like `[[" ","0","1","2","3","4","5","6","7","8","9"],["A","a","B","b","C","c","D","d","E","e",";"]...`, you can't search here, it's better to use `letterVariations.toString()` – AlexOwl Mar 13 '19 at 15:49
  • Divide with width and height to get the pos – mplungjan Mar 13 '19 at 15:50
  • 1
    Well, that's an 11 x 9 grid, not 10 x 8. – Scott Sauyet Mar 13 '19 at 15:58
  • 1
    For the `x` position, I think you can try to proportionate the value to the length of the string. Example: `u` has index 307, using: `Math.floor((pos*11)/string.length)` you can get the `x` position, which is 8 in that case. It's 11 because it's an 11x9 grid. I'm not sure how you can get the Y value though. – briosheje Mar 13 '19 at 16:00
  • @AlexOwl has the right problem. The index of `M` in the string is 203, this includes all the quotes and the `[, ]` characters. It's not the 203rd index as the array is indexed. Consider the array `let r = ['m']` if you stringily that and look for the index of `m` you will get 2 not zero. – Mark Mar 13 '19 at 16:02
  • I don't know, something like that should work: https://jsfiddle.net/gwfr5m21/ I'm not a math dude, but using floor for X and ceil for Y seems to work. A thousand unit tests would help here. Perhaps some tweaks are necessary, but it may be a good starting point – briosheje Mar 13 '19 at 16:03
  • I was also playing with ceil and floor – mplungjan Mar 13 '19 at 16:04
  • @briosheje you can't find right index in `JSON.stringify` string – AlexOwl Mar 13 '19 at 16:04
  • @mplungjan check out my answer! – AlexOwl Mar 13 '19 at 16:05
  • 1
    @AlexOwl mind explaining why? JSON.stringify does not add things arbitrarely and, since the length of each item of the array is always the same, you should be able to get informations back. Besides, I think the original question is to **fix** the code he provided by keeping the logic of what is currently written. – briosheje Mar 13 '19 at 16:05
  • @briosheje JSON.stringify adds braces and quotes like `[["1","2"], ["3","4"]]` - you can't get right position using `.infdexOf()` on such string – AlexOwl Mar 13 '19 at 16:09
  • @AlexOwl That's always proportional, though. I don't think it's **impossible** to actually get the right index, I think the question is rather **how much complex** it is. – briosheje Mar 13 '19 at 16:10
  • @briosheje to get plain string of symbols he can use `.toString().replace(/,/g, '')` – AlexOwl Mar 13 '19 at 16:10
  • @AlexOwl assuming all entries are only one character. – Mark Mar 13 '19 at 16:11
  • It boggles my mind why someone would care so much about this question to vote it down – mplungjan Jun 25 '19 at 04:44
  • And again....... – mplungjan Dec 11 '22 at 08:50

5 Answers5

2

function findPos(array, symbol) {
  const string = array.toString().replace(/,/g, '');
  const pos = string.indexOf(symbol)

  const d = (array[0] || []).length

  const x = pos % d;
  const y = Math.floor(pos / d)

  return { x, y }
}

const array = [
  [' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
  ['A', 'a', 'B', 'b', 'C', 'c', 'D', 'd', 'E', 'e', ';'],
  ['Â', 'â', 'F', 'f', 'G', 'g', 'H', 'h', 'Ê', 'ê', ':'],
  ['À', 'à', 'I', 'i', 'J', 'j', 'K', 'k', 'È', 'è', '.'],
  ['L', 'l', 'Î', 'î', 'M', 'm', 'N', 'n', 'É', 'é', '?'],
  ['O', 'o', 'Ï', 'ï', 'P', 'p', 'Q', 'q', 'R', 'r', '!'],
  ['Ô', 'ô', 'S', 's', 'T', 't', 'U', 'u', 'V', 'v', '“'],
  ['W', 'w', 'X', 'x', 'Y', 'y', 'Ù', 'ù', 'Z', 'z', '”'],
  ['@', '&', '#', '[', '(', '/', ')', ']', '+', '=', '-'],
];


console.log(findPos(array,' ')) //=> [0, 0]
console.log(findPos(array,'M')) //=> [4, 4]
console.log(findPos(array,'u')) //=> [6, 7]
console.log(findPos(array,'-')) //=> [8, 10]
mplungjan
  • 169,008
  • 28
  • 173
  • 236
AlexOwl
  • 869
  • 5
  • 11
  • What happens if one of the entries is more than one character? – Mark Mar 13 '19 at 16:10
  • @MarkMeyer it brokes) You need to use normal solution like above to handle such cases – AlexOwl Mar 13 '19 at 16:12
  • Oh, ok, that's interesting. Mind explaining how X and Y are calculated? That answers the question anyway. Of course, elements with more than one character would break the algorithm but still, I think this answers the question. – briosheje Mar 13 '19 at 16:16
2

You could join the strings and use the length of the inner array as value for divisioin or for the remainder operator. This works only for strings with a single character.

var letterVariations = [
        [' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
        ['A', 'a', 'B', 'b', 'C', 'c', 'D', 'd', 'E', 'e', ';'],
        ['Â', 'â', 'F', 'f', 'G', 'g', 'H', 'h', 'Ê', 'ê', ':'],
        ['À', 'à', 'I', 'i', 'J', 'j', 'K', 'k', 'È', 'è', '.'],
        ['L', 'l', 'Î', 'î', 'M', 'm', 'N', 'n', 'É', 'é', '?'],
        ['O', 'o', 'Ï', 'ï', 'P', 'p', 'Q', 'q', 'R', 'r', '!'],
        ['Ô', 'ô', 'S', 's', 'T', 't', 'U', 'u', 'V', 'v', '“'],
        ['W', 'w', 'X', 'x', 'Y', 'y', 'Ù', 'ù', 'Z', 'z', '”'],
        ['@', '&', '#', '[', '(', '/', ')', ']', '+', '=', '-']
    ],
    string = letterVariations.map(a => a.join('')).join(''),
    pos = string.indexOf("u");

console.log(Math.floor(pos / 11), pos % 11);

pos = string.indexOf("M")
console.log(Math.floor(pos / 11), pos % 11);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

This produces the correct result. There is no need to stringify, you can flatten the arrays and use indexOf to get the position:

var letterVariations = [
  [' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
  ['A', 'a', 'B', 'b', 'C', 'c', 'D', 'd', 'E', 'e', ';'],
  ['Â', 'â', 'F', 'f', 'G', 'g', 'H', 'h', 'Ê', 'ê', ':'],
  ['À', 'à', 'I', 'i', 'J', 'j', 'K', 'k', 'È', 'è', '.'],
  ['L', 'l', 'Î', 'î', 'M', 'm', 'N', 'n', 'É', 'é', '?'],
  ['O', 'o', 'Ï', 'ï', 'P', 'p', 'Q', 'q', 'R', 'r', '!'],
  ['Ô', 'ô', 'S', 's', 'T', 't', 'U', 'u', 'V', 'v', '“'],
  ['W', 'w', 'X', 'x', 'Y', 'y', 'Ù', 'ù', 'Z', 'z', '”'],
  ['@', '&', '#', '[', '(', '/', ')', ']', '+', '=', '-'],
];

var flattened = letterVariations.flat()

var findLetter = function(letter) {
  var pos = flattened.indexOf(letter),
    x = Math.floor((pos / 10) % 8),
    y = (pos - (pos % 11)) / 11;
  return {
    letter: letter,
    x: x,
    y: y
  }
}
console.log(findLetter(' ')) //=> [0, 0]
console.log(findLetter('M')) //=> [4, 4]
console.log(findLetter('u')) //=> [6, 7]
console.log(findLetter('-')) //=> [8, 10]
mplungjan
  • 169,008
  • 28
  • 173
  • 236
GluePear
  • 7,244
  • 20
  • 67
  • 120
1

Here is one version of that:

var letterVariations = [ 
  [' ','0','1','2','3','4','5','6','7','8','9'],
  ['A','a','B','b','C','c','D','d','E','e',';'],
  ['Â','â','F','f','G','g','H','h','Ê','ê',':'],
  ['À','à','I','i','J','j','K','k','È','è','.'],
  ['L','l','Î','î','M','m','N','n','É','é','?'],
  ['O','o','Ï','ï','P','p','Q','q','R','r','!'],
  ['Ô','ô','S','s','T','t','U','u','V','v','“'],
  ['W','w','X','x','Y','y','Ù','ù','Z','z','”'],
  ['@','&','#','[','(','/',')',']','+','=','-'],
];

const findLetterIn = letterVariations => {
  const width = letterVariations[0].length * 4 + 2;
  const alpha = JSON.stringify(letterVariations)

  return (char, pos = alpha.indexOf(char)) => pos > -1 
    ? [Math.floor((pos - 1) / width), (((pos - 1) % width) - 2)/4]
    : [-1, -1]
}

const findLetter = findLetterIn (letterVariations)

console.log(findLetter(' ')) //=> [0, 0]
console.log(findLetter('M')) //=> [4, 4]
console.log(findLetter('u')) //=> [6, 7]
console.log(findLetter('-')) //=> [8, 10]

Here width has to do with row width.

The 4s have to do with u ~> "u", The + 2 has to do with adding [ and ] to the beginning and end (as well as an additional , after the ], but removing one before it.) The - 1 has to do with ignoring the initial [ and the - 2 has to do with removing the leading ," or, for the first one, the leading [".

You can switch to 1-based indices by adding 1 to both element of the returned array.

mplungjan
  • 169,008
  • 28
  • 173
  • 236
Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103
0

Based on @GluePear answer

You can even use multi-chars in this solution

function findPos(array, symbol) {
  const string = array.flat();
  const pos = string.indexOf(symbol)
  
  const d = (array[0] || []).length
  
  const x = pos % d;
  const y = Math.floor(pos / d)

  return { x, y }
}

const array = [ 
  [' ','0','1','2','3','4','5','6','7','8','9'],
  ['A','a','B','b','C','c','D','d','E','e',';'],
  ['Â','â','F','f','G','g','H','h','Ê','ê',':'],
  ['À','à','I','i','J','j','K','k','È','è','.'],
  ['L','l','Î','î','M','m','N','n','É','é','?'],
  ['O','o','Ï','ï','P','p','Q','q','R','r','!'],
  ['Ô','ô','S','s','T','t','U','u','V','v','“'],
  ['W','w','X','x','Y','y','Ù','ù','Z','z','”'],
  ['@','&','#','[','(','/',')',']','+','=','-'],
 ];
  
  
console.log(findPos(array, '-'))
AlexOwl
  • 869
  • 5
  • 11