'how to select best combination of different lines

A few time ago I started playing an old RPG I had was I was young.

You have to make a group of 4 characters, each one having a value in the skill list from 0 (can't learn the skill) to 5 (Mastery of the skill).

It looks a bit like this for example:

         Shield Sword Magic
Knight     5      5     0
Ranger     2      3     3
Sorcerer   0      0     5

With of course many more skills and many more classes.

So I thought about making a script that can test all classes combination and give me the 4 characters that give me the most mastery skills at the end.

But I don't need 2 skills to be max out by 2 different characters, for example if sorcerer can get a 5 in magic, I don't necessarily need another char that can do it.

My idea was to go on a some for loop which will compare all the values in the selected skill column for all the 4 heroes combinations, then proceed to the next one, etc...

But I have no idea where to start and how to do it. Any ideas?

Have a nice day all



Solution 1:[1]

An example implementation of my comment, no Pandas required.

import itertools
from collections import Counter

class_infos = {
    "knight": {"shield": 5, "sword": 5},
    "ranger": {"shield": 2, "sword": 3, "magic": 3},
    "sorcerer": {"magic": 5},
    "street_urchin": {"shield": 1, "sword": 1, "magic": 1},
}


def score_party(party_classes):
    skill_totals = Counter()
    skill_occurrences = Counter()

    for char_cls in party_classes:
        char_skills = class_infos[char_cls]
        skill_totals.update(char_skills)  # Sum up skill points
        # Sum up occurrences of skills in the party composition.
        skill_occurrences.update({skill for skill, value in char_skills.items() if value})

    total_skill = sum(skill_totals.values())
    # Figure out how many skills are non-unique.
    skills_with_overlap = {skill for (skill, chars) in skill_occurrences.items() if chars > 1}
    # TODO: adjust this divisor – right now it just looks at the number of skills
    #       that overlap between characters, and quite heavily penalizes them.
    divisor = 1 + len(skills_with_overlap)
    return total_skill / divisor


def main():
    num_party_members = 2
    party_scores = {
        frozenset(party): score_party(party)
        for party in itertools.combinations(class_infos, num_party_members)
    }

    for party, score in sorted(party_scores.items(), key=lambda x: x[1], reverse=True):
        print(sorted(party), score)


if __name__ == "__main__":
    main()

The output (for these example numbers and parties of 2)

['knight', 'sorcerer'] 15.0
['ranger', 'sorcerer'] 6.5
['knight', 'ranger'] 6.0
['knight', 'street_urchin'] 4.33
['sorcerer', 'street_urchin'] 4.0
['ranger', 'street_urchin'] 2.75

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 AKX