Comment ai-je sauvé Mars ou une petite quête de python

Bonjour tout le monde!

Août 2018


C'est un été chaud dehors, qui se termine en douceur, et je suis assis dans une pièce fraîche avec un ordinateur portable et je surfe sur Internet à la recherche de choses intéressantes. Ayant perdu espoir de trouver quoi que ce soit digne d'attention, je suis soudain tombé sur l'un des groupes quasi-silencieux plutôt populaires sur VKontakte avec un lien vers une autre ressource informatique. La quête m'a semblé intéressante, car il s'agit presque d'une quête de texte classique dans un espace, et même vous devez programmer ici!



Par conséquent, dans cet article, nous parlerons de la façon dont j'ai joué pour résoudre cette quête.

Le lien nous attend avec une introduction à la quête avec le texte suivant:

2022 . - KASP 120 .

, . , - KASP . — .


Après avoir choisi un langage - C ++, C # et Python sont disponibles, nous attendons une page avec un "message du MCC", qui est un ensemble de caractères dans un encodage spécifique. Pour passer à l'étape suivante, vous devez décoder le message en triant les morceaux du message afin d'augmenter la longueur du message et entrer le hachage md5 du message reçu.
Mais quelle sorte, dites-vous? Le fait que ce message soit un certain codage devient immédiatement clair que l'on peut facilement comprendre en utilisant une ressource similaire, par exemple.

Ayant compris qu'il s'agit de base64 , nous commençons à le décoder. Je l'ai fait en python :

Décoder base64:
 import base64 code = """=""" def base64ToString(b): return base64.b64decode(b).decode('utf-8') decodedJSON = base64ToString(code) print(decodedJSON) 

Après la sortie, il devient clair que les données sont au format JSON:

Un tel jason que nous obtenons:
[{"id":31,"s":"ony: 1 man"},{"id":27,"s":"de all spe"},{"id":61,"s":"s will fac"},{"id":55,"s":"out men, a"},{"id":42,"s":"ntists.\n2."},{"id":18,"s":"n. Our soc"},{"id":70,"s":"the planet"},{"id":5,"s":". One oper"},{"id":64,"s":" condition"},{"id":44,"s":"y have to "},{"id":49,"s":"st 51% of "},{"id":58,"s":"ists must "},{"id":71,"s":". Select p"},{"id":59,"s":"be male.\n3"},{"id":85,"s":"he followi"},{"id":43,"s":" The colon"},{"id":73,"s":" resilienc"},{"id":24,"s":"selection."},{"id":62,"s":"e all kind"},{"id":47,"s":"nerations,"},{"id":105,"s":"eople who "},{"id":103,"s":"rmation, s"},{"id":22,"s":"ias to sim"},{"id":86,"s":"ng format:"},{"id":2,"s":"p's lander"},{"id":36,"s":" computer "},{"id":48,"s":" so at lea"},{"id":16,"s":"for Mars c"},{"id":75,"s":"0 and more"},{"id":11,"s":". You have"},{"id":95,"s":"emale = 0,"},{"id":68,"s":"ple should"},{"id":41,"s":"s, 14 scie"},{"id":7,"s":", but is u"},{"id":98,"s":"e rating\ne"},{"id":0,"s":"Two of the"},{"id":101,"s":".\n\nKnowing"},{"id":33,"s":"oks, 4 ele"},{"id":97,"s":";Resilienc"},{"id":51,"s":"olonists m"},{"id":108,"s":"d Planet."},{"id":100,"s":"break - \\n"},{"id":60,"s":". Colonist"},{"id":40,"s":"8 mechanic"},{"id":78,"s":"100.\n\nThe "},{"id":1,"s":" three shi"},{"id":13,"s":"0 most app"},{"id":12,"s":" to pick 4"},{"id":93,"s":"ID;Profess"},{"id":104,"s":"elect 40 p"},{"id":39,"s":"5 medics, "},{"id":8,"s":"nable to c"},{"id":52,"s":"ust be fem"},{"id":96,"s":" male = 1)"},{"id":89,"s":"female = 0"},{"id":10,"s":" colonists"},{"id":65,"s":"s. Only th"},{"id":35,"s":"gineers, 5"},{"id":21,"s":"ree criter"},{"id":17,"s":"olonisatio"},{"id":54,"s":" forget ab"},{"id":15,"s":"andidates "},{"id":87,"s":" ID;Profes"},{"id":37,"s":"system spe"},{"id":79,"s":"file attac"},{"id":90,"s":", male = 1"},{"id":29,"s":"ssential f"},{"id":107,"s":"ize the Re"},{"id":6,"s":"ates fully"},{"id":66,"s":"e most res"},{"id":32,"s":"ager, 3 co"},{"id":63,"s":"s of harsh"},{"id":4,"s":"unctioning"},{"id":82,"s":"tains a li"},{"id":38,"s":"cialists, "},{"id":74,"s":"e rating 6"},{"id":77,"s":"from 1 to "},{"id":19,"s":"iologists "},{"id":3,"s":"s are malf"},{"id":53,"s":"ale. Don't"},{"id":23,"s":"plify the "},{"id":28,"s":"cialists e"},{"id":88,"s":"sion;Sex ("},{"id":94,"s":"ion;Sex (f"},{"id":106,"s":"will colon"},{"id":25,"s":"\n\n1. Crew "},{"id":102,"s":" this info"},{"id":91,"s":");Resilien"},{"id":81,"s":"s task con"},{"id":57,"s":"% of colon"},{"id":76,"s":" on scale "},{"id":30,"s":"or the col"},{"id":80,"s":"hed to thi"},{"id":14,"s":"ropriate c"},{"id":72,"s":"eople with"},{"id":69,"s":" colonize "},{"id":9,"s":"ontain 120"},{"id":20,"s":"defined th"},{"id":67,"s":"ilient peo"},{"id":50,"s":"selected c"},{"id":99,"s":"tc. \nLine "},{"id":83,"s":"st of colo"},{"id":56,"s":"t least 30"},{"id":84,"s":"nists in t"},{"id":34,"s":"ctrical en"},{"id":45,"s":"exist for "},{"id":92,"s":"ce rating\n"},{"id":26,"s":"must inclu"},{"id":46,"s":"several ge"}]


