| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import bisect |
| from typing import List, Sequence, Tuple |
|
|
|
|
| def search_for_fit(numbers: Sequence[int], capacity: int) -> int: |
| r""" |
| Finds the index of largest number that fits into the knapsack with the given capacity. |
| """ |
| index = bisect.bisect(numbers, capacity) |
| return -1 if index == 0 else (index - 1) |
|
|
|
|
| def greedy_knapsack(numbers: List[int], capacity: int) -> List[List[int]]: |
| r""" |
| An efficient greedy algorithm with binary search for the knapsack problem. |
| """ |
| numbers.sort() |
| knapsacks = [] |
|
|
| while numbers: |
| current_knapsack = [] |
| remaining_capacity = capacity |
|
|
| while True: |
| index = search_for_fit(numbers, remaining_capacity) |
| if index == -1: |
| break |
|
|
| remaining_capacity -= numbers[index] |
| current_knapsack.append(numbers.pop(index)) |
|
|
| knapsacks.append(current_knapsack) |
|
|
| return knapsacks |
|
|
|
|
| def infer_seqlen(source_len: int, target_len: int, cutoff_len: int) -> Tuple[int, int]: |
| r""" |
| Computes the real sequence length after truncation by the cutoff_len. |
| """ |
| if target_len * 2 < cutoff_len: |
| max_target_len = cutoff_len |
| elif source_len * 2 < cutoff_len: |
| max_target_len = cutoff_len - source_len |
| else: |
| max_target_len = int(cutoff_len * (target_len / (source_len + target_len))) |
|
|
| new_target_len = min(max_target_len, target_len) |
| max_source_len = max(cutoff_len - new_target_len, 0) |
| new_source_len = min(max_source_len, source_len) |
| return new_source_len, new_target_len |
|
|