Próbuję rozwiązywać wyzwania CodeWars, ale mam z tym problem:

„Biorąc pod uwagę ciąg słów, musisz znaleźć słowo o najwyższej punktacji. Każda litera słowa otrzymuje punkty zgodnie z jej pozycją w alfabecie:

 a = 1, b = 2, c = 3 etc.

Musisz zwrócić najwyżej punktowane słowo jako ciąg. Jeśli dwa słowa mają taki sam wynik, zwróć słowo, które pojawiło się najwcześniej w oryginalnym ciągu. Wszystkie litery będą małymi literami, a wszystkie dane wejściowe będą prawidłowe ”.

Mój kod przeszedł 104 przypadki, ale w 1 przypadku się pomylił. Przypadek testowy z błędną odpowiedzią to

'what time are we climbing up the volcano' 

Według codewars - Oczekiwano: `` wulkan '', zamiast tego otrzymano: `` wspinaczka ''

Jakieś pomysły?

Link do problemu - https://www.codewars.com/kata/57eb8fcdf670e99d9b000272/train / javascript

 function high(x){
  let result = '', value =0, counterValue = 0; 

  let splittedArray = x.split(' ');

  splittedArray.map(splitItem => {
    counterValue = 0;

    let splitItemArray = splitItem.split('');

    splitItemArray.map(splitChar => { 
      counterValue += splitChar.charCodeAt();
    })

    if(counterValue>value){
      result = splitItem;
      value = counterValue;
    }
  });
  return result;
}
1
Mustafizur Rahman Choudhury 31 marzec 2020, 20:42

7 odpowiedzi

Najlepsza odpowiedź
function high(x) {
  const words = x.split(' ');
  const alphabetMap = {};
  for (let i='a'.charCodeAt(), j = 1; i <= 'z'.charCodeAt(); i++, j++) {
    alphabetMap[i] = j;
  }
  let highestScoringWord = { word: '', score: 0 };
  words.forEach(w => {
    const chars = w.split('');
    const sumOfChars = chars.reduce((count, char) => count + alphabetMap[char.charCodeAt()], 0);
    if (sumOfChars > highestScoringWord.score) {
      highestScoringWord = { word: w, score: sumOfChars };
    }
  });

  return highestScoringWord.word;
}

console.log(high('what time are we climbing up the volcano')) // volcano ;)
1
Vazgen 31 marzec 2020, 18:08

Rozwiązaniem jest użycie tablicy alfabetu i zaindeksowanie w niej pozycji znaku,

let al = `abcdefghijklmnopqrstuvwxyz`.split('')


   function high(x){
     let words = x.split(" ");
     let out = words.map(word => {
     let score = 0;
     let letters = word.split("");
     letters.map(c => {
      score += al.indexOf(c);
     })
     return [word, score];
    });

    out = out.sort((a,b) => { 
      if(a[1] > b[1]) return -1;
      else if(a[1] < b[1]) return 1; 
      else return 0;  });

return out[0][0];
}
1
Adarsh Hegde 31 marzec 2020, 18:13

Możesz użyć funkcji redukuj i obiektu, aby śledzić największą liczbę i odpowiednie słowo

function high(x){
  let mapper = [...`abcdefghijklmnopqurstuvwxyz`].reduce((op,inp,index)=>{
    op[inp] = index+1
    return op
  },{})
  return x.split(' ').reduce((op,inp)=>{
    let currentCount = 0;
    [...inp].forEach(v=>{
      currentCount += mapper[v]
    })
    if(currentCount > op.maxCount){
      op.maxCount = currentCount
      op.word = inp
    }
    return op
  }, {maxCount:0, word:''}).word
}

console.log(high('what time are we climbing up the volcano'), 'volcano'))
1
Code Maniac 31 marzec 2020, 17:55

Popełniłem błąd, nie licząc pozycji liter w alfabecie. Jeśli odejmę 96 od wartości ASCII, to obliczy a as 1, b as 2......

Więc rozwiązanie jest podane poniżej

 function high(x){
  let result = '', value =0, counterValue = 0; 

  let splittedArray = x.split(' ');

  splittedArray.map(splitItem => {
    counterValue = 0;

    let splitItemArray = splitItem.split('');

    splitItemArray.map(splitChar => { 
      counterValue += splitChar.charCodeAt()-96; // if I subtract 96 then it will calculate a as 1, b as 2......
    })

    if(counterValue>value){
      result = splitItem;
      value = counterValue;
    }
  });
  return result;
}
0
Mustafizur Rahman Choudhury 31 marzec 2020, 19:03

Metoda charCodeAt () zwraca liczbę całkowitą z przedziału od 0 do 65535 reprezentującą jednostkę kodu UTF-16 o podanym indeksie.

Zasadniczo musisz przekonwertować go na alfabet z dużymi literami i odjąć wartość charCodeAt o 64, co da ci pozycję ciągu w alfabecie.

Sprawdź to:

function high(x) {
    let splittedArray = x.split(' ');
    let splitChar = splittedArray.map(el => el.split(''));
    let charValue = splitChar.map(el => {
        let counter = 0;
        el.map(element => counter += element.toUpperCase().charCodeAt() - 64);
        return counter;
    });
    let largest = 0;
    let largestIndex;
    for (let i = 0; i < charValue.length; i++) {
        if (charValue[i] > largest) {
            largest = charValue[i];
            largestIndex = i;
        }
    }
    return splittedArray[largestIndex];
}
0
Shahriar Shojib 31 marzec 2020, 18:51

Pomysł:

  • Przechowuj wartości punktacji w tabeli, aby ułatwić wyszukiwanie
  • podziel zdania na słowa za pomocą znaków niealfabetycznych
  • uzyskać punktację każdego słowa, najpierw obliczając wyniki poszczególnych znaków, a następnie sumując je razem (za pomocą funkcji zmniejsz).
  • Nie zapomnij posortować według oryginalnej pozycji, jeśli wyniki są takie same, zrób to, śledząc pierwotną pozycję.

Demo: https://jsfiddle.net/9xkfqh1m/

const ScoreTable = {
  "a": 1,
  "b": 2,
  "c": 3,
  "d": 4,
  "e": 5,
  "f": 6,
  "g": 7,
  "h": 8,
  "i": 9,
  "j": 10,
  "k": 11,
  "l": 12,
  "m": 13,
  "n": 14,
  "o": 15,
  "p": 16,
  "q": 17,
  "r": 18,
  "s": 19,
  "t": 20,
  "u": 21,
  "v": 22,
  "w": 23,
  "x": 24,
  "y": 25,
  "z": 26
};

// non-ascii letters = 0
function CharScore(char) {
  const lowerCaseChar = char.toLowerCase();
  return lowerCaseChar in ScoreTable ? ScoreTable[lowerCaseChar] : 0;
}

function WordScore(word) {
  return word.split("").reduce((score, char) => {
    return score + CharScore(char);
  }, 0);
}

function SplitOnNonAlphabeticCharacters(str) {
  return str.split(/[^a-zA-Z]+/gm);
}

function high(str){
  const scoreObjects = SplitOnNonAlphabeticCharacters(str)        // split into words
  .map((word, index) => {                                         // map our words into an object with its score and original position
    return {
      text: word,
      score: WordScore(word),
      originalPosition: index
    };
  }).sort((word1, word2) => {                                        // sort
    return word2.score - word1.score                                 // highest score first
                ||  word1.originalPosition - word2.originalPosition; // if score same, earliest original position in string
  });

  return scoreObjects.length > 0 ? scoreObjects[0].text : null;   // return word by the highest score (or earliest original position), or null
}

0
Asher Garland 31 marzec 2020, 18:34

Jestem zdezorientowany Twoją linią counterValue += splitChar.charCodeAt();. Nie rozumiem, jak splitChar.charCodeAt() przekłada się na 1-26 czyli pozycję liter w alfabecie. „Każda litera słowa jest punktowana zgodnie z jej pozycją w alfabecie”

Udało mi się sprawić, że Twój kod będzie działał, robiąc dwie rzeczy:

  1. Dodaj mapę, aby zapisać wartość każdej litery alfabetu. Jestem pewien, że można to zrobić na wiele sposobów, ale takie było moje podejście:
let letterValues = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10, k: 11, l: 12, m: 13, n: 14, o: 15, p: 16, q: 17, r: 18, s: 19, t: 20, u: 21, v: 22, w: 23, x: 24, y: 25, z: 26 };
  1. A potem użyj tego w counterValue += splitChar.charCodeAt(); jako counterValue += letterValues[letter];
0
Jason Lydon 31 marzec 2020, 18:16