Dans chaque élément du tableau, il y a un paramètre "id" - c'est un numéro de série, et nous allons trier les morceaux de message par celui-ci. Compliquons notre code:

Code précédent avec améliorations:
 import base64 import json import hashlib code = """=""" def base64ToString(b): return base64.b64decode(b).decode('utf-8') def sortbylen(sortlist): return sortlist[ids] decodedJSON = base64ToString(code) print(decodedJSON) sortString = json.loads(decodedJSON) sortList = list() for item in sortString: sortList.append(item) elem = sortList[0] ids = list(elem.keys())[0] messages = list(elem.keys())[1] sortList.sort(key=sortbylen) finallyDecodedString = '' for item in sortList: finallyDecodedString = finallyDecodedString + '' + str(item[messages]) print(finallyDecodedString + '\n') print('Md5 hash: ' + hashlib.md5(finallyDecodedString.encode('utf-8')).hexdigest()) 


En conséquence, nous obtenons le message et le hachage md5 du message:

Two of the three ship's landers are malfunctioning. One operates fully, but is unable to contain 120 colonists. You have to pick 40 most appropriate candidates for Mars colonisation. Our sociologists defined three criterias to simplify the selection.

1. Crew must include all specialists essential for the colony: 1 manager, 3 cooks, 4 electrical engineers, 5 computer system specialists, 5 medics, 8 mechanics, 14 scientists.
2. The colony have to exist for several generations, so at least 51% of selected colonists must be female. Don't forget about men, at least 30% of colonists must be male.
3. Colonists will face all kinds of harsh conditions. Only the most resilient people should colonize the planet. Select people with resilience rating 60 and more on scale from 1 to 100.

The file attached to this task contains a list of colonists in the following format: ID;Profession;Sex (female = 0, male = 1);Resilience rating
ID;Profession;Sex (female = 0, male = 1);Resilience rating
etc.
Line break - \n.

Knowing this information, select 40 people who will colonize the Red Planet.

Md5 hash: 88f57ef56978a95f044183951eabef3b


