EaglePB2's Competitive Programming Writeups
  • Home Page
  • Why Python?
  • Why 10^9 + 7?
  • General Formatting Title
  • 🇲🇾CodeNection
    • 2021
      • Closed Cateogry
        • Attend Talks
        • Distant Relatives
        • Concert
        • Mamak
        • Fair Contest
      • Open Preliminary Round
        • f(Aibohphobia)^-1
        • Did they cheat?
        • Semester Breaks
      • Open Final Round
        • Ways 1
        • Circular Campus
        • A joke
        • 🥰Last year when life was better
        • Thank You Pizza
    • 2023
      • Test Round
        • Codey and Alphabetical Scoring
        • Codey and Binary Guesser
      • Preliminary Round
        • Codey and CodeNection
        • Codey and Hide-and-Seek
        • Codey and Math
        • Codey and Textbooks
        • Codey and Money
        • Codey and Team Selection
        • Codey and Painted Tree
        • Codey and Number Grid
        • Codey and Crimes
      • Final Round
        • Codey and CodeNection 2
        • Codey and Connection
        • Codey and Schedule
        • Codey and School Supplies
        • Codey and Zombies
        • Codey and Sightseeing
        • Codey and Apples
        • Codey and Facto
        • Codey and Zoey
    • 2024
      • Test Round
        • Codey and Sunday
        • Codey and Takoyaki
      • Preliminary Round
        • Codey and CodeNection
        • Codey and Pebbles
        • Codey and Spam
        • Codey and Coins
        • Codey and Rectangles
        • Codey and Manuscript
        • Codey and Recipes
        • Codey and Toy Kingdom
        • Codey and Peaks
      • Final Round
        • Codey and Exit
        • Codey and Gardening
        • Codey and Symbol
        • Codey and Rectangles 2
        • Codey and Jutsu
        • Codey and Toy Kingdom 2
        • Codey and Speeches
  • ABaKoDa
    • 2023
      • Round 1
        • Problem Letters
        • Problem Statistics
        • Rankings Order
        • Rankings Search
      • Round 2
        • Abakoda Letters
        • Borrowed Words
        • Kensorship
        • Duel Languages
  • Meta Coding Competitions
    • 2011
      • Qualification Round
        • Double Squares
        • Peg Game
        • Studious Student
      • Round 1A
        • Diversity Number
        • Turn on the Lights
        • Wine Tasting
      • Round 1B
        • Chess 2
        • Diminishing Circle
        • Slot Machine Hacker
      • Round 1C
        • N-Factorful
        • Polynomial Factoring
        • Risky Slide
      • Round 2
        • Bonus Assignments
        • Scott's New Trick
        • Studious Student II
      • Final Round
        • Alien Game
        • Party Time
        • Safest Place
  • EaglePB2's Special
    • Hong Kong Identity card
    • Cycle Prefix Averages
    • Word Squares
Powered by GitBook
On this page
  • Question
  • Input Format
  • Constraints
  • Output Format
  • Sample Inputs:
  1. CodeNection
  2. 2021
  3. Closed Cateogry

Fair Contest

https://www.hackerrank.com/contests/codenection-2021-closed-category/challenges/fair-contest

Question

There are N students in a class with known amount of programming skills (here the skill of a person is scored with a number). Now the lecturer wants to form two programming teams in the class in such a way that their overall difference in programming skill in minimal.

Your task is to help the lecturer find the minimum such achievable difference. (Note : The sizes of groups do not have to be equal)

Input Format

The first input line has an integer N the number of students.

The next line has N integers p1,p2,...,pnp_1,p_2,...,p_np1​,p2​,...,pn​ the programming skill of each student.

Constraints

1≤N≤201 \le N \le 201≤N≤20
1≤pi≤1091 \le p_i \le 10^91≤pi​≤109

Output Format

Output one integer the minimum difference between the skills of the groups.

Sample Inputs:

Input

10
603 324 573 493 659 521 654 70 718 257

Output

2

First Attempt — Greedy Algorithm

My first thought is to by simply using greedy algorithm, which works by first sorting the numbers in descending order, thus adding the numbers on both arrays. Thus, inserting the next number into smaller array to try balancing out.

Meanwhile, this won't work at all as this method only gives approximation, not exact minimum difference. For sample input, this method would output 62 instead of 2, which is not viable solution.

But this could be the first start before opting to better strategy.

def min_partition_difference(arr):
    arr.sort(reverse=True)
    sum1, sum2 = 0, 0

    for num in arr:
        if sum1 < sum2:
            sum1 += num
        else:
            sum2 += num

    return abs(sum1 - sum2)

i = int(input())  
arr = list(map(int, input().split()))
print(min_partition_difference(arr))
Second Attempt — MiTM Dynamic Programming

After realizing that greedy algorithm won't work anyways, I tried to attempt this question by using dynamic programming instead. First, we know that the most optimized difference is 0, which is when both array is same. By making both array is same, the most optimized value should be the half of the sum of the inputs.

After getting the optimized target, now we can use iterative method to find if the combination of subset is able to reach the target. After taking all pairs of targets possible, we can simply divide the input array into 2 subsets (with all possible ways), compute all possible sums on each half, and lastly getting the best way to combine the sum as close as the target.

Although sounds feasible, meanwhile it defeats itself (TLE) when the test case values are large. Therefore, we have to think another better way to attempt this question.

def min_partition_difference(arr):
    total_sum = sum(arr)
    n = len(arr)
    half_sum = total_sum // 2

    dp = [False] * (half_sum + 1)
    dp[0] = True

    for num in arr:
        for j in range(half_sum, num - 1, -1):
            if dp[j - num]:
                dp[j] = True

    for s in range(half_sum, -1, -1):
        if dp[s]:
            return total_sum - 2 * s

i = int(input())  
arr = list(map(int, input().split()))
print(min_partition_difference(arr))
Final Solution — Optimize with binary search, combinations

If we somehow utilize the ready-made library, maybe it can make it faster in some reason. The previous attempt hits the TLE as it took too much time to traverse all possible pairs.

After thinking a bit, I think implementing a binary search during search phase, and introducing the combination library could help optimizing the problem.

Here's the final solution, which passed all test cases:

from itertools import combinations
import bisect

def subset_sums(arr):
    sums = set()
    n = len(arr)
    for i in range(n + 1):
        for comb in combinations(arr, i):
            sums.add(sum(comb))
    return sorted(sums)

def min_partition_difference(arr):
    total_sum = sum(arr)
    half_sum = total_sum // 2
    n = len(arr)
    
    left, right = arr[:n//2], arr[n//2:]
    
    left_sums = subset_sums(left)
    right_sums = subset_sums(right)
    
    min_diff = float('inf')
    for s in left_sums:
        idx = bisect.bisect_right(right_sums, half_sum - s) - 1
        if idx >= 0:
            best_s = right_sums[idx] + s
            min_diff = min(min_diff, abs(total_sum - 2 * best_s))
    
    return min_diff

i = int(input())  
arr = list(map(int, input().split()))
print(min_partition_difference(arr))
PreviousMamakNextOpen Preliminary Round

Last updated 2 months ago

🇲🇾