Reputation: 353
I am doing the following coding challenge in java:
/**
* 4. Given a word, compute the scrabble score for that word.
*
* --Letter Values-- Letter Value A, E, I, O, U, L, N, R, S, T = 1; D, G = 2; B,
* C, M, P = 3; F, H, V, W, Y = 4; K = 5; J, X = 8; Q, Z = 10; Examples
* "cabbage" should be scored as worth 14 points:
*
* 3 points for C, 1 point for A, twice 3 points for B, twice 2 points for G, 1
* point for E And to total:
*
* 3 + 2*1 + 2*3 + 2 + 1 = 3 + 2 + 6 + 3 = 5 + 9 = 14
*
* @param string
* @return
*/
My idea is to insert all these letters in a hash map by doing something like this:
map.add({A,,E,I,O,U,L,N,R,S,T}, 1);
Is there any way to do this in java?
Upvotes: 1
Views: 3399
Reputation: 166
One line:
Map<String, Integer> map = Stream.of( "A", "E", "I", "O", "U", "L", "N", "R", "S", "T" ).collect( Collectors.toMap( Function.identity(), o -> 1 ) );
Or if you already have a list of strings
Collection<String> chars = new ArrayList<>();
// Add to collection
Map<String, Integer> map = chars.stream().collect( Collectors.toMap( Function.identity(), o -> 1 ) );
You can use the same method to add other keys with the same value
map.addAll( Stream.of( "F", "H", "V", "W", "Y" ).collect( Collectors.toMap( FUnction.identity(), o -> 4 );
Ultimately, it would be best to use a helper function for readability
private Map<String, Integer> mapScores( int score, String... letter ) {
return Stream.of( letter ).collect( Collectors.toMap( Function.identity(), o -> score ) );
}
Map<String, Integer> map = new ConcurrentHashMap<>();
map.putAll( mapScores( 1, "A", "E", "I", "O", "U", "L", "N", "R", "S", "T" ) );
map.putAll( mapScores( 2, "D", "G" ) );
map.putAll( mapScores( 3, "B", "C", "M", "P" ) );
map.putAll( mapScores( 4, "F", "H", "V", "W", "Y" ) );
map.put( "K", 5 );
map.putAll( mapScores( 8, "J", "X" ) );
map.putAll( mapScores( 10, "Q", "Z" ) );
Upvotes: 0
Reputation: 4967
You said in your comments that you would like to be able to add all these entries in a single statement. While Java is not a great language for doing things like this in a single statement, it can be done if you are really determined to do so. For example:
Map<Character, Integer> scores =
Stream.of("AEIOULNRST=1","DG=2","BCMP=3","FHVWY=4" /* etc */ )
.flatMap(line -> line.split("=")[0].chars().mapToObj(c -> new Pair<>((char)c, Integer.parseInt(line.split("=")[1]))))
.collect(Collectors.toMap(Pair::getKey, Pair::getValue));
System.out.println("C = " + scores.get('C'));
Output:
C = 3
In the code above, I first build a stream of all the entries (as Pairs), and collect them into a map.
Note:
The Pair class I have used above is from javafx.util.Pair
. However you could just as easily use AbstractMap.SimpleEntry
, your own Pair class, or any collection data type capable of holding two Objects.
A Better Approach
Another idea would be to write your own helper method. This method could be put into a class which contains similar helper methods. This approach would be more idiomatic, easier to read, and thus easier to maintain.
public enum MapHelper {
; // Utility class for working with maps
public static <K,V> void multiKeyPut(Map<? super K,? super V> map, K[] keys, V value) {
for(K key : keys) {
map.put(key, value);
}}}
Then you would use it like this:
Map<Character, Integer> scores = new HashMap<>();
MapHelper.multiKeyPut(scores, new Character[]{'A','E','I','O','U','L','N','R','S','T'}, 1);
MapHelper.multiKeyPut(scores, new Character[]{'D','G'}, 2);
MapHelper.multiKeyPut(scores, new Character[]{'B','C','M','P'}, 3);
/* etc */
Upvotes: 4
Reputation: 3609
I think it's not a good idea to store list of more characters as keys (take a look at this question) and single value corresponding to this key, but if you really need that, you might want to give a try to this:
Map<ArrayList<Character>, Integer> map = new HashMap<>();
map.put(new ArrayList<Character>(Arrays.asList('A', 'E',...)), 1);
map.put(new ArrayList<Character>(Arrays.asList('D', 'G',...)), 2);
Personally, I would suggest using HashMap<Integer, ArrayList<Character>>
- keys are "values" of a set of letters (e. g. key would be 1 for ArrayList
containg letters: A, E, etc.), as a value corresponding to that Integer key could be ArrayList
storing characters (A, E,...). You can achieve that result with:
Map<Integer, ArrayList<Character>> map = new HashMap<>();
map.put(1, new ArrayList<Character>(Arrays.asList('A', 'E',...)));
map.put(2, new ArrayList<Character>(Arrays.asList('D', 'G',...)));
Upvotes: 0
Reputation: 312267
Map
has no methods that operate on multiple keys, but you could stream a list of these characters and call forEach
:
Map<Character, Integer> scores = new HashMap<>();
Stream.of('A', 'E', 'I', 'O', 'U', 'L', 'N', 'R', 'S', 'T')
.forEach(c -> scores.put(c, 1));
Stream.of('D', 'G').forEach(c -> scores.put(c, 2));
// etc...
Upvotes: 0
Reputation: 151
Take an array of length 26, each element representing an alphabet's score. So, we will have an array like this:-
alphabetScore = [1,3,3,2,.....................];
Now, iterate over the word, and keep adding the score of the current alphabet in the total score.
Upvotes: 1