T: / Corrigés des challenges / Java
Manipulation de chaines de caractères, construction d’une classe et utilisation de Map
On poursuit les corrigés de l’édition 2025 de la Battle Dev Thales. Dans ce challenge, il était question de récupérer différentes informations sur des abris afin de leur calculer un « état vital ». Il fallait faire ce calcul pour tous les abris afin de trouver celui avec l’état vital le + élevé ainsi que la moyenne de l’état vital de tous les abris.
Spoiler alert : chaque jeu de données renvoyait l’abri « PRO » (= PROméthes) comme meilleur abri. Cela permettait de lancer la suite de l’histoire…
3 grandes étapes pour résoudre ce challenge
La complexité de ce challenge était assez abordable, mais sa résolution pouvait demander « beaucoup » de code. Pour ce corrigé, on va le résoudre en Java, avec une approche orientée objet très structurée.
On va structurer la classe Shelter avec toutes les informations qu’un abri peut contenir :
class Shelter {
// Propriétés
private String trigram;
private int equipement;
private int nourriture;
private int sante;
private int score;
// Constructeur
public Shelter(String trigram, int equipement, int nourriture, int sante) {
this.trigram = trigram;
this.equipement = equipement;
this.nourriture = nourriture;
this.sante = sante;
}
}
On crée donc les propriétés, avec les types associés et le constructeur qui va avec, qui permet de définir chaque propriété, à l’exception du score qui sera calculé plus tard.
Mais comme le challenge nous fournit les informations d’un abri sous cette forme « QXG_E:15_N:19_S:16 », on ne peut pas utiliser le constructeur tel quel. Il faut parser ces données préalablement. C’est là qu’il est intéressant de créer une méthode statique dans la class Shelter, qui sera à la fois chargée de parser les données ET de retourner une nouvelle instance de Shelter :
public static Shelter fromString(String data) {
String[] parts = data.split("_");
String trigram = parts[0];
int e = Integer.parseInt(parts[1].split(":")[1]);
int n = Integer.parseInt(parts[2].split(":")[1]);
int s = Integer.parseInt(parts[3].split(":")[1]);
return new Shelter(trigram, e, n, s);
}
Un peu d’explications :
Les informations étant maintenant stockées dans des propriétés, on peut s’en servir pour calculer l’état vital (score) et le stocker dans l’objet. Voici la méthode que l’on peut mettre en place :
public void calculateScore() {
double base = (equipement * 0.25 + nourriture * 0.40 + sante * 0.35) * 2.25;
if (equipement >= 15 && nourriture >= 15 && sante >= 15) {
base += 8; // bonus
}
if (nourriture <= 10 || sante <= 10) {
base -= 10; // malus
}
base = Math.max(0, Math.min(100, base)); // bornes 0–100
this.score = (int) Math.floor(base);
}
Un peu d’explications :
Comme les propriétés trigram et score sont privés, il nous faut 2 getters pour pouvoir y accéder depuis le programme principal. Il n’y en a pas besoin pour les autres propriétés :
public String getTrigram() { return trigram; }
public int getScore() { return score; }
Voici la classe Shelter complète :
class Shelter {
private String trigram;
private int equipement;
private int nourriture;
private int sante;
private int score;
public Shelter(String trigram, int equipement, int nourriture, int sante) {
this.trigram = trigram;
this.equipement = equipement;
this.nourriture = nourriture;
this.sante = sante;
}
// Méthode de parsing à partir de la chaîne "ABC_E:10_N:20_S:30"
public static Shelter fromString(String data) {
String[] parts = data.split("_");
String trigram = parts[0];
int e = Integer.parseInt(parts[1].split(":")[1]);
int n = Integer.parseInt(parts[2].split(":")[1]);
int s = Integer.parseInt(parts[3].split(":")[1]);
return new Shelter(trigram, e, n, s);
}
// Calcul du score selon les règles données
public void calculateScore() {
double base = (equipement * 0.25 + nourriture * 0.40 + sante * 0.35) * 2.25;
if (equipement >= 15 && nourriture >= 15 && sante >= 15) {
base += 8; // bonus
}
if (nourriture <= 10 || sante <= 10) {
base -= 10; // malus
}
base = Math.max(0, Math.min(100, base)); // bornes 0–100
this.score = (int) Math.floor(base);
}
// Getters
public String getTrigram() { return trigram; }
public int getScore() { return score; }
}
Et le programme principal :
public class Challenge {
public static void main(String[] args) {
//== NE PAS TOUCHER
String[] shelters = {
"QXG_E:15_N:19_S:16", "OKE_E:24_N:6_S:7", "GCJ_E:21_N:3_S:7",
"GLH_E:13_N:11_S:12", "HAF_E:9_N:12_S:12", "VKL_E:1_N:5_S:3",
"HRS_E:25_N:5_S:21", "PRO_E:32_N:33_S:38", "CEX_E:22_N:8_S:28",
"MNN_E:8_N:20_S:14"
};
//== NE PAS TOUCHER
// Map pour stocker les résultats
Map<String, Integer> scores = new HashMap<>();
int total = 0;
// Parsing et calcul du score
for (String data : shelters) {
Shelter s = Shelter.fromString(data);
s.calculateScore();
scores.put(s.getTrigram(), s.getScore());
total += s.getScore();
}
// Recherche du meilleur abri
String best = Collections.max(scores.entrySet(), Map.Entry.comparingByValue()).getKey();
int bestScore = scores.get(best);
// Moyenne des scores arrondie à l'entier inférieur
int avg = (int) Math.floor((double) total / shelters.length);
// Résultat final
System.out.println(best + "_" + bestScore + "_" + avg);
}
}
Un peu d’explications :
Ce corrigé montre comment transformer des données textuelles en informations exploitables grâce à un parsing simple, une structuration des données dans une classe, et l’utilisation d’une Map pour identifier, comparer et agréger les résultats de façon claire en Java.