• # Aujourd'hui, on fait dans le sale.

    Posté par . En réponse au message Avent du Code, jour 21. Évalué à 2. Dernière modification le 21 décembre 2022 à 23:56.

    J'ai mis grosso modo 1h15.
    Pour faire l'éval, j'ai utilisé un parser JEXL. Le problème est qu'il travaille en double & qu'il m'a fallut passer en BigDecimal pour éviter les pertes de précisions du au double.
    Résultat, j'ai été obligé de transformer les expression pour utiliser des BigDecimal.
    çà m'a permit de trouver rapidement la première étoile.

    La deuxième étoile.
    J'ai déjà commencé par réduire l'arbre d'évaluation, en gros tout ce qui ne dépend pas de humn.

    Puis, j'ai rapidement vu que la fonction décroissé. J'aurai pu tenter une recherche dichotomique dans l'espace d'entier.
    Mais j'étais trop fatigué pour coder un truc intelligent.
    Résultat, j'ai monté une boucle qui permet de suivre l'évolution, j'ai joué manuellement sur les paramétres pour trouver la valeur

    C'est tellement sale que je partage mon code pour une fois :-p

    import java.math.BigDecimal;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Scanner;
    import org.apache.commons.jexl3.JexlBuilder;
    import org.apache.commons.jexl3.JexlContext;
    import org.apache.commons.jexl3.JexlEngine;
    import org.apache.commons.jexl3.JexlExpression;
    import org.apache.commons.jexl3.MapContext;
    public class A2022D21S2 {
     private static final JexlEngine jexl = new JexlBuilder().cache(512).strict(true).silent(false).create();
     public static void main(String[] args) { 
     step1();
     }
     private static void step1() {
     Map<String, String> mapMonkey = new HashMap<>();
     try (Scanner in = new Scanner(A2022D21S2.class.getResourceAsStream("/res/i21.txt"))) {
     while (in.hasNext()) {
     String row = in.nextLine();
     String[] part = row.split(":");
     if(part.length > 2) {
     throw new RuntimeException();
     }
     if(part[0].equals( "root")) {
     part[1] = part[1].replaceAll(" ", "").replaceAll("\\+", "-");
     System.out.println("root:" + part[1]);
     }
     mapMonkey.put(part[0], part[1]);
     }
     }
     for (Map.Entry<String, String> entry : mapMonkey.entrySet()) {
     if (canReduce(mapMonkey, entry.getKey())) {
     BigDecimal d = evalMonkey(mapMonkey, entry.getKey());
     System.out.println("Reduce " + entry.getKey() + ":" + d.toPlainString());
     mapMonkey.put(entry.getKey(), d.toPlainString());
     }
     }
     System.out.println("=========================");
     Double previous = null;
     for(long x=3876907167000L;x < 3876907168000L;x+= 1L) {
     BigDecimal bdx = new BigDecimal(x);
     mapMonkey.put("humn", bdx.toString());
     BigDecimal currentResult = evalMonkey(mapMonkey, "root");
     if(currentResult.doubleValue() == 0.0) {
     System.out.println("Found:" + x);
     break;
     }
     System.out.println(x + "=>" + currentResult.toPlainString());
     if(previous != null) {
     System.out.println(previous > currentResult.doubleValue() ? "diminue" : "augmente");
     }
     previous = currentResult.doubleValue();
     }
     }
     private static boolean canReduce(Map<String, String> mapMonkey, String key) {
     String expr = mapMonkey.get(key);
     if(expr.matches("[ 0-9.]*")) {
     return true;
     }
     for(String other: mapMonkey.keySet()) {
     if(expr.contains(other)) {
     if("root".equals(other) || "humn".equals(other)) {
     return false;
     } 
     boolean r = canReduce(mapMonkey, other);
     if(! r) {
     return false;
     } 
     }
     }
     return true;
     }
     public static final BigDecimal MINUS_ONE = BigDecimal.valueOf(-1L);
     public static final BigDecimal ZERO = BigDecimal.valueOf(0L);
     public static final BigDecimal ONE = BigDecimal.valueOf(1L);
     private static BigDecimal evalMonkey(Map<String, String> mapMonkey, String name) {
     String expr = mapMonkey.get(name);
     if(expr.matches("[ 0-9.]*")) {
     return new BigDecimal(expr.replaceAll(" " , ""));
     }
     JexlContext context = new MapContext();
     context.set("MINUS_ONE", MINUS_ONE);
     for(String other: mapMonkey.keySet()) {
     if(expr.contains(other)) {
     context.set(other, evalMonkey(mapMonkey, other)); 
     }
     }
     expr = expr.replaceAll(" ", "");
     //System.out.println("Eval:" + expr);
     JexlExpression e = jexl.createExpression( expr );
     BigDecimal bdBigDecimal;
     expr = expr.replaceAll("\\+([a-z]*)", ".add(1ドル)"); 
     expr = expr.replaceAll("\\*([a-z]*)", ".multiply(1ドル)");
     expr = expr.replaceAll("\\/([a-z]*)", ".divide(1ドル)");
     expr = expr.replaceAll("\\-([a-z]*)", ".add(1ドル.mulitply(MINUS_ONE))");
     //System.out.println("Eval2:" + expr);
     Object o =e.evaluate(context);
     if(o instanceof BigDecimal) {
     return (BigDecimal)o;
     }
     if(o instanceof Boolean) {
     return Boolean.TRUE.equals(o) ? ONE : ZERO;
     }
     throw new RuntimeException();
     }
    }