Scrabble Scores with Streams

Viewed 227

I'm a beginner here trying to work out some stream syntax for one of my projects. I am currently having issues trying to find:

  1. the average score of all the words
  2. those word above average
  3. those words below average

How would I map my word value into a double that I can grab the average of for all of the words and display those averages? And how would I split the values to above and below average using the partitioningBy method? Keeping in mind that this has to be done via Streams.

Here is my code so far:

import java.util.Arrays;
import java.util.HashMap;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

// methods within a class

public static int scrapleVal(String word) {
    Map<Character, Integer> letterValues = new HashMap<>();
    letterValues.put('a', 1);
    letterValues.put('b', 3);
    letterValues.put('c', 3);
    letterValues.put('d', 2);
    letterValues.put('e', 1);
    letterValues.put('f', 4);
    letterValues.put('g', 2);
    letterValues.put('h', 4);
    letterValues.put('i', 1);
    letterValues.put('j', 8);
    letterValues.put('k', 5);
    letterValues.put('l', 1);
    letterValues.put('m', 3);
    letterValues.put('n', 1);
    letterValues.put('o', 1);
    letterValues.put('p', 3);
    letterValues.put('q', 10);
    letterValues.put('r', 1);
    letterValues.put('s', 1);
    letterValues.put('t', 1);
    letterValues.put('u', 1);
    letterValues.put('v', 8);
    letterValues.put('w', 4);
    letterValues.put('x', 8);
    letterValues.put('y', 4);
    letterValues.put('z', 10);

    return word.toLowerCase().chars().map(e -> letterValues.get((char)e)).sum();
}

public static void main(String[] args) {

    String [] words = {"Java", "program", "list", "string", "unix",
    "hours", "syntax", "error"};
    System.out.println("Top three words are: ");
    Stream.of(words).sorted((e1,e2)->scrapleVal(e2)-scrapleVal(e1)).limit(3).forEach
    (e->System.out.println(e+" : "+scrapleVal(e)));
    
    System.out.println("\nAverage value fo words is: ");
    Stream.of(words).sorted((e1,e2)->scrapleVal(e2)-scrapleVal(e1)).forEach
    (e->System.out.println(scrapleVal(e).average()));
}
1 Answers

To find the average scrapleValue, one way is to find the sum of all values and divide it by the total number of words. Ofcourse, the sum would be similar to the operation that you've performed inside your scrapleValue method.

What it would though need you to make things similar would be to mapToInt to get an IntStream where you could perform a sum or even directly an average. Hence the mapping would look like :

System.out.println("Average scraple value of words is: ");
double averageScrapleValue = Stream.of(words)
        .mapToInt(YourClass::scrapleVal)
        .average()
        .orElse(0.0);

Further note, when you want to sort words with their values, just compare them using the integer value returned by your method

.sorted(Comparator.comparingInt(YourClass::scrapleVal))

and to solve for getting the values below and above average, the hint in the right direction would be to look for "partioningBy" the average calculated in the above block.

Related