I have a coding problem that is very hard to explain, so I came up with this fruit swapping problem that is very easy to understand:
A fruiterer sells 3 kinds of fruits: apples (denoted as 'A'
), bananas (denoted as 'B'
) and coconuts (denoted as 'C'
). The weird thing about him is that he always prepares 10 bags (bag id 0 to 9), including 3 small bags that can contain 2 fruits, 3 medium bags that can contain 4 fruits, 3 large bags that can contain 8 fruits, and one extra large bag that can contain 16 fruits. He only puts in same type of fruit into each bag. This can be abstracted to the following python code:
import random
from string import ascii_uppercase
#length = 30
#max_size = 10
#bag_sizes = [random.randint(1, max_size) for _ in range(length)]
n_fruit = 3
bag_sizes = [2, 2, 2, 4, 4, 4, 8, 8, 8, 16]
random.seed(55)
fruiterer_bags = [[random.choice(ascii_uppercase[:n_fruit])] * bag_sizes[i]
for i in range(len(bag_sizes))]
print(fruiterer_bags)
Output:
[['A', 'A'], ['A', 'A'], ['A', 'A'],
['C', 'C', 'C', 'C'], ['B', 'B', 'B', 'B'], ['A', 'A', 'A', 'A'],
['C', 'C', 'C', 'C', 'C', 'C', 'C', 'C'],
['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'],
['B', 'B', 'B', 'B', 'B', 'B', 'B', 'B'],
['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A']]
Note that every day the fruiterer put fruits in each bag like this
The supplier comes to the fruit shop every day with the same 10 bags (3 small, 3 medium, 3 large, 1 extra large). He also only puts in same type of fruit in each bag, but the fruits he puts in are not exactly the same as the fruiterer's. Every day he comes with the following bags:
random.seed(100)
supplier_bags = [[random.choice(ascii_uppercase[:n_fruit])] * bag_sizes[i]
for i in range(len(bag_sizes))]
print(supplier_bags)
Output:
[['A', 'A'], ['B', 'B'], ['B', 'B'],
['A', 'A', 'A', 'A'], ['C', 'C', 'C', 'C'], ['B', 'B', 'B', 'B'],
['C', 'C', 'C', 'C', 'C', 'C', 'C', 'C'],
['B', 'B', 'B', 'B', 'B', 'B', 'B', 'B'],
['B', 'B', 'B', 'B', 'B', 'B', 'B', 'B'],
['C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C']]
The weirdest thing about this fruiterer is that every time the supplier comes, he wants to swap some bags because they are fresher. The supplier says "OK, fine. You can swap however you like, you can do as many swaps as you want, but:
- I don't swap the bags with the same type of fruits in them;
- I must have the same amount of each fruit after all the swaps;
- I only swap whole bags, not individual fruit;
- Each bag can only swap once;
- PLEASE BE FAST!"
Note that only supplier_bags
has to have the same amount of each fruit after the swaps, not necessarily fruiterer_bags
. Every day the fruiterer and supplier come with same bags of fruits, but hopefully they can find different ways of swapping bags (radomness).
My question is: is there any algorithm to get one possible solution very fast. The expected output is the indices of the bags being swapped. For example, one solution could be swap_ids = [1, 2, 3, 4]
, since the supplier_bags
after the swaps becomes:
new_supplier_bags =[
['A', 'A'], ['A', 'A'], ['A', 'A'],
['C', 'C', 'C', 'C'], ['B', 'B', 'B', 'B'], ['B', 'B', 'B', 'B'],
['C', 'C', 'C', 'C', 'C', 'C', 'C', 'C'],
['B', 'B', 'B', 'B', 'B', 'B', 'B', 'B'],
['B', 'B', 'B', 'B', 'B', 'B', 'B', 'B'],
['C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C']]
which still has the same amount of each fruit as before swaps. This can be checked by
assert sorted([f for bag in new_supplier_bags for f in bag]) == sorted(
[f for bag in supplier_bags for f in bag])
I don't want all possible solutions, but one fast solution with randomness. I want an algorithm to work for any given n_fruit
, bag_sizes
, fruiterer_bags
and supplier_bags
. I guess a greedy algorithm will do.
Also, Is there any way to quick check if there is a solution at all? If not, maybe we can say there is no solution after the greedy algorithm suggests e.g. 1000 wrong solutions (if fast enough).
Any suggestions?
Aucun commentaire:
Enregistrer un commentaire