content: /*
   * Copyright (C) 2019 Jos Paumard
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   *
   */
  
  package hu.akarnokd.comparison.scrabble;
  
  import java.util.*;
  import java.util.Map.Entry;
  import java.util.concurrent.TimeUnit;
  
  import org.openjdk.jmh.annotations.*;
  
  /**
   * Shakespeare plays Scrabble with Ix optimized.
   * @author José
   * @author akarnokd
   */
  public class ShakespearePlaysScrabbleWithDirect extends ShakespearePlaysScrabble {
  
      @SuppressWarnings("unused")
      @Benchmark
      @BenchmarkMode(Mode.SampleTime)
      @OutputTimeUnit(TimeUnit.MILLISECONDS)
      @Warmup(
          iterations = 5, time = 1
      )
      @Measurement(
          iterations = 5, time = 1
      )
      @Fork(1)
      public List<Entry<Integer, List<String>>> measureThroughput() throws InterruptedException {
  
          TreeMap<Integer, List<String>> treemap = new TreeMap<Integer, List<String>>(Comparator.reverseOrder());
  
          for (String word : shakespeareWords) {
              if (scrabbleWords.contains(word)) {
                  HashMap<Integer, MutableLong> wordHistogram = new LinkedHashMap<>();
                  for (int i = 0; i < word.length(); i++) {
                      MutableLong newValue = wordHistogram.get((int)word.charAt(i)) ;
                      if (newValue == null) {
                          newValue = new MutableLong();
                          wordHistogram.put((int)word.charAt(i), newValue);
                      }
                      newValue.incAndSet();
                  }
                  long sum = 0L;
                  for (Entry<Integer, MutableLong> entry : wordHistogram.entrySet()) {
                      sum += Long.max(0L, entry.getValue().get() -
                                  scrabbleAvailableLetters[entry.getKey() - 'a']);
                  }
                  boolean b = sum <= 2L;
  
                  if (b) {
                      // redo the histogram?!
  //                    wordHistogram = new HashMap<>();
  //                    for (int i = 0; i < word.length(); i++) {
  //                        MutableLong newValue = wordHistogram.get((int)word.charAt(i)) ;
  //                        if (newValue == null) {
  //                            newValue = new MutableLong();
  //                            wordHistogram.put((int)word.charAt(i), newValue);
  //                        }
  //                        newValue.incAndSet();
  //                    }
  
                      int sum2 = 0;
                      for (Map.Entry<Integer, MutableLong> entry : wordHistogram.entrySet()) {
                          sum2 += letterScores[entry.getKey() - 'a'] *
                                  Integer.min(
                                  (int)entry.getValue().get(),
                                  scrabbleAvailableLetters[entry.getKey() - 'a']
                              );
                      }
                      int max2 = 0;
                      for (int i = 0; i < 3 && i < word.length(); i++) {
                          max2 = Math.max(max2, letterScores[word.charAt(i) - 'a']);
                      }
  
                      for (int i = 3; i < word.length(); i++) {
                          max2 = Math.max(max2, letterScores[word.charAt(i) - 'a']);
                      }
  
                      sum2 += max2;
                      sum2 = 2 * sum2 + (word.length() == 7 ? 50 : 0);
  
                      Integer key = sum2;
  
                      List<String> list = treemap.get(key) ;
                      if (list == null) {
                          list = new ArrayList<>() ;
                          treemap.put(key, list) ;
                      }
                      list.add(word) ;
                  }
              }
          }
  
          List<Entry<Integer, List<String>>> list = new ArrayList<Entry<Integer, List<String>>>();
  
          int i = 4;
          for (Entry<Integer, List<String>> e : treemap.entrySet()) {
              if (--i == 0) {
                  break;
              }
              list.add(e);
          }
  
          return list;
      }
  
      public static void main(String[] args) throws Exception {
          ShakespearePlaysScrabbleWithDirect s = new ShakespearePlaysScrabbleWithDirect();
          s.init();
          System.out.println(s.measureThroughput());
      }
  }