简体   繁体   中英

Difficulties with a permutational programming challenge “Goats” in Python

I have been assigned a task - to solve the following programming challenge:

Goats
George is with his herd of goats at the shore of a river. He wants to pass through the river with his goats by using a raft that has limited weight capacity, with no more than K courses. His goats are all different, with different weight. He wants to calculate what is the minimal capacity of the raft that would be able to get all of his N goats through the river with no more than K courses.
However, he has rules that he has to abide:
In every course, he first puts the heaviest available goat on the raft, then from those who are left he again puts the heaviest goat that won't be too heavy for the raft's capacity, then the next one and so on until there are no more goats that can go on the raft, because of its capacity. After that, he gets them to the other shore (makes a course) and gets back to get more goats on the raft and to make another course. (The capacity of the raft must be at least as much as the heaviest goat's weight)

Thus, I need to write a script that calculates what is the minimal capacity of the raft with a given amount of courses K , amount of goats N , and the weight of each of them ( A1, A2 and so on..). Because of it being a relatively small constant, George's weight is ignored (no need to add it to the calculations).

Everything noted up till now is per the requirements of the challenge.

An example of the result of a proper solution:

6 goats, 2 courses
Weight of each goat: 26, 7, 10, 30, 5, 4
Result (minimal capacity of the raft): 42
The courses are: (30, 10); (26, 7, 5, 4)
The following solution does not follow the rules: (30, 7, 4); (26, 10, 5) - because the goat that weights 10kg can be in the first course and it must be there per the rules.

My solution attempt:

import itertools

goatnum = 0
courses = 0
goatw = []
counter = 0

goatnum = int(input("Enter the number of goats: "))
courses = int(input("Enter the number of courses: "))
for g in range(goatnum):
    goatw.append(int(input("Enter the weight of goat #{}: ".format(g+1))))

goatw = sorted(goatw, reverse=True)
goats = sum(goatw)
result = []
permlen = len(goatw)/courses
while not result:
    result = [seq for i in range(len(goatw), 0, -1) for seq in itertools.permutations(goatw, permlen) if sum(seq) == int(goats/courses)]
    if not result:
        goats += 1
        permlen += 1
    else:
        break

print(result)

I am using permutations for the task, simply because I do not know another way to approach it. Currently from the result I only get solutions that do not abide the rules (for the given example). I get the solution (30, 7, 4); (26, 10, 5) (30, 7, 4); (26, 10, 5) inside, however, there are even no results with a course that has a different amount of goats than 3, all courses are with 3 goats.

My output for the given example (6 goats, 2 courses, w: 26,7,10,30,5,4):

[(30, 7, 4), (30, 4, 7), (26, 10, 5), (26, 5, 10), (10, 26, 5), (10, 5, 26), (7, 30, 4), (7, 4, 30), (5, 26, 10), (5, 10, 26), (4, 30, 7), (4, 7, 30), (30, 7, 4), (30, 4, 7), (26, 10, 5), (26, 5, 10), (10, 26, 5), (10, 5, 26), (7, 30, 4), (7, 4, 30), (5, 26, 10), (5, 10, 26), (4, 30, 7), (4, 7, 30), (30, 7, 4), (30, 4, 7), (26, 10, 5), (26, 5, 10), (10, 26, 5), (10, 5, 26), (7, 30, 4), (7, 4, 30), (5, 26, 10), (5, 10, 26), (4, 30, 7), (4, 7, 30), (30, 7, 4), (30, 4, 7), (26, 10, 5), (26, 5, 10), (10, 26, 5), (10, 5, 26), (7, 30, 4), (7, 4, 30), (5, 26, 10), (5, 10, 26), (4, 30, 7), (4, 7, 30), (30, 7, 4), (30, 4, 7), (26, 10, 5), (26, 5, 10), (10, 26, 5), (10, 5, 26), (7, 30, 4), (7, 4, 30), (5, 26, 10), (5, 10, 26), (4, 30, 7), (4, 7, 30), (30, 7, 4), (30, 4, 7), (26, 10, 5), (26, 5, 10), (10, 26, 5), (10, 5, 26), (7, 30, 4), (7, 4, 30), (5, 26, 10), (5, 10, 26), (4, 30, 7), (4, 7, 30)]

I am new to this kind of thing and I also got the example of the use of permutations from internet. Where is my code wrong? I know I can just make a function to check whether the results I have abide by the rules, and if not, fix the results, but I have no idea how to go about that. Any help would be appreciated.

I believe the problem you are having is that all the permutations you generate consist of 3 goats. If you were to generate all possible permutations of N goats and then slicing these permutations in K places, the correct solution would be among one of these lists. For example with 3 goats, A , B , and C we get these permutations:

(A,B,C), (A,C,B), (B,A,C), (B,C,A), (C,B,A), (C,A,B)

Let's say we have 2 courses. Now imagine we have K - 1 sticks (1 in this case) which we can place in N - 1 places (2 in this case) in each of these permutations. A stick can be placed in between any of the goats or at the edges. The stick serves as a separator deciding which groups of goats will go on each trip. In the general case you have K - 1 sticks to place and you do not want to place two sticks in the same spot since that would mean you would have one trip where no goats are on the boat. Then we get the following space in which we can search for a solution:

(A | B C), (A B | C)
(A | C B), (A C | B) 
(B | A C), (B A | C)
(B | C A), (B C | A)
(C | B A), (C B | A)
(C | A B), (C A | B)

Note that you could "place the stick" at the very left as well meaning that there would be one empty trip and one trip where all the goats go but obviously the optimal solution would not be found here since it will always be better to utilize as many of the trips as possible. Note that many of these possibilities will not abide by the rules since the goats need to be loaded in order, so these results need to be filtered to remove those that do not abide by the rules.

From here it just a matter of finding which one of these possibilities requires the minimum capacity boat and this can be calculated by calculating the largest sum in each of these possibilities and selecting the possiblity where this sum is the smallest.

So in conclusion, one way of solving this problem using permutations is to:

  1. Generate all possible permutations of the goats.

  2. Generate all the ways each permutation can be subdivided into K groups.

  3. Get rid of any of the candidates generated from step 2 which do not abide by the rules.

  4. From the remaining candidates, find the one where the heaviest trip is lighter than the heaviest trip of the other candidates.

This is by no means an optimal solution but it should do the job.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM