Problem:
Given a set of words and many review of this hotels, you must display the hotels Ids containing in their reviews the words informed.
Inputs:
– Line 1: words
– Line 2: quantity of reviews
– Line 3 .. N: Id Hotel and review;
Rules :
– Special characters should be disregarded;
– If a word appears more than once it should be told all times;
– The result should be respectively ordered by the number of words found and the id of the hotel.
My solution :
public static class Hotel{ private Integer idHotel; private Integer score; public Hotel(Integer idHotel, Integer score){ this.idHotel = idHotel; this.score = 0; } public Integer getScore() { return score; } public Integer getIdHotel() { return idHotel; } @Override public String toString(){ return this.getIdHotel().toString() + " "; } } public static class Utils{ public static List<String> getArrayOfWordsLine(String words) { String[] wordsArray = buildWordsArray(words); return Arrays.asList(wordsArray); } private static String[] buildWordsArray(String words) { words = words.replaceAll("[!,?._'@]", ""); words = words.replaceAll("^ +| +$|( )+", " "); words = words.replaceAll("^\\s+", "").replaceAll("\\s+$", ""); return words.split(" "); } } public static void main(String[] args) { Scanner scan = new Scanner(System.in); String words = scan.nextLine(); Integer nunReviews = scan.nextInt(); List<Hotel> hotelList = new ArrayList<>(); int counter = 0; while (counter < nunReviews){ Integer hotelId = scan.nextInt(); scan.next(); String stringReview = scan.nextLine(); List<String> arrayWithWordsReview = Utils.getArrayOfWordsLine(stringReview); Integer score = calcHotelScore(words,arrayWithWordsReview); hotelList.add(new Hotel(hotelId, score)); counter ++; } List<Hotel> answer = takeOrderDescHotelsByQuantityReview(hotelList); answer.stream().forEach(System.out::print); } private static Integer calcHotelScore(String reviews, List<String> wordsArray) { return wordsArray.stream().filter(s -> reviews.contains(s)).collect( Collectors.groupingBy(Object::toString, Collectors.collectingAndThen( Collectors.mapping(Object::toString, Collectors.toSet()), Set::size))).values().stream().mapToInt(i -> i.intValue()).sum(); } private static List<Hotel> takeOrderDescHotelsByQuantityReview(List<Hotel> hotelList) { List<Hotel> finalList = new ArrayList<>(); hotelList.stream() .collect(Collectors.groupingBy(h -> h.getIdHotel(), Collectors.summingInt(h->h.getScore()))).forEach((a,b)->{finalList.add(new Hotel(a,b));}); orderResultsByScoreAndHotelId(finalList); return finalList; } private static void orderResultsByScoreAndHotelId(List<Hotel> finalListHotels) { Collections.sort(finalListHotels, new Comparator<Hotel>() { @Override public int compare(Hotel o1, Hotel o2) { Integer compare = o2.getScore().compareTo(o1.getScore()); if ( compare == 0){ return o1.getIdHotel().compareTo(o2.getIdHotel()); } return compare; } }); }