Skip to content

Instantly share code, notes, and snippets.

@adityak74
Created November 8, 2021 17:17
Show Gist options
  • Save adityak74/724a12724ae85c664f58bda98643d06e to your computer and use it in GitHub Desktop.
Save adityak74/724a12724ae85c664f58bda98643d06e to your computer and use it in GitHub Desktop.
Sort Articles by Comments and Alphabetic Hackerrank Solution
/*
* Complete the 'topArticles' function below.
*
* The function is expected to return a STRING_ARRAY.
* The function accepts INTEGER limit as parameter.
* base url for copy/paste:
* https://jsonmock.hackerrank.com/api/articles?page=<pageNumber>
*/
const https = require('https');
const makeRequest = (pageNumber = 1) => new Promise((resolve, reject) => {
https.get(`https://jsonmock.hackerrank.com/api/articles?page=${pageNumber}`, res => {
let body = "";
res.setEncoding("utf8");
res.on("data", data => body += data);
res.on('end', () => {
const bodyParsed = JSON.parse(body);
resolve({ articles: bodyParsed.data, totalPages: bodyParsed.total_pages });
});
});
});
const getTitle = (article) => {
return article.title || article.story_title || null;
};
async function topArticles(limit) {
if (limit < 0) return [];
const sortByCommentsAndAlpha = (a, b) => {
if (a.num_comments === b.num_comments) {
if (a.parsedName > b.parsedName) return -1;
else if (a.parsedName < b.parsedName) return 1;
return 0;
};
if (a.num_comments > b.num_comments) return -1;
return 1;
};
return new Promise(async (resolve, reject) => {
let articles = [];
const initRequest = await makeRequest();
articles = articles.concat(initRequest.articles);
for (let i = 2; i <= initRequest.totalPages; i += 1) {
let newReq = await makeRequest(i);
articles = articles.concat(newReq.articles);
}
articles = articles.map(article => ({ ...article, parsedName: getTitle(article) }));
articles.sort(sortByCommentsAndAlpha);
articles.splice(limit);
resolve(articles.map(article => article.parsedName));
});
}
@logavdm
Copy link

logavdm commented Oct 5, 2022

package com.loga;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

public class Article {

private static final String URL = "https://jsonmock.hackerrank.com/api/articles";

public static void main(String[] args) throws IOException {				
	int records=2;				
	
	Map<String, Integer> titles = getArticles();		
	Map<String,Integer> sortedMap = 
			titles.entrySet().stream()
		    .sorted(Entry.comparingByValue(Comparator.reverseOrder()))
		    .collect(Collectors.toMap(Entry::getKey, Entry::getValue,
		                              (e1, e2) -> e1, LinkedHashMap::new));		
	List<String> keyList=new LinkedList<>(sortedMap.keySet());
	
	for (int i=0;i<records;i++) {
		System.out.println(sortedMap.get(keyList.get(i))+"-> "+keyList.get(i));
	}
}


private static Map<String, Integer> getArticles() throws IOException {
	Map<String,Integer> titles=new LinkedHashMap<>();				
	int page = 1;
	int totalPage = 1;
	String response;

	while (page <= totalPage) {
		URL obj = new URL(URL + "?page=" + page);
		HttpURLConnection con = (HttpURLConnection) obj.openConnection();
		con.setRequestMethod("GET");
		BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));

		while ((response = in.readLine()) != null) {				
			JsonObject jsonResponse = new Gson().fromJson(response, JsonObject.class);
			totalPage = jsonResponse.get("total_pages").getAsInt();
			JsonArray data = jsonResponse.getAsJsonArray("data");

			for (JsonElement e : data) {					
				JsonElement ele=e.getAsJsonObject().get("title")!=null ? e.getAsJsonObject().get("title") : e.getAsJsonObject().get("story_title")!=null ?e.getAsJsonObject().get("story_title") : null;										
				if(!ele.isJsonNull()) {
					String title = ele.getAsString();							
					JsonElement commentEle=e.getAsJsonObject().get("num_comments");																		
					int comments_count=commentEle.isJsonNull() ? 0 : commentEle.getAsInt();						
					titles.put(title,comments_count);
				}
			}
		}
		page++;
	}
	return titles;
}

}

@logavdm
Copy link

logavdm commented Oct 5, 2022

Java solution

@fzybb
Copy link

fzybb commented Nov 5, 2022

The js solution is wrong, zero test case can be passed.

@erebelo
Copy link

erebelo commented Feb 6, 2023

The Java implementation works well, but just a slight correction is required that compromises the result. The comparison with null must be done by isJsonNul() rather than !=null.

Replace the first line after this code snippet for (JsonElement e : data) { with this one:
JsonElement titleElement = e.getAsJsonObject().get("title").isJsonNull() ? e.getAsJsonObject().get("story_title") : e.getAsJsonObject().get("title");

@hendisantika
Copy link

What if the method like this?

public static List<String> topArticles(String username, int limit) {

    }

@FREEZEHAWK
Copy link

Python Solution.

import requests  # Import the requests library for making HTTP requests

def top_articles(limit):
    if limit < 0:
        return []

    def make_request(page_number=1):
        response = requests.get(f"https://jsonmock.hackerrank.com/api/articles?page={page_number}")
        response.raise_for_status()  # Raise an error for bad responses
        return response.json()

    def get_title(article):
        return article.get('title') or article.get('story_title') or None

    articles = []
    init_request = make_request()
    articles.extend(init_request['data'])

    for i in range(2, init_request['total_pages'] + 1):
        new_req = make_request(i)
        articles.extend(new_req['data'])

    for article in articles:
        article['parsed_name'] = get_title(article)

    # Sort by number of comments (treat None as 0) and then alphabetically by title
    articles.sort(key=lambda a: (
        -a.get('num_comments', 0) if a.get('num_comments') is not None else 0,
        a['parsed_name'] if a['parsed_name'] is not None else ""
    ))

    # Limit the number of articles to the specified limit
    articles = articles[:limit]

    return [article['parsed_name'] for article in articles]

# Example usage
print(top_articles(2))

@nardocesar
Copy link

Here it goes (TS):

const API_URL = "https://jsonmock.hackerrank.com/api/articles";

type Article = {
    title: string | null;
    url: string;
    author: string;
    num_comments: number | null;
    story_id: string | null;
    story_title: string | null;
    story_url: string | null;
    parent_id: string | null;
    created_at: string;
};

type ApiResponse = {
    page: number;
    per_page: number;
    total: number;
    total_pages: number;
    data: Article[];
};

const filterArticle = (article: Article): boolean => {
    return article.title !== null || article.story_title !== null;
};

const getArticleName = (article: Article): string => {
    return article.title ?? article.story_title ?? '';
};

async function topArticles(limit: number): Promise<string[]> {
    const fetchData = async (page: number): Promise<ApiResponse> => {
        const response = await axios.get<ApiResponse>(`${API_URL}?page=${page}`);
        return response.data;
    };

    const allArticles: { name: string; num_comments: number }[] = [];

    const firstPageData = await fetchData(1);
    const { total_pages } = firstPageData;

    allArticles.push(
        ...firstPageData.data
            .filter(filterArticle)
            .map(article => ({
                name: getArticleName(article),
                num_comments: article.num_comments ?? 0,
            }))
    );

    for (let page = 2; page <= total_pages; page++) {
        const pageData = await fetchData(page);
        allArticles.push(
            ...pageData.data
                .filter(filterArticle)
                .map(article => ({
                    name: getArticleName(article),
                    num_comments: article.num_comments ?? 0,
                }))
        );
    }

    allArticles.sort((a, b) => {
        if (b.num_comments !== a.num_comments) {
            return b.num_comments - a.num_comments;
        }
        return b.name.localeCompare(a.name);
    });

    return allArticles.slice(0, limit).map(article => article.name);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment