stringscalascoringhighest

How to find a highest scoring word inside a string?


I am doing some of the CodeWars challenges again.

I have a problem with this one:

"Given a string of words, you need to find the highest scoring word.

Each letter of a word scores points according to its position in the alphabet: a = 1, b = 2, c = 3 etc.

You need to return the highest scoring word as a string.

If two words score the same, return the word that appears earliest in the original string.

All letters will be lowercase and all inputs will be valid."

I've already looked up the solutions on SO, and have used the idea of one person(although I did change it a bit).

It still does not work.

Any ideas?

object Scoring {

def high(s: String): String = {

        var max = 0
                var whichWord = 0     
                var x = 0
                var y = new Array[Int](100)


                for(word <- s.split(" ")){
                    for(letter <- word) letter match{
                    case 'a' => y(x)+=1
                    case 'b' => y(x)+=2
                    case 'c' => y(x)+=3
                    case 'd' => y(x)+=4
                    case 'e' => y(x)+=5
                    case 'f' => y(x)+=6
                    case 'g' => y(x)+=7
                    case 'h' => y(x)+=8
                    case 'i' => y(x)+=9
                    case 'j' => y(x)+=10
                    case 'k' => y(x)+=11
                    case 'l' => y(x)+=12
                    case 'm' => y(x)+=13
                    case 'n' => y(x)+=14
                    case 'o' => y(x)+=15
                    case 'p' => y(x)+=16
                    case 'q' => y(x)+=17
                    case 'r' => y(x)+=18
                    case 's' => y(x)+=19
                    case 't' => y(x)+=20
                    case 'u' => y(x)+=21
                    case 'v' => y(x)+=22
                    case 'w' => y(x)+=23
                    case 'x' => y(x)+=24
                    case 'y' => y(x)+=25
                    case 'z' => y(x)+=26

                    }
                    x +=1
                }

        for(x <- 0 until y.length){

            if(y(x) > max)
            { 
                max = y(x)
                        whichWord = x
            }
        }

        s.substring(whichWord-1, whichWord)
}
}

Here are the tests:

test Results:

  RandomTestSpec
     high("ykvhorsqve kfkq jhjibercdptf efevxax ccr vnsmumqby jwhxvamegupfcj lierziuopbcsutm") should return "lierziuopbcsutm"
    Test Failed

    "[s]" was not equal to "[lierziuopbcsutm]"

 Stack Trace

    Completed in 34ms
     high("skwwwm") should return "skwwwm"

Test Failed

String index out of range: -1
 Stack Trace
Completed in 1ms
 high("a") should return "a"
Test Failed

String index out of range: -1
 Stack Trace
Completed in 1ms
 high("gykoialocufuc wcdwuxksqk bvapztcnqwx") should return "bvapztcnqwx"
Test Failed

"[y]" was not equal to "[bvapztcnqwx]"
 Stack Trace
Completed in 1ms
 high("gdhfoonwtih xbvsiaqhsesl obrndpz nxt inkklyo lf oyoadxqhuys lbqr oxbqq bopalqknjxvpg") should return "oyoadxqhuys"
Test Failed

"o[]" was not equal to "o[yoadxqhuys]"
 Stack Trace
Completed in 1ms
 high("bbzlmqhsypato pfufsi ryu oboklfa iigha h m") should return "bbzlmqhsypato"
Test Failed

String index out of range: -1
 Stack Trace
Completed in 1ms
 high("dbtfwvhk kadarmvldjhkx dgxffryldcxodtn hoffibiayxriqe gtqzeuywpgc nqlgvudy") should return "dgxffryldcxodtn"
Test Failed

"[b]" was not equal to "[dgxffryldcxodtn]"
 Stack Trace
Completed in 1ms
 high("vhyxdefryeznlkz fcaenzsnoxsn phdqu zjbbbybjmdn dbfhvxwnusz dqbqskfbwuomzsl ogsdioilk") should return "vhyxdefryeznlkz"
Test Failed

String index out of range: -1
 Stack Trace
 high("yqbzfuprmezbgee yxsewucg u") should return "yqbzfuprmezbgee"
Test Failed
String index out of range: -1
 Stack Trace
Completed in 1ms
 high("zifha") should return "zifha"
Test Failed

String index out of range: -1
 Stack Trace
 high("moroydyolj tcfpokvitzwzor rnzeacau") should return "tcfpokvitzwzor"
Test Failed

"[m]" was not equal to "[tcfpokvitzwzor]"
 Stack Trace
Completed in 1ms
 high("jhieih m") should return "jhieih"
Test Failed

String index out of range: -1
 Stack Trace
 high("yn ounbzw wk eldpjyikbfs nzm") should return "eldpjyikbfs"
Test Failed

"[ ]" was not equal to "[eldpjyikbfs]"
 Stack Trace
Completed in 1ms

Solution

  • In Scala it is easier/ (better) to use the functions that are provided in the collections.

    In your example - here a possibility:

    First to add the scoring you can use this:

    "hello".map(_.toInt).sum // 532
    

    This returns the sum of all the chars as Int values (a=97; ...; z=122)

    To find the highest weight you can use foldLeft, starting from "".

    scala> List("a", "ab","ba").foldLeft("")((a,b)=> higher(a,b))
    res10: String = ab
    

    Here the complete higher function:

    def higher(a:String, b:String):String=
      if(a.map(_.toInt).sum >= b.map(_.toInt).sum) a else b
    

    There are many cool possibilities to do this with collection functions - don't use mutable state! That is an important reason why to switch to Scala.

    Update: After playing on https://www.codewars.com I found a bug and a shorter solution:

    s.split(" ").map(w => (w, w.map(_.toInt - 96).sum)).maxBy(_._2)._1