import math
def allocate_students(schools, groups):
"""
Allocates students from schools into groups, prioritizing the most even
distribution possible.
Args:
schools: A dictionary mapping school names to student counts.
groups: A list of group names.
Returns:
A dictionary mapping school names to a list of (group, student_count) tuples.
"""
num_schools = len(schools)
num_groups = len(groups)
total_students = sum(schools.values())
# Check if allocation is possible
if num_schools < 2 or num_groups < 2:
return None # Not enough schools or groups
# Calculate ideal group size
ideal_group_size = total_students // num_groups
# Create the allocation dictionary (now with schools as keys)
allocation = {school: [] for school in schools}
# Sort schools by student count in descending order
sorted_schools = sorted(schools.items(), key=lambda item: item[1], reverse=True)
# Allocate students
group_counts = {group: 0 for group in groups} # Track group sizes
for school, count in sorted_schools:
remaining_count = count
assigned_groups = 0
while remaining_count > 0:
# Find the group with the fewest students
min_group = min(group_counts, key=group_counts.get)
# Calculate how many students to allocate to this group
allocate_count = min(remaining_count, ideal_group_size // 2)
allocation[school].append((min_group, allocate_count))
group_counts[min_group] += allocate_count
remaining_count -= allocate_count
assigned_groups += 1
# Distribute remaining students one by one
while remaining_count > 0:
min_group = min(group_counts, key=group_counts.get)
allocation[school].append((min_group, 1))
group_counts[min_group] += 1
remaining_count -= 1
return allocation
# Example usage
schools = {
"kpu": 39,
"bij": 27,
"Mullahikheda": 34,
"SKP": 56,
"kamalpur": 17,
"Alinagar": 14
}
groups = ["Tushar red", "Adheep", "Valentina", "Kavita", "Manjari", "Surabhi", "Vishal", "Sukhmani", "planetarium"]
allocation = allocate_students(schools, groups)
if allocation:
for school, groups_and_counts in allocation.items():
print(f"{school}:")
for group, count in groups_and_counts:
print(f" {group}: {count}")
else:
print("Allocation not possible.") # This should rarely happen
aW1wb3J0IG1hdGgKCmRlZiBhbGxvY2F0ZV9zdHVkZW50cyhzY2hvb2xzLCBncm91cHMpOgogICIiIgogIEFsbG9jYXRlcyBzdHVkZW50cyBmcm9tIHNjaG9vbHMgaW50byBncm91cHMsIHByaW9yaXRpemluZyB0aGUgbW9zdCBldmVuIAogIGRpc3RyaWJ1dGlvbiBwb3NzaWJsZS4KCiAgQXJnczoKICAgIHNjaG9vbHM6IEEgZGljdGlvbmFyeSBtYXBwaW5nIHNjaG9vbCBuYW1lcyB0byBzdHVkZW50IGNvdW50cy4KICAgIGdyb3VwczogQSBsaXN0IG9mIGdyb3VwIG5hbWVzLgoKICBSZXR1cm5zOgogICAgQSBkaWN0aW9uYXJ5IG1hcHBpbmcgc2Nob29sIG5hbWVzIHRvIGEgbGlzdCBvZiAoZ3JvdXAsIHN0dWRlbnRfY291bnQpIHR1cGxlcy4KICAiIiIKCiAgbnVtX3NjaG9vbHMgPSBsZW4oc2Nob29scykKICBudW1fZ3JvdXBzID0gbGVuKGdyb3VwcykKICB0b3RhbF9zdHVkZW50cyA9IHN1bShzY2hvb2xzLnZhbHVlcygpKQoKICAjIENoZWNrIGlmIGFsbG9jYXRpb24gaXMgcG9zc2libGUKICBpZiBudW1fc2Nob29scyA8IDIgb3IgbnVtX2dyb3VwcyA8IDI6CiAgICByZXR1cm4gTm9uZSAgIyBOb3QgZW5vdWdoIHNjaG9vbHMgb3IgZ3JvdXBzCgogICMgQ2FsY3VsYXRlIGlkZWFsIGdyb3VwIHNpemUKICBpZGVhbF9ncm91cF9zaXplID0gdG90YWxfc3R1ZGVudHMgLy8gbnVtX2dyb3VwcwoKICAjIENyZWF0ZSB0aGUgYWxsb2NhdGlvbiBkaWN0aW9uYXJ5IChub3cgd2l0aCBzY2hvb2xzIGFzIGtleXMpCiAgYWxsb2NhdGlvbiA9IHtzY2hvb2w6IFtdIGZvciBzY2hvb2wgaW4gc2Nob29sc30KCiAgIyBTb3J0IHNjaG9vbHMgYnkgc3R1ZGVudCBjb3VudCBpbiBkZXNjZW5kaW5nIG9yZGVyCiAgc29ydGVkX3NjaG9vbHMgPSBzb3J0ZWQoc2Nob29scy5pdGVtcygpLCBrZXk9bGFtYmRhIGl0ZW06IGl0ZW1bMV0sIHJldmVyc2U9VHJ1ZSkKCiAgIyBBbGxvY2F0ZSBzdHVkZW50cwogIGdyb3VwX2NvdW50cyA9IHtncm91cDogMCBmb3IgZ3JvdXAgaW4gZ3JvdXBzfSAgIyBUcmFjayBncm91cCBzaXplcwogIGZvciBzY2hvb2wsIGNvdW50IGluIHNvcnRlZF9zY2hvb2xzOgogICAgcmVtYWluaW5nX2NvdW50ID0gY291bnQKICAgIGFzc2lnbmVkX2dyb3VwcyA9IDAKICAgIHdoaWxlIHJlbWFpbmluZ19jb3VudCA+IDA6CiAgICAgICMgRmluZCB0aGUgZ3JvdXAgd2l0aCB0aGUgZmV3ZXN0IHN0dWRlbnRzCiAgICAgIG1pbl9ncm91cCA9IG1pbihncm91cF9jb3VudHMsIGtleT1ncm91cF9jb3VudHMuZ2V0KQoKICAgICAgIyBDYWxjdWxhdGUgaG93IG1hbnkgc3R1ZGVudHMgdG8gYWxsb2NhdGUgdG8gdGhpcyBncm91cAogICAgICBhbGxvY2F0ZV9jb3VudCA9IG1pbihyZW1haW5pbmdfY291bnQsIGlkZWFsX2dyb3VwX3NpemUgLy8gMikKCgogICAgICBhbGxvY2F0aW9uW3NjaG9vbF0uYXBwZW5kKChtaW5fZ3JvdXAsIGFsbG9jYXRlX2NvdW50KSkKICAgICAgZ3JvdXBfY291bnRzW21pbl9ncm91cF0gKz0gYWxsb2NhdGVfY291bnQKICAgICAgcmVtYWluaW5nX2NvdW50IC09IGFsbG9jYXRlX2NvdW50CiAgICAgIGFzc2lnbmVkX2dyb3VwcyArPSAxCgogICAgIyBEaXN0cmlidXRlIHJlbWFpbmluZyBzdHVkZW50cyBvbmUgYnkgb25lCiAgICB3aGlsZSByZW1haW5pbmdfY291bnQgPiAwOgogICAgICBtaW5fZ3JvdXAgPSBtaW4oZ3JvdXBfY291bnRzLCBrZXk9Z3JvdXBfY291bnRzLmdldCkKICAgICAgYWxsb2NhdGlvbltzY2hvb2xdLmFwcGVuZCgobWluX2dyb3VwLCAxKSkKICAgICAgZ3JvdXBfY291bnRzW21pbl9ncm91cF0gKz0gMQogICAgICByZW1haW5pbmdfY291bnQgLT0gMQoKICByZXR1cm4gYWxsb2NhdGlvbgoKIyBFeGFtcGxlIHVzYWdlCnNjaG9vbHMgPSB7CiAgICAia3B1IjogMzksCiAgICAiYmlqIjogMjcsCiAgICAiTXVsbGFoaWtoZWRhIjogMzQsCiAgICAiU0tQIjogNTYsCiAgICAia2FtYWxwdXIiOiAxNywKICAgICJBbGluYWdhciI6IDE0Cn0KZ3JvdXBzID0gWyJUdXNoYXIgcmVkIiwgIkFkaGVlcCIsICJWYWxlbnRpbmEiLCAiS2F2aXRhIiwgIk1hbmphcmkiLCAiU3VyYWJoaSIsICJWaXNoYWwiLCAiU3VraG1hbmkiLCAicGxhbmV0YXJpdW0iXQoKYWxsb2NhdGlvbiA9IGFsbG9jYXRlX3N0dWRlbnRzKHNjaG9vbHMsIGdyb3VwcykKCmlmIGFsbG9jYXRpb246CiAgZm9yIHNjaG9vbCwgZ3JvdXBzX2FuZF9jb3VudHMgaW4gYWxsb2NhdGlvbi5pdGVtcygpOgogICAgcHJpbnQoZiJ7c2Nob29sfToiKQogICAgZm9yIGdyb3VwLCBjb3VudCBpbiBncm91cHNfYW5kX2NvdW50czoKICAgICAgcHJpbnQoZiIgIHtncm91cH06IHtjb3VudH0iKQplbHNlOgogIHByaW50KCJBbGxvY2F0aW9uIG5vdCBwb3NzaWJsZS4iKSAgIyBUaGlzIHNob3VsZCByYXJlbHkgaGFwcGVuCgo=