SCB Programming Test
Q1
Bandwidth Allocation A seryce provider is managing n APl endpoints, each serving different functionalities, rumbered fom’t to n. Given ‘mbandwidths allotate thiese among endpoints so that no adjacent endpoints receive bandwidth wth a diferencegrater than 1 unit, The goal is to maximire the bandwidth allocated to the ih endpoint Determine the maxmum bandwidth that can be allocated to the k” endpoint while adhering to the requirements. Note! . The endpoints i and nare not adjacent. Every’ APlendpoint shoudld be provided wn some nongera number of bandwidths. Examplena# k 3m-17 Orie optirmal way to distnibute im s 17units af bandwidth among the n =4 endpoints is 3, 4. 5, 5.Here, the 3’d endpoint is allocated S units of bandwidth, Hence, 5 is the required answen Functlon DescriptlonComplete the function fnd,axmum&and.wdths in the edstor below findMaxmumgandwdrhstakesthe following parameters): int n the total nurnber of APl endpaints managed by the service prowider int ie the endpo nt number for which bandwidth alocations are to be maximized inf m: the total number of bandwidthi allocatlons to be distributed among the APl endpoints Returns int the maxirmum anits of bandwidth that can be allocated to the k’ endpoint Constralnts #15ns10? ”1家大生的 .nsms10 e input Format For custom Testing v sample case 0 Sample input For Custom Testing STOINFUNCTION 有 2 发 na6 。k=之 4:m11 Sample Qutput
A1: Arithmetic
Bandwidth Allocation Solution
To solve this problem, we need to allocate bandwidth units among n
API endpoints such that:
- No two adjacent endpoints have bandwidth allocations differing by more than 1 unit
- Every endpoint gets at least 1 unit of bandwidth
- We need to maximize the allocation to the
k
-th endpoint
Approach
-
Understand the constraints: The key constraint is that adjacent endpoints can’t differ by more than 1 unit. This creates a “pyramid” pattern where bandwidth increases towards the center and decreases towards the ends.
-
Pattern recognition: The maximum allocation to any endpoint
k
depends on its position relative to the ends of the sequence. The optimal allocation forms a pyramid with peak atk
. -
Mathematical formulation: We can model this as finding the peak of a pyramid centered at
k
, while ensuring the total bandwidth sums tom
.
Solution Code
public class BandwidthAllocation {
public static int findMaximumBandwidth(int n, int k, int m) {
// The minimal possible sum is n (1 unit per endpoint)
if (m < n) {
return -1; // Not possible to allocate
}
// Binary search to find the maximum possible x for endpoint k
int left = 1;
int right = m;
int result = 1;
while (left <= right) {
int mid = left + (right - left) / 2;
// Calculate minimum bandwidth needed if endpoint k gets 'mid' units
long minSum = calculateMinSum(n, k, mid);
if (minSum <= m) {
result = mid;
left = mid + 1;
} else {
right = mid - 1;
}
}
return result;
}
private static long calculateMinSum(int n, int k, int x) {
// Calculate the sum when endpoint k gets x units
// Left side: forms a pyramid up to k
long leftSum = 0;
// From 1 to k: x, x-1, ..., x - (k-1)
// But can't go below 1
int leftPeak = Math.min(k, x);
leftSum = (long)leftPeak * (leftPeak + 1) / 2;
if (x > k) {
leftSum += (long)(x - k) * k;
}
// Right side: forms a pyramid down from k
long rightSum = 0;
// From k to n: x, x-1, ..., x - (n - k)
// But can't go below 1
int rightPeak = Math.min(n - k + 1, x);
rightSum = (long)rightPeak * (rightPeak + 1) / 2;
if (x > (n - k + 1)) {
rightSum += (long)(x - (n - k + 1)) * (n - k + 1);
}
// Subtract x once since it was counted in both left and right sums
return leftSum + rightSum - x;
}
public static void main(String[] args) {
// Sample test case
System.out.println(findMaximumBandwidth(4, 3, 17)); // Output: 5
System.out.println(findMaximumBandwidth(6, 2, 11)); // Output: 3
}
}
Explanation
-
Binary Search: We use binary search to find the maximum possible bandwidth
x
that can be allocated to endpointk
. For each candidatex
, we calculate the minimum total bandwidth needed to satisfy the constraints. - Minimum Sum Calculation: The
calculateMinSum
function computes the minimal bandwidth distribution where:- The left side of
k
forms an increasing sequence (1, 2, …, x) - The right side of
k
forms a decreasing sequence (x, x-1, …, 1) - The sum is adjusted to ensure no endpoint gets less than 1 unit
- The left side of
- Edge Handling: We ensure the pyramid doesn’t go below 1 unit for endpoints at the far ends, and properly account for cases where
x
is larger than the distance to either end.
This approach efficiently finds the maximum possible allocation for endpoint k
while respecting all constraints, using binary search to optimize the solution.
Q2: DB
- Are you an expert on data structures? Which of the following data structures can erase from its beginning or its end in O(1) tim Pick ONE option vector deque stack segment tree
A2:
The correct answer is: deque (Double-Ended Queue)
Here’s why:
- deque (Double-Ended Queue):
- Can erase/pop from both front and back in O(1) time
- Implemented as a dynamic array that grows in both directions
- Provides constant time insertion/removal at both ends
- Why not the others:
- vector: Only O(1) erase from back (pop_back), but O(n) from front (requires shifting elements)
- stack: Only allows O(1) operations at one end (LIFO principle)
- segment tree: Designed for range queries, not efficient for end operations
Key characteristics of deque:
- Supports push_front/pop_front and push_back/pop_back in O(1)
- Random access is possible (though not O(1) in all implementations)
- Typically implemented with multiple fixed-size arrays or a circular buffer
This makes deque the ideal choice when you need efficient insertion/removal at both ends of a sequence.
Q3: SQL
- Count the Employees The data for the number employed at several famous IT companies is maintained in the COMPANY table. Write a qi print the IDs of the companies that have more than 10000 employees, in ascending order of ID. Input Format COMPANY Name TD NAME EMPLOYEES Type Integer String Integer Description A company ID in the inclusive range [1. 1000]. This is the primary key. A company name. This field contains between 7 and 100 characters (inclusive). The total number of employees in the company. Output Format The result should contain the IDs of all the companies that have more than 10000 employees, in ascending order in tr following format: COMPANY. ID Sample Input ID COMPANY NAME Adobe Flipkart amazor Paytm BookMyShow EMPLOYEES 28085 35543 1089 9982 5589
A3:
SQL Query to Count Employees
To solve this problem, I’ll write a SQL query that:
- Selects company IDs from the COMPANY table
- Filters for companies with more than 10,000 employees
- Orders the results by ID in ascending order
Solution
SELECT ID
FROM COMPANY
WHERE EMPLOYEES > 10000
ORDER BY ID ASC;
Explanation
- SELECT ID: We only need to return the company IDs as specified in the output format
- FROM COMPANY: Querying the COMPANY table where the data is stored
- WHERE EMPLOYEES > 10000: Filter condition to only include companies with more than 10,000 employees
- ORDER BY ID ASC: Ensures the results are sorted in ascending order by company ID
Expected Output
For the sample input provided, the query would return:
ID
1
2
This is because:
- Adobe (ID 1) has 28,085 employees (>10,000)
- Flipkart (ID 2) has 35,543 employees (>10,000)
- The other companies have fewer than 10,000 employees and are excluded
- The results are ordered by ID in ascending order as required
Q4: Arithmetic
- FizzBuzz
P)
ALL
Given a number n, for each integer / in the range from 1 to
inclusive, print one value per line as follows:
• If /is a multiple of both 3 and 5, print FizzBuzz.
• If /is a multiple of 3 (but not 5), print Fizz.
• If / is a multiple of 5 (but not 3), print Buzz.
• If / is not a multiple of 3 or 5, print the value of i.
Function Description
Complete the function fizz Buzz in the editor below.
3
fizzBuzz has the following parameter(s):
int n: upper limit of values to test (inclusive)
Returns: NONE
Prints;
The function must print the appropriate response for each value i
in the set (1, 2, … m} in ascending order, each on a separate line.
Constraints
- 0=1 = 2x 105
- Input Format for Custom Testing y Sample Case 0 Sample Input STDIN Function 15 = 15
A4:
FizzBuzz Solution in Java
Here’s the Java implementation for the classic FizzBuzz problem:
Solution Code
public class FizzBuzz {
public static void fizzBuzz(int n) {
for (int i = 1; i <= n; i++) {
if (i % 3 == 0 && i % 5 == 0) {
System.out.println("FizzBuzz");
} else if (i % 3 == 0) {
System.out.println("Fizz");
} else if (i % 5 == 0) {
System.out.println("Buzz");
} else {
System.out.println(i);
}
}
}
public static void main(String[] args) {
/* Test with sample input */
fizzBuzz(15);
}
}
Explanation
- Loop through numbers: We iterate from 1 to n (inclusive)
- Check conditions in order:
- First check if divisible by both 3 and 5 (print “FizzBuzz”)
- Then check if divisible by 3 only (print “Fizz”)
- Then check if divisible by 5 only (print “Buzz”)
- Finally, print the number if none of the above conditions are met
- Order matters: We check the most specific condition (divisible by both) first, then the individual cases
Sample Output
For input n = 15, the output would be:
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
This solution efficiently handles all cases with a time complexity of O(n) and space complexity of O(1), which is optimal for this problem.
Q5: security
- Insecure end point A local bank recently released a new feature that allow the mobile application and starts analyzing it. The attacke eir insurances on a single page. An attacker creates an account with the net banking feature. The attacker cannot find any major security issues on the web, but downlo: ure and finds an interesting end-point such as tollows: nttps://api.banking-corp.com/insurance/?id=13066396 The attacker cycles this predictable end-point and is then at customers data. Which vulnerability is being exploited? dID escalalion 1) account takeover insecure direct obiect referencing enumeration attack
A5:
The vulnerability being exploited in this scenario is:
Insecure Direct Object Reference (IDOR)
Here’s why:
- Predictable endpoint: The URL contains a direct reference to an insurance record using a simple numeric ID (
?id=13066396
) - Parameter manipulation: The attacker can cycle through different ID values to access other customers’ data
- Lack of access control: The endpoint doesn’t verify if the requesting user is authorized to view each specific insurance record
- Data exposure: This allows unauthorized access to sensitive insurance information of other customers
Key characteristics of this vulnerability:
- Direct references to internal implementation objects (like database keys)
- No proper authorization checks
- Predictable patterns in object references
- Bypasses intended access controls
This is different from:
- Account takeover: Would require compromising user credentials
- Enumeration attack: Typically refers to discovering valid users/IDs, not necessarily accessing their data
- Privilege escalation: Would involve elevating user privileges beyond their normal access level
The proper mitigation would be to implement:
- Proper access control checks
- Indirect reference maps
- Session-based authorization
- Randomized/non-sequential IDs
Q6: Programming
Local and Global Variable #L/bin/bash value-10 funciO) value=S ((value + 2)) echo “Inside func: Value is: Svalue” 7 func2() f local value value=$ ((value + 2)) echo “Inside func2: Value is: Svalue” 1 func Svalue funca echo “Outside Function: Value is: Svalue” What is the output of this Bash script? Pick ONE option Inside func1: Value is: 2 Inside func2: Value is: 2 Outside Function: Value is: 10
A6:
Let’s analyze the Bash script step by step to determine the correct output.
Script Analysis:
#!/bin/bash
value=10
func1() {
value=$((value + 2))
echo "Inside func1: Value is: $value"
}
func2() {
local value
value=$((value + 2))
echo "Inside func2: Value is: $value"
}
func1
func2
echo "Outside Function: Value is: $value"
Execution Flow:
- Global variable initialization:
value=10
(global scope) - func1():
- Modifies the global
value
variable (10 + 2 = 12) - Prints: “Inside func1: Value is: 12”
- Modifies the global
- func2():
- Declares a new
local value
variable (shadows the global one) - The local
value
is initially empty (treated as 0 in arithmetic) - 0 + 2 = 2
- Prints: “Inside func2: Value is: 2”
- Doesn’t affect the global
value
- Declares a new
- Final output:
- Global
value
remains 12 (modified by func1) - Prints: “Outside Function: Value is: 12”
- Global
Correct Output:
Inside func1: Value is: 12
Inside func2: Value is: 2
Outside Function: Value is: 12
Why the Provided Options Are Incorrect:
The option you listed:
Inside func1: Value is: 2
Inside func2: Value is: 2
Outside Function: Value is: 10
is incorrect because:
- func1 modifies the global variable (should be 12, not 2)
- The outside value shows the pre-modified value (should show 12 after func1 modifies it)
Key Concepts:
func1
uses the global variablefunc2
creates a new local variable (shadowing the global one)- Local variables don’t affect global variables with the same name
- Arithmetic expansion treats empty variables as 0
Q7:SQL
Which of the following operators is used for pattern matching? Pick ONE option (9 15 NULL operator ASSIGNMENT operator LIKE operator NOT operator
A7:
The correct answer is:
LIKE operator
Here’s why:
- LIKE operator:
- Specifically designed for pattern matching in SQL
- Uses wildcards:
%
- matches any sequence of characters_
- matches any single character
- Example:
WHERE name LIKE 'J%'
finds all names starting with ‘J’
- Why not the others:
- NULL operator: Used for checking NULL values (IS NULL, IS NOT NULL)
- ASSIGNMENT operator: Used for assigning values (
=
in most languages) - NOT operator: Logical operator that reverses a condition
The LIKE operator is the standard SQL operator for pattern matching across all major database systems including MySQL, PostgreSQL, SQL Server, and Oracle.
Q8: Arithmetic
Competitive Gaming A group of friends is playing a video game where players earn points. At the end of a round, players who achieve at least rank k can “evel up” their characters. Given the scores of players at the end of the round, determine how many players will level up. Notes: • Players with equal scores share the same rank, and the next player with a lower score takes the subsequent rank position, For instance, if four players finish with scores ranking them as 1, 1, 1, and 4, the first three players tie for first place, and the next player is ranked fourth. • No player with a score of 0 can level up, regardless of rank. Example n = 4 1 = 3 scores = [100, 50. 50. 251 These players’ ranks are (1, 2, 2, 41. Because the players need to have a rank of at least « = 3 to level up, only the first three players quality. Therefore, the answer is 3. Function Description Complete the function numPlayers in the editor with the following parameters: int k the cutoff rank to level up a player’s character Int scores[n/ the players’ scores Returns int: the number of players who can level up after this round Constraints • 15 n= 105
A8:
To solve this problem, we need to determine how many players will level up based on their ranks at the end of a round. The key points to consider are:
- Ranking Rules: Players with the same score share the same rank, and the next player with a lower score gets the next subsequent rank. For example, if three players have the same highest score, they all get rank 1, and the next player gets rank 4.
- Cutoff Rank: Only players with a rank of at least
k
can level up. - Zero Score: Players with a score of 0 cannot level up, regardless of their rank.
Approach
- Sort the Scores: First, we sort the scores in descending order to easily determine the ranks.
- Assign Ranks: We then assign ranks to each player. Players with the same score will share the same rank. The next player with a lower score will get a rank equal to their position in the sorted list (1-based index).
- Count Eligible Players: We count how many players have a rank ≤
k
and a score greater than 0.
Solution Code
def numPlayers(k, scores):
if not scores:
return 0
# Sort scores in descending order
scores.sort(reverse=True)
# Assign ranks
ranks = []
rank = 1
for i in range(len(scores)):
if i == 0:
ranks.append(rank)
else:
if scores[i] == scores[i-1]:
ranks.append(ranks[i-1])
else:
rank = i + 1
ranks.append(rank)
# Count players who can level up
count = 0
for i in range(len(scores)):
if ranks[i] <= k and scores[i] > 0:
count += 1
return count
Explanation
- Sorting: The scores are sorted in descending order to facilitate rank assignment. Higher scores come first.
- Rank Assignment: We iterate through the sorted scores. The first player gets rank 1. For subsequent players, if their score is the same as the previous player’s score, they receive the same rank. Otherwise, their rank is their 1-based position in the list.
- Eligibility Check: We then count how many players have a rank that is less than or equal to
k
and a score greater than 0. This count is returned as the result.
For example, given the input k = 3
and scores = [100, 50, 50, 25]
, the sorted scores are [100, 50, 50, 25]
. The ranks assigned are [1, 2, 2, 4]
. The first three players have ranks ≤ 3 and non-zero scores, so the result is 3. This approach efficiently handles the ranking logic and checks the eligibility criteria to determine the number of players who can level up.
Q9:SQL
- The Superheroes Name The information of the superheroes have been stored in the SUPERHERO table. Write a query to print the names, i.e., SUPERHERO.NAME of the superheroes whose NAME has fewer than 7 characters. Sort the output in increasing order of their /Ds. Input Format SUPERHERO Name ID NAME LATITUDE LONGITUDE Type Integer String Float Description A superhero ID in the inclusive range [1, 1000]. This field is the primary key. A superhero name. This field contains between 1 and 100 characters (inclusive). The latitude of the superhero. The longitude of the superhero. Output Format The result should contain the names of the superheroes whose names have fewer than 7 characters. The result should be sorted in the increasing order of their /Ds. SUPERHERO. NAME Sample Input NAME batman spiderman SUPERHERO LATITUDE LONGITUDE 50.0 85.0 65.0 65.0
A9:
SQL Query for Superheroes with Short Names
Here’s the SQL query to find superheroes whose names have fewer than 7 characters, sorted by ID in ascending order:
SELECT NAME
FROM SUPERHERO
WHERE LENGTH(NAME) < 7
ORDER BY ID ASC;
Explanation
- SELECT NAME: We only need to return the superhero names as specified in the output format
- FROM SUPERHERO: Querying the SUPERHERO table where the data is stored
- WHERE LENGTH(NAME) < 7: Filter condition to only include names with fewer than 7 characters
- ORDER BY ID ASC: Ensures the results are sorted in ascending order by superhero ID
Expected Output
For the sample input provided, the query would return:
NAME
batman
This is because:
- “batman” has 6 characters (<7)
- “spiderman” has 9 characters (≥7)
- The results are ordered by ID in ascending order as required
The query works across all major SQL databases including MySQL, PostgreSQL, SQL Server, and Oracle.
Q10: Microservice
Microservices Communication services-based architecture for an e-commerce platform is in the design phase. A core requirement is to ensure that the system can handle eventual consistency while ensuring that the plattorm’s various services remain loosely coupled. Two services. Order Service and Inventory Service, need to communicate regarding the availability of products. Service needs to check if the product is in stock using the Inventory Service. However, the design must ensure that even it the Inventory service Is tempo rarily unavailable, the Order Service can still accent When a customer places an order, the Ordel orders, albeit with some potential delay in processing. Which of the following communication patterns is most suitable to re that the services remain decoupled and the system handles eventual consistency. PICk ONE OguOn ( Synchronous HTTP REST API calls from Order Service to Inventory Service O RPC calls from Order Service to Inventory Service using a protocol like gRPC. Order Service writes to a shared database which Inventory Service polls periodically Order Service publishes an event (like “OrderPlaced”) to a message queue, and Inventory Service subscribes to these
A10:
The most suitable communication pattern for this scenario is:
Order Service publishes an event (like “OrderPlaced”) to a message queue, and Inventory Service subscribes to these
Here’s why this is the best choice:
- Loose Coupling:
- Services communicate via events/messages rather than direct calls
- Neither service needs to know about the other’s implementation
- Eventual Consistency:
- The order can be accepted immediately
- Inventory updates can happen when the Inventory Service is available
- Resilience:
- If Inventory Service is down, messages queue up and process later
- No blocking of Order Service during inventory checks
- Scalability:
- Message queues handle load spikes gracefully
- Each service can scale independently
- Asynchronous Processing:
- Matches the business requirement of accepting orders even with delayed processing
The other options have significant drawbacks:
- Synchronous HTTP/RPC calls: Create tight coupling and block orders if inventory is down
- Shared database: Creates tight coupling and becomes a scalability bottleneck
This event-driven approach with message queues is the standard pattern for handling such scenarios in microservices architectures, providing the right balance of responsiveness and reliability while maintaining loose coupling.
Q11: DataBase
Database Locks While debugging performance issues in a relational database system, multiple transactions are frequently waiting for each other, leading to decreased throughput. What phenomenon is this? Pick ONE option ) Deadlock O ) Under-provisioning ® Database fragmentation Replication lag
A11
The correct answer is: Deadlock
Here’s why this is the right choice:
- Deadlock Definition:
- A deadlock occurs when two or more transactions permanently block each other
- Each transaction waits for a resource held by the other transaction
- Neither can proceed until the other releases its locks
- Key Characteristics:
- Circular wait condition (Transaction A waits for B, which waits for A)
- Transactions remain stuck indefinitely without external intervention
- Directly causes decreased throughput as transactions can’t complete
- Why Not Other Options:
- Under-provisioning: General resource shortage, not specifically about transactions waiting
- Database fragmentation: Affects storage efficiency, not transaction blocking
- Replication lag: Delay in copying data between nodes, not mutual blocking
- Deadlock Symptoms:
- Transactions stuck in “waiting” state
- Increasing number of blocked processes
- Application timeouts
- Requires database intervention (rollback of one transaction) to resolve
Deadlocks are a common performance issue in relational databases that must be handled through proper transaction design and isolation levels.
Q12: SQL
Index Optimization bookstore uses a web application mnges us inventory. database table, Books, contains over 10 million records. The most frequent user operations include searching for books by title and filtering by their publication date. Andses Indicate that searches take a significant amount or time er complaints. The only index is on the BookID column To optimize the search speed, which of the following steps v Pick ONE option C Add a Full-Text Search index on the Title column to optimize text-based searches ) Add a composite index combinine both Title and PublicationDate columns ) Increase the memo / allocated to the database server to improve search soeed. () Partition the Books table based on the PublicationDate column
A12:
The best option to optimize search speed in this scenario is:
Add a composite index combining both Title and PublicationDate columns
Here’s why this is the optimal solution:
- Query Pattern Alignment:
- The most frequent operations search by title AND filter by publication date
- A composite index on (Title, PublicationDate) serves both needs efficiently
- Performance Benefits:
- Single index can satisfy both search conditions
- Eliminates full table scans for common queries
- Better than separate indexes due to index merging overhead
- Why Not Other Options:
- Full-text search: Overkill for simple title matching (better for content search)
- Increasing memory: Doesn’t address the root cause (missing proper indexes)
- Partitioning: Helps for date-range queries but not title searches
- Implementation Impact:
- Minimal application changes required
- Works with existing queries
- More storage-efficient than multiple single-column indexes
This composite index will provide the best performance improvement for the described workload while maintaining query flexibility.
The index should be created with:
CREATE INDEX idx_title_pubdate ON Books(Title, PublicationDate);
Q13: RestAPI
REST API: Energy Bar Given a country name, use a chocolate database to find the chocolate that provides the most energy per gram of chocolate. Use HTTP GET requests to access the database at https://isonmock.hackerrank.com/ api/chocolates. The query result is paginated and can be further accessed by appending to the query string &page=(num} where num is the page number. To filter the query based on specific fields, append -fieldname»=value to the URL. For example, https:// jsonmock.hackerrank.com/api/chocolates? countryOfOrigin={country] returns filtered results based on the country of origin. The query response from the API includes these fields: • page: the current page • per page: the maximum results per page • total: the total number of records • total pages: the total number of pages for the query • data: an array of SON objects containing chocolate information Each object in the data field includes the following: • countryOfOrigin: the country where the chocolate originated • brand the brand name of the chocolate • O/pesthe type of chocolate
- nutritionalinformation: an object containing nutritional information about the chocolate • prices: a price array of different variations of the chocolate • weights: a weight array of different variations of the chocolate
- other details not relevant to this question For example, the record from https://jsonmock.hackerrank.com/api/ chocolates indudes the following:”type”: “Truffle” “brand”: “Tonv’s Chocolonely” “ingredients”: [ “Sugar” “Cocoa butter” “Cocoa mass” “Whole milk powder” “Lactose” “Soy lecithin” “Vanillin” “Vanilla extract”. “Milk fat” “Butter oil” l. “prices”: [ 614, 283, 564, 365, 689 1, “weights”: [ 125, 71 g 116, 100, 126 1, “countryoforigin”: “Norway” “nutritionalInformation”: f “fats”: 1.01, “kcal”: 115, “carbs”: 7.49, “vitaminD”: 5.47, vitamink”: 8.14, “fiber” : 6.46, “sugar”: 14.48 7 “allergenInformation” A L “Cashews”“Cashews” “productNumber”: 291563, “flavors”: [ “Vanilla” “Hazelnut” Given a string country, return the brand and type of chocolate in the format “brand:type” that provides the most energy per gram (kcal0.01 *weight) of chocolate. Round down the energy calculation to the nearest integer. If a chocolate has multiple weights, use the average weight rounded down to the nearest integer. If more than one chocolate provides the same amount of energy, return the one whose average price rounded down to the nearest integer is the east. 6 Function Description Complete the function energyBarin the editor below. energyBar has the following parameter(s): string country: the country of origin for the chocolate Returns string: the brand and type of chocolate that provides the most energy per gram in the format “brand:type” Note: Please review the header in the code stub to see available libraries for API requests in the selected language. Required libraries can be imported to solve the question. Check our full list of supported libraries at https//www.hackerrank.com/environment.
A13:
Python:
I’ll help you solve this problem by creating a function that queries a paginated REST API to find the chocolate with the most energy per gram from a specific country.
Approach
- Fetch All Chocolates: We’ll need to handle pagination to get all chocolates from the specified country
- Calculate Energy per Gram: For each chocolate:
- Compute average weight (rounded down)
- Calculate energy per gram:
floor(kcal * 0.01 * average_weight)
- Select Best Chocolate: Find the chocolate with maximum energy per gram, and if there’s a tie, choose the one with the lowest average price
- Format Result: Return the result as “brand:type”
Solution Code
import requests
import math
def energyBar(country):
base_url = "https://jsonmock.hackerrank.com/api/chocolates"
max_energy = -1
best_chocolate = None
min_price = float('inf')
# Get first page to determine total pages
response = requests.get(f"{base_url}?countryOfOrigin={country}&page=1")
data = response.json()
total_pages = data['total_pages']
# Process all pages
for page in range(1, total_pages + 1):
response = requests.get(f"{base_url}?countryOfOrigin={country}&page={page}")
data = response.json()
for chocolate in data['data']:
# Calculate average weight
weights = chocolate.get('weights', [])
if not weights:
continue
avg_weight = math.floor(sum(weights) / len(weights))
# Calculate energy per gram
kcal = chocolate['nutritionalInformation']['kcal']
energy = math.floor(kcal * 0.01 * avg_weight)
# Calculate average price
prices = chocolate.get('prices', [])
avg_price = math.floor(sum(prices) / len(prices)) if prices else 0
# Check if this is the best chocolate
if (energy > max_energy) or \
(energy == max_energy and avg_price < min_price):
max_energy = energy
min_price = avg_price
best_chocolate = chocolate
if best_chocolate:
return f"{best_chocolate['brand']}:{best_chocolate['type']}"
return "No chocolates found"
Explanation
-
API Pagination Handling: We first fetch the initial page to determine total pages, then iterate through all pages to process every chocolate from the specified country.
- Energy Calculation:
- For each chocolate, we calculate the average weight (sum of weights divided by count, rounded down)
- Energy per gram is computed as
floor(kcal * 0.01 * average_weight)
- Price Calculation:
- We calculate the average price (sum of prices divided by count, rounded down)
- This is used as a tiebreaker when energy values are equal
- Selection Logic:
- We keep track of the chocolate with highest energy per gram
- When energies are equal, we select the one with lower average price
- Result Formatting: The final result is returned in “brand:type” format as specified.
This solution efficiently handles the paginated API and implements all the specified requirements for energy calculation and tie-breaking.
Java 8
Java 8 Implementation for Energy Bar Problem
Here’s the Java 8 solution using HttpURLConnection
for API requests and proper JSON parsing:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
public class ChocolateEnergyFinder {
public static String energyBar(String country) {
try {
List<Chocolate> chocolates = getAllChocolates(country);
if (chocolates.isEmpty()) {
return "No chocolates found";
}
// Find chocolate with max energy per gram, then min average price
Chocolate best = chocolates.stream()
.max(Comparator.comparing(Chocolate::getEnergyPerGram)
.get();
return best.getBrand() + ":" + best.getType();
} catch (Exception e) {
e.printStackTrace();
return "Error processing request";
}
}
private static List<Chocolate> getAllChocolates(String country) throws Exception {
List<Chocolate> chocolates = new ArrayList<>();
int page = 1;
int totalPages = 1;
do {
String urlStr = String.format(
"https://jsonmock.hackerrank.com/api/chocolates?countryOfOrigin=%s&page=%d",
country, page);
JSONObject response = getApiResponse(urlStr);
totalPages = response.getInt("total_pages");
JSONArray data = response.getJSONArray("data");
for (int i = 0; i < data.length(); i++) {
JSONObject chocoJson = data.getJSONObject(i);
Chocolate choco = parseChocolate(chocoJson);
chocolates.add(choco);
}
page++;
} while (page <= totalPages);
return chocolates;
}
private static JSONObject getApiResponse(String urlStr) throws Exception {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
StringBuilder response = new StringBuilder();
try (BufferedReader in = new BufferedReader(
new InputStreamReader(conn.getInputStream()))) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
}
return new JSONObject(response.toString());
}
private static Chocolate parseChocolate(JSONObject json) {
String brand = json.getString("brand");
String type = json.getString("type");
// Calculate average weight
JSONArray weights = json.getJSONArray("weights");
int avgWeight = (int) Math.floor(weights.toList().stream()
.mapToDouble(w -> Double.parseDouble(w.toString()))
.average()
.orElse(0));
// Calculate energy per gram
JSONObject nutrition = json.getJSONObject("nutritionalInformation");
int kcal = nutrition.getInt("kcal");
int energyPerGram = (int) Math.floor(kcal * 0.01 * avgWeight);
// Calculate average price for tie-breaker
JSONArray prices = json.getJSONArray("prices");
int avgPrice = (int) Math.floor(prices.toList().stream()
.mapToDouble(p -> Double.parseDouble(p.toString()))
.average()
.orElse(0));
return new Chocolate(brand, type, energyPerGram, avgPrice);
}
static class Chocolate {
private String brand;
private String type;
private int energyPerGram;
private int avgPrice;
public Chocolate(String brand, String type, int energyPerGram, int avgPrice) {
this.brand = brand;
this.type = type;
this.energyPerGram = energyPerGram;
this.avgPrice = avgPrice;
}
public String getBrand() { return brand; }
public String getType() { return type; }
public int getEnergyPerGram() { return energyPerGram; }
public int getAvgPrice() { return avgPrice; }
}
public static void main(String[] args) {
System.out.println(energyBar("Norway")); // Example usage
}
}
Key Features
- Java 8 Streams: Used for:
- Calculating averages of weights and prices
- Finding the chocolate with maximum energy per gram
- Handling tie-breakers with minimum average price
- HTTP Requests: Uses
HttpURLConnection
to:- Make GET requests to the paginated API
- Handle JSON responses
- JSON Processing: Uses
org.json
library to:- Parse API responses
- Extract chocolate data
- Handle nested JSON structures
-
Error Handling: Includes basic exception handling
- Custom Comparator: Implements proper comparison logic for:
- Primary sort by energy per gram (descending)
- Secondary sort by average price (ascending)
This implementation follows all the requirements from the problem statement and handles the paginated API properly while calculating the required metrics.