Program to find maximum length of k ribbons of same length in Python

Suppose we have a list of positive numbers representing ribbon lengths and a value k. We can cut the ribbons as many times as we want, and we need to find the largest length r such that we can have k ribbons of length r. If no such solution exists, return -1.

So, if the input is like ribbons = [1, 2, 5, 7, 15] and k = 5, then the output will be 5. We can cut the ribbon of size 15 into 3 pieces of length 5 each, cut the ribbon of size 7 into pieces of size 2 and 5, and use the existing ribbon of size 5. This gives us 5 ribbons total of size 5.

Algorithm

We use binary search to find the maximum possible ribbon length ?

  • Set left = 0 and right = maximum of ribbons
  • While left < right:
    • Calculate mid = (left + right + 1) // 2
    • Count how many ribbons of length mid we can get
    • If count ? k, search for larger length: left = mid
    • Otherwise, search for smaller length: right = mid - 1
  • Return left if non-zero, otherwise -1

Implementation

def solve(ribbons, k):
    left = 0
    right = max(ribbons)
    
    while left < right:
        mid = (left + right + 1) // 2
        # Count how many ribbons of length 'mid' we can get
        count = sum(ribbon_len // mid for ribbon_len in ribbons)
        
        if count >= k:
            left = mid  # Try for a larger length
        else:
            right = mid - 1  # Try for a smaller length
    
    return left if left > 0 else -1

# Test the function
ribbons = [1, 2, 5, 7, 15]
k = 5
result = solve(ribbons, k)
print(f"Maximum ribbon length: {result}")
Maximum ribbon length: 5

How It Works

Let's trace through the example step by step ?

def solve_with_trace(ribbons, k):
    left = 0
    right = max(ribbons)
    print(f"Initial range: [{left}, {right}]")
    
    while left < right:
        mid = (left + right + 1) // 2
        count = sum(ribbon_len // mid for ribbon_len in ribbons)
        
        print(f"Trying length {mid}: can get {count} ribbons")
        
        if count >= k:
            left = mid
            print(f"  Sufficient! New range: [{left}, {right}]")
        else:
            right = mid - 1
            print(f"  Not enough. New range: [{left}, {right}]")
    
    return left if left > 0 else -1

ribbons = [1, 2, 5, 7, 15]
k = 5
result = solve_with_trace(ribbons, k)
print(f"\nFinal answer: {result}")
Initial range: [0, 15]
Trying length 8: can get 3 ribbons
  Not enough. New range: [0, 7]
Trying length 4: can get 6 ribbons
  Sufficient! New range: [4, 7]
Trying length 6: can get 4 ribbons
  Not enough. New range: [4, 5]
Trying length 5: can get 5 ribbons
  Sufficient! New range: [5, 5]

Final answer: 5

Edge Cases

# Test edge cases
test_cases = [
    ([1, 2, 3], 10),  # Impossible case
    ([10, 20, 30], 3),  # Each ribbon used once
    ([5, 5, 5], 3),  # All same length
]

for ribbons, k in test_cases:
    result = solve(ribbons, k)
    print(f"ribbons={ribbons}, k={k} ? {result}")
ribbons=[1, 2, 3], k=10 ? -1
ribbons=[10, 20, 30], k=3 ? 10
ribbons=[5, 5, 5], k=3 ? 5

Conclusion

This solution uses binary search to efficiently find the maximum ribbon length in O(n log(max_length)) time. The key insight is that if we can make k ribbons of length x, we can also make k ribbons of any length smaller than x.

Updated on: 2026-03-26T17:03:05+05:30

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements