[Algorithms] – Find words in reviews of hotels

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;
        }
    });
}

 

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s