Le message est accompagné d'un fichier contenant des informations sur les colons au format suivant:

1;electrical engineer;0;90
2;mechanic;0;77
3;scientist;1;71


Le format est: ID; Profession; Sexe (femme = 0, homme = 1); Cote de durabilité

Il est proposé que sur 120 colons, un score de 40 soit atteint et répondant aux critères suivants:

  1. La colonie devrait avoir 1 directeur, 3 cuisiniers, 4 électriciens, 5 informaticiens, 5 médecins, 8 mécaniciens et 14 scientifiques.
  2. Les colonies devront exister pendant plus d'un an, donc au moins 51% de la population doit être composée de femmes. Mais au moins 30% des colons doivent être des hommes.
  3. Vivre dans une colonie n'est pas si facile et amusant, il vous suffit donc de sélectionner des candidats dont la note de durabilité est de 60 unités ou plus sur une échelle de 1 à 100.

Et maintenant, nous procédons à la sélection des colons!

Nous sélectionnons ...
 import random import math import sys colonists_list = list() new_colonists_list_male = list() new_colonists_list_female = list() manager_fem_list = list() manager_mal_list = list() cook_fem_list = list() cook_mal_list = list() elen_fem_list = list() elen_mal_list = list() compspec_fem_list = list() compspec_mal_list = list() doc_fem_list = list() doc_mal_list = list() mech_fem_list = list() mech_mal_list = list() sci_fem_list = list() sci_mal_list = list() lucky_colonists = list() luck_list = [random.randint(0, 100) for i in range(100)] managers = 1 cooks = 3 electrical_engineers = 4 computer_system_specialists = 5 medics = 5 mechanics = 8 scientists = 14 def pick_percentage(low, high): return random.randint(low, high)/100 perc_male = pick_percentage(30, 49) perc_female = pick_percentage(51, 69) quantity_required = 40 quantity_of_women_required = math.ceil(quantity_required * perc_female) min_percentage_fem = quantity_of_women_required/quantity_required quantity_of_men_required = quantity_required * perc_male min_percentage_mal = quantity_of_men_required/quantity_required unsorted_list = list() while 1: try: line = input() except EOFError: break unsorted_list.append(line) sorted_list = list() for i in unsorted_list: sorted_list.append(i.split(';')) #    for item in sorted_list: if int(item[3]) >= 60: colonists_list.append(item) counter = 0 conditions = "1. Crew must include all specialists essential for the colony: 1 manager, 3 cooks," \ " 4 electrical engineers, 5 computer system specialists, 5 medics, 8 mechanics, 14 " \ "scientists. 2. The colony have to exist for several generations, so at least 51% " \ "of selected colonists must be female. Don't forget about men, at least 30% of colonists must be male."\ "3. Colonists will face all kinds of harsh conditions. Only the most resilient people should colonize " \ "the planet. Select people with resilience rating 60 and more on scale from 1 to 100." #   for item in colonists_list: if int(item[2]) == 0: new_colonists_list_female.append(item) #   for item in colonists_list: if int(item[2]) == 1: new_colonists_list_male.append(item) #     for item in new_colonists_list_female: if item[1] == 'manager': manager_fem_list.append(item) if item[1] == 'cook': cook_fem_list.append(item) if item[1] == 'electrical engineer': elen_fem_list.append(item) if item[1] == 'computers specialist': compspec_fem_list.append(item) if item[1] == 'doctor': doc_fem_list.append(item) if item[1] == 'mechanic': mech_fem_list.append(item) if item[1] == 'scientist': sci_fem_list.append(item) #     for item in new_colonists_list_male: if item[1] == 'manager': manager_mal_list.append(item) if item[1] == 'cook': cook_mal_list.append(item) if item[1] == 'electrical engineer': elen_mal_list.append(item) if item[1] == 'computers specialist': compspec_mal_list.append(item) if item[1] == 'doctor': doc_mal_list.append(item) if item[1] == 'mechanic': mech_mal_list.append(item) if item[1] == 'scientist': sci_mal_list.append(item) #   def percentage_is_ok(colonists): female_quantity = 0 female_is_ok = 1 male_is_ok = 1 for i in colonists: if int(i[2]) == 0: female_quantity = female_quantity + 1 percentage_female = female_quantity/int(len(colonists)) percentage_male = 1 - percentage_female if percentage_female < min_percentage_fem: female_is_ok = 0 elif percentage_male < min_percentage_mal: male_is_ok = 0 return [female_is_ok, male_is_ok, percentage_female, percentage_male, female_quantity] def choose_colonists(female, male, quantity, resulting_list): for i in range(quantity): if int(percentage_is_ok(resulting_list)[0]) == 0 and len(female) > 0: colonist_choice = random.choice(female) resulting_list.append(colonist_choice) female.remove(colonist_choice) elif int(percentage_is_ok(resulting_list)[1]) == 0 and len(male) > 0: colonist_choice = random.choice(male) resulting_list.append(colonist_choice) male.remove(colonist_choice) else: if len(male) > 0 and len(female) > 0: sex_choice = random.choice([female, male]) colonist_choice = random.choice(sex_choice) resulting_list.append(colonist_choice) sex_choice.remove(colonist_choice) else: if len(male) == 0: colonist_choice = random.choice(female) resulting_list.append(colonist_choice) sex_choice.remove(colonist_choice) elif len(female) == 0: colonist_choice = random.choice(male) resulting_list.append(colonist_choice) sex_choice.remove(colonist_choice) #  if int(random.choice(luck_list)) >= 50: choice = random.choice(manager_fem_list) lucky_colonists.append(choice) else: choice = random.choice(manager_mal_list) lucky_colonists.append(choice) #  choose_colonists(cook_fem_list, cook_mal_list, cooks, lucky_colonists) #  choose_colonists(elen_fem_list, elen_mal_list, electrical_engineers, lucky_colonists) #   choose_colonists(compspec_fem_list, compspec_mal_list, computer_system_specialists, lucky_colonists) #  -   doctors_left = 1 for i in range(medics): if int(percentage_is_ok(lucky_colonists)[0]) == 0: choice = random.choice(doc_fem_list) lucky_colonists.append(choice) doc_fem_list.remove(choice) elif doctors_left > 0: choice = random.choice(doc_mal_list) lucky_colonists.append(choice) doc_mal_list.remove(choice) doctors_left = 0 else: choice = random.choice(doc_fem_list) lucky_colonists.append(choice) doc_fem_list.remove(choice) #  -   mechanics_male_left = 6 for i in range(mechanics): if int(percentage_is_ok(lucky_colonists)[0]) == 0: choice = random.choice(mech_fem_list) lucky_colonists.append(choice) mech_fem_list.remove(choice) elif mechanics_male_left > 0: choice = random.choice(mech_mal_list) lucky_colonists.append(choice) mech_mal_list.remove(choice) mechanics_male_left = mechanics_male_left - 1 else: choice = random.choice(mech_fem_list) lucky_colonists.append(choice) #  choose_colonists(sci_fem_list, sci_mal_list, scientists, lucky_colonists) colonists_string = '' for item in lucky_colonists: colonists_string = colonists_string + item[0] + ';' colonists_string = colonists_string[0:len(colonists_string)-1] # sys.stdout.write(colonists_string) 


Le formulaire du site reprend le code et le teste automatiquement. Les données sont fournies par le flux d'entrée standard, pour la même raison, vous devez les lire à partir de là, ce qui complique un peu le test de code lors de l'écriture.

Janvier 2019


Je voulais partager avec vous cette expérience plutôt intéressante de participer à de telles quêtes. Pour moi, il a été le premier. Il me semble que l'idée est intéressante même sans base concurrentielle. Personnellement, j'ai résolu 5 tâches de différents types. J'ai mis le reste sur le lien vers github.

Et aussi, en récompense, à la fin, il y a un tableau de notation avec votre temps. Pour moi, le meilleur résultat était le suivant:



Le résultat, une 50ème place symbolique sur plus de 400 participants.

Que peut-on en dire? Pour moi, c'était une programmation passionnante. Soit dit en passant, des missions sont toujours disponibles pour ceux qui souhaitent les résoudre, malgré le fait que le concours soit terminé depuis longtemps.

Source: https://habr.com/ru/post/fr435286/


All Articles