¡Enfrentamiento de expresiones matemáticas!

15

Se le dan 6 números: 5 dígitos [0-9] y un número objetivo. Su objetivo es intercalar operadores entre los dígitos para acercarse lo más posible al objetivo. Usted tiene que utilizar cada dígito exactamente una vez, y puede utilizar los siguientes operadores tantas veces como desee: + - * / () ^ sqrt sin cos tan. Por ejemplo, si me dan 8 2 4 7 2 65puedo dar salida 82-(2*7)-4. Esto se evalúa a 64, lo que me da una puntuación de 1 ya que estaba 1 lejos del objetivo. Nota: No puede poner un punto decimal entre dígitos.

Estoy usando el código de esta respuesta de StackOverflow para evaluar las expresiones matemáticas. Al final de esta pregunta hay programas que puede usar para probarlo.

Funciones de encadenamiento (¡Actualización!)

@mdahmoune ha revelado un nuevo nivel de complejidad para este desafío. Como tal, estoy agregando una nueva característica: encadenar funciones unarias. Esto funciona en sin, cos, tan y sqrt. Ahora, en lugar de escribir sin(sin(sin(sin(10)))), puedes escribir sin_4(10). ¡Pruébalo en el evaluador!

Entrada

200 casos de prueba separados por líneas de 5 dígitos y un número de destino separados por espacios. Puede usar el programa al final de la pregunta para hacer casos de prueba de muestra, pero tendré mis propios casos de prueba para la calificación oficial. Los casos de prueba se dividen en 5 secciones de 40 pruebas con los siguientes rangos para el número objetivo:

  • Sección 1: [0,1] (a 5 puntos decimales)
  • Sección 2: [0,10] (a 4 puntos decimales)
  • Sección 3: [0,1000] (a 3 puntos decimales)
  • Sección 4: [0,10 6 ] (a 1 punto decimal)
  • Sección 5: [0,10 9 ] (a 0 puntos decimales)

Salida

200 expresiones matemáticas separadas por líneas. Por ejemplo, si el caso de prueba es 5 6 7 8 9 25.807, una posible salida podría ser78-59+6

Puntuación

El objetivo de cada ronda es acercarse al número objetivo que los otros programas competidores. Voy a utilizar Mario Kart 8 de puntuación , que es: . Si las respuestas múltiples obtienen el mismo puntaje exacto, los puntos se dividen en partes iguales, redondeados al int más cercano. Por ejemplo, si los programas en quinto a octavo lugar están empatados, cada uno obtiene (8 + 7 + 6 + 5) / 4 = 6.5 => 7 puntos en esa ronda. Al final de las 200 rondas, gana el programa que obtuvo más puntos. Si dos programas tienen el mismo número de puntos al final, el desempate es el programa que terminó de ejecutarse más rápido.1st: 15 2nd: 12 3rd: 10 4th: 9 5th: 8 6th: 7 7th: 6 8th: 5 9th: 4 10th: 3 11th: 2 12th: 1 13th+: 0

Reglas

  1. Solo puede usar uno de los lenguajes preinstalados comúnmente en Mac como C, C ++, Java, PhP, Perl, Python (2 o 3), Ruby y Swift. Si tiene un idioma que desea usar con un compilador / intérprete que es una descarga relativamente pequeña, puedo agregarlo. También puede usar un idioma con un intérprete en línea, pero eso no se ejecutará tan rápido.
  2. Especifique en su respuesta si desea que las funciones trigonométricas se calculen en grados o radianes .
  3. Su programa debe enviar sus soluciones a los 200 casos de prueba (a un archivo o STDOUT) en 60 segundos en mi Mac.
  4. La aleatoriedad debe ser sembrada.
  5. Su producción total para todos los casos de prueba no puede ser superior a 1 MB .
  6. Si ha mejorado su solución y desea volver a calificar, agregue Re-Score en negrita en la parte superior de su respuesta.

Programas

(cambie el argumento "deg" a "rad" si quiere radianes)

  1. Probar evaluador
  2. Califique la salida de su programa para casos de prueba
  3. Generar casos de prueba:

document.getElementById("but").onclick = gen;
var checks = document.getElementById("checks");
for(var i = 1;i<=6;i++) {
var val = i<6 ? i : "All";
var l = document.createElement("label");
l.for = "check" + val;
l.innerText = " "+val+" ";
checks.appendChild(l);
  var check = document.createElement("input");
  check.type = "checkBox";
  check.id = "check"+val;
  if(val == "All") {
  check.onchange = function() {
  if(this.checked == true)  {
  for(var i = 0;i<5;i++) {
    this.parentNode.elements[i].checked = true;
  }
  }
};  
  }
  else {
  check.onchange = function() {
    document.getElementById("checkAll").checked = false;
  }
  }
  checks.appendChild(check);
  
}



function gen() {
var tests = [];
var boxes = checks.elements;
if(boxes[0].checked)genTests(tests,1,5,40);
if(boxes[1].checked)genTests(tests,10,4,40);
if(boxes[2].checked)genTests(tests,1000,3,40);
if(boxes[3].checked)genTests(tests,1e6,1,40);
if(boxes[4].checked)genTests(tests,1e9,0,40);
document.getElementById("box").value =  tests.join("\n");
}

function genTests(testArray,tMax,tDec,n) {
for(var i = 0;i<n;i++) {
  testArray.push(genNums(tMax,tDec).join(" "));
}
}

function genNums(tMax,tDec) {
var nums = genDigits();
nums.push(genTarget(tMax,tDec));
return nums;
}

function genTarget(tMax,tDec) {
  return genRand(tMax,tDec);
}

function genRand(limit,decimals) {
  var r = Math.random()*limit;
  return r.toFixed(decimals);
}

function genDigits() {
  var digits = [];
   for(var i = 0;i<5;i++) {
    digits.push(Math.floor(Math.random()*10));
   }
   return digits;
}
textarea {
  font-size: 14pt;
  font-family: "Courier New", "Lucida Console", monospace;
}

div {
text-align: center;
}
<div>
<label for="checks">Sections: </label><form id="checks"></form>
<input type="button" id="but" value="Generate Test Cases" /><br/><textarea id="box" cols=20 rows=15></textarea>
</div>

Tabla de clasificación

  1. usuario202729 ( C ++ ): 2856, 152 victorias
  2. mdahmoune ( Python 2 ) [v2]: 2544, 48 victorias

Puntajes de sección (# de victorias):

  1. [0-1] usuario202729 : 40, mdahmoune: 0
  2. [0-10] usuario202729 : 40, mdahmoune: 0
  3. [0-1000] usuario202729 : 39, mdahmoune: 1
  4. [0-10 6 ] usuario202729 : 33, mdahmoune: 7
  5. [0-10 9 ] usuario202729: 0, mdahmoune : 40

Relacionado: generar una ecuación válida utilizando números especificados por el usuario

geokavel
fuente
¿Hay alguna razón específica para que las funciones trigonométricas tengan que usar grados? ¿Se podría agregar una opción para la respuesta para especificar radianes o grados?
notjagan
¿El conjunto de dígitos contiene necesariamente un dígito distinto de cero?
mdahmoune
@mdahmoune Los casos de prueba se generan aleatoriamente, por lo que los dígitos podrían ser todos 0. Simplemente tendría que hacer lo mejor en esa situación. En el modo de grado pude llegar hasta 3283.14 con cos(0)/sin(0^0)/sin(0^0).
geokavel
Gracias por tu respuesta completa :)
mdahmoune
¿Es el mismo método de puntuación para las 5 secciones diferentes? Abs (valor_expresión_de_valor_objetivo) I
mdahmoune

Respuestas:

3

C ++

// This program use radian mode

//#define DEBUG

#ifdef DEBUG
#define _GLIBCXX_DEBUG
#include <cassert>
#else
#define assert(x) void(0)
#endif

namespace std {
    /// Used for un-debug.
    struct not_cerr_t {
    } not_cerr;
}

template <typename T>
std::not_cerr_t& operator<<(std::not_cerr_t& not_cerr, T) {return not_cerr;}

#include <iostream>
#include <iomanip>
#include <cmath>
#include <limits>
#include <array>
#include <bitset>
#include <string>
#include <sstream>

#ifndef DEBUG
#define cerr not_cerr
#endif // DEBUG


// String conversion functions, because of some issues with MinGW
template <typename T>
T from_string(std::string st) {
    std::stringstream sst (st);
    T result;
    sst >> result;
    return result;
}

template <typename T>
std::string to_string(T x) {
    std::stringstream sst;
    sst << x;
    return sst.str();
}

template <typename T> int sgn(T val) {
    return (T(0) < val) - (val < T(0));
}


const int N_ITER = 1000, N_DIGIT = 5, NSOL = 4;
std::array<int, N_DIGIT> digits;
double target;

typedef std::bitset<N_ITER> stfunc; // sin-tan expression
// where sin = 0, tan = 1

double eval(const stfunc& fn, int length, double value) {
    while (length --> 0) {
        value = fn[length] ? std::tan(value) : std::sin(value);
    }
    return value;
}

struct stexpr { // just a stfunc with some information
    double x = 0, val = 0; // fn<length>(x) == val
    int length = 0;
    stfunc fn {};
//    bool operator[] (const int x) {return fn[x];}
    double eval() {return val = ::eval(fn, length, x);}
};

struct expr { // general form of stexpr
    // note that expr must be *always* atomic.
    double val = 0;
    std::string expr {};

    void clear() {
        val = 0;
        expr.clear();
    }

    // cos(cos(x)) is in approx 0.5 - 1,
    // so we can expect that sin(x) and tan(x) behaves reasonably nice
    private: void wrapcos2() {
        expr = "(cos_2 " + expr + ")"; // we assume that all expr is atomic
        val = std::cos(std::cos(val));
    }

    public: void wrap1() {
        if (val == 0) {
            expr = "(cos " + expr + ")"; // we assume that all expr is atomic
            val = std::cos(val);
        }
        if (val == 1) return;
        wrapcos2(); // range 0.54 - 1
        int cnt_sqrt = 0;
        for (int i = 0; i < 100; ++i) {
            ++cnt_sqrt;
            val = std::sqrt(val);
            if (val == 1) break;
        }
        expr = "(sqrt_" + to_string(cnt_sqrt) + " " + expr + ")"; // expr must be atomic
    }
};

stexpr nearest(double initial, double target) {
    stexpr result; // built on the fn of that
    result.x = initial;
    double value [N_ITER + 1];
    value[0] = initial;
    for (result.length = 1; result.length <= N_ITER; ++result.length) {
        double x = value[result.length-1];
        if (x < target) {
            result.fn[result.length-1] = 1;
        } else if (x > target) {
            result.fn[result.length-1] = 0;
        } else { // unlikely
            --result.length;
//            result.val = x;
            result.eval();
            assert(result.val == x);
            return result;
        }
        value[result.length] = result.eval(); // this line takes most of the time
        if (value[result.length] == value[result.length-1])
            break;
    }

//    for (int i = 0; i < N_ITER; ++i) {
//        std::cerr << i << '\t' << value[i] << '\t' << (value[i] - target) << '\n';
//    }

    double mindiff = std::numeric_limits<double>::max();
    int resultlength = -1;
    result.length = std::min(N_ITER, result.length);
    for (int l = 0; l <= result.length; ++l) {
        if (std::abs(value[l] - target) < mindiff) {
            mindiff = std::abs(value[l] - target);
            resultlength = l;
        }
    }

    result.length = resultlength;
    double val = value[resultlength];
    assert(std::abs(val - target) == mindiff);
    if (val != target) { // second-order optimization
        for (int i = 1; i < result.length; ++i) {
            // consider pair (i-1, i)
            if (result.fn[i-1] == result.fn[i]) continue; // look for (sin tan) or (tan sin)
            if (val < target && result.fn[i-1] == 0) { // we need to increase val : sin tan -> tan sin
                result.fn[i-1] = 1;
                result.fn[i] = 0;
                double newvalue = result.eval();
//                if (!(newvalue >= val)) std::cerr << "Floating point sin-tan error 1\n";
                if (std::abs(newvalue - target) < std::abs(val - target)) {
//                    std::cerr << "diff improved from " << std::abs(val - target) << " to " << std::abs(newvalue - target) << '\n';
                    val = newvalue;
                } else {
                    result.fn[i-1] = 0;
                    result.fn[i] = 1; // restore
                    #ifdef DEBUG
                    result.eval();
                    assert(val == result.val);
                    #endif // DEBUG
                }
            } else if (val > target && result.fn[i-1] == 1) {
                result.fn[i-1] = 0;
                result.fn[i] = 1;
                double newvalue = result.eval();
//                if (!(newvalue <= val)) std::cerr << "Floating point sin-tan error 2\n";
                if (std::abs(newvalue - target) < std::abs(val - target)) {
//                    std::cerr << "diff improved from " << std::abs(val - target) << " to " << std::abs(newvalue - target) << '\n';
                    val = newvalue;
                } else {
                    result.fn[i-1] = 1;
                    result.fn[i] = 0; // restore
                    #ifdef DEBUG
                    result.eval();
                    assert(val == result.val);
                    #endif // DEBUG
                }
            }
        }
    }
    double newdiff = std::abs(val - target);
    if (newdiff < mindiff) {
        mindiff = std::abs(val - target);
        std::cerr << "ok\n";
    } else if (newdiff > mindiff) {
        std::cerr << "Program error : error value = " << (newdiff - mindiff) << " (should be <= 0 if correct) \n";
        std::cerr << "mindiff = " << mindiff << ", newdiff = " << newdiff << '\n';
    }
    result.eval(); // set result.result
    assert(val == result.val);

    return result;
}

expr nearest(const expr& in, double target) {
    stexpr tmp = nearest(in.val, target);
    expr result;
    for (int i = 0; i < tmp.length; ++i)
        result.expr.append(tmp.fn[i] ? "tan " : "sin ");

    result.expr = "(" + result.expr + in.expr + ")";
    result.val = tmp.val;
    return result;
}

int main() {
    double totalscore = 0;

    assert (std::numeric_limits<double>::is_iec559);
    std::cerr << std::setprecision(23);

//    double initial = 0.61575952241185627;
//    target = 0.6157595200093855;
//    stexpr a = nearest(initial, target);
//    std::cerr << a.val << ' ' << a.length << '\n';
//    return 0;

    while (std::cin >> digits[0]) {
        for (unsigned i = 1; i < digits.size(); ++i) std::cin >> digits[i];
        std::cin >> target;

/*        std::string e;
//        int sum = 0;
//        for (int i : digits) {
//            sum += i;
//            e.append(to_string(i)).push_back('+');
//        }
//        e.pop_back(); // remove the last '+'
//        e = "cos cos (" + e + ")";
//        double val = std::cos(std::cos((double)sum));
//
//        stexpr result = nearest(val, target); // cos(cos(x)) is in approx 0.5 - 1,
//        // so we can expect that sin(x) and tan(x) behaves reasonably nice
//        std::string fns;
//        for (int i = 0; i < result.length; ++i) fns.append(result.fn[i] ? "tan" : "sin").push_back(' ');
//
//        std::cout << (fns + e) << '\n';
//        continue;*/

        std::array<expr, NSOL> sols;
        expr a, b, c, d; // temporary for solutions

        /* ----------------------------------------
           solution 1 : nearest cos cos sum(digits) */

        a.clear();
        for (int i : digits) {
            a.val += i; // no floating-point error here
            a.expr.append(to_string(i)).push_back('+');
        }
        a.expr.pop_back(); // remove the last '+'
        a.expr = "(" + a.expr + ")";
        a.wrap1();

        sols[0] = nearest(a, target);


        /* -----------------------------------------
              solution 2 : a * tan(b) + c (also important) */

        // find b first, then a, then finally c
        a.clear(); b.clear(); c.clear(); // e = a, b = e1, c = e2

        a.expr = to_string(digits[0]);
        a.val = digits[0];
        a.wrap1();

        b.expr = "(" + to_string(digits[1]) + "+" + to_string(digits[2]) + ")";
        b.val = digits[1] + digits[2];
        b.wrap1();

        c.expr = to_string(digits[3]);
        c.val = digits[3];
        c.wrap1();

        d.expr = to_string(digits[4]);
        d.val = digits[4];
        d.wrap1();

        b = nearest(b, std::atan(target));

        double targetA = target / std::tan(b.val);
        int cnt = 0;
        while (targetA < 1 && targetA > 0.9) {
            ++cnt;
            targetA = targetA * targetA;
        }
        a = nearest(a, targetA);
        while (cnt --> 0) {
            a.val = std::sqrt(a.val);
            a.expr = "sqrt " + a.expr;
        }
        a.expr = "(" + a.expr + ")"; // handle number of the form 0.9999999999

        /// partition of any number to easy-to-calculate sum of 2 numbers
        {{{{{{{{{{{{{{{{{{{{{{{{{{{{}}}}}}}}}}}}}}}}}}}}}}}}}}}}

        double targetC, targetD; // near 1, not in [0.9, 1), >= 0.1
        // that is, [0.1, 0.9), [1, inf)

        double target1 = target - (a.val * std::tan(b.val));

        double ac = std::abs(target1), sc = sgn(target1);
        if (ac < .1) targetC = 1 + ac, targetD = -1;
        else if (ac < 1) targetC = 1 + ac/2, targetD = ac/2 - 1;
        else if (ac < 1.8 || ac > 2) targetC = targetD = ac/2;
        else targetC = .8, targetD = ac - .8;

        targetC *= sc; targetD *= sc;

        c = nearest(c, std::abs(targetC)); if (targetC < 0) c.val = -c.val, c.expr = "(-" + c.expr + ")";
        d = nearest(d, std::abs(targetD)); if (targetD < 0) d.val = -d.val, d.expr = "(-" + d.expr + ")";

        sols[1].expr = a.expr + "*tan " + b.expr + "+" + c.expr + "+" + d.expr;
        sols[1].val = a.val * std::tan(b.val) + c.val + d.val;

        std::cerr
        << "\n---Method 2---"
        << "\na = " << a.val
        << "\ntarget a = " << targetA
        << "\nb = " << b.val
        << "\ntan b = " << std::tan(b.val)
        << "\nc = " << c.val
        << "\ntarget c = " << targetC
        << "\nd = " << d.val
        << "\ntarget d = " << targetD
        << "\n";

        /* -----------------------------------------
              solution 3 : (b + c) */

        target1 = target / 2;
        b.clear(); c.clear();

        for (int i = 0; i < N_DIGIT; ++i) {
            expr &ex = (i < 2 ? b : c);
            ex.val += digits[i];
            ex.expr.append(to_string(digits[i])).push_back('+');
        }
        b.expr.pop_back();
        b.expr = "(" + b.expr + ")";
        b.wrap1();

        c.expr.pop_back();
        c.expr = "(" + c.expr + ")";
        c.wrap1();

        b = nearest(b, target1);
        c = nearest(c, target - target1); // approx. target / 2

        sols[2].expr = "(" + b.expr + "+" + c.expr + ")";
        sols[2].val = b.val + c.val;

        /* -----------------------------------------
              solution 4 : a (*|/) (b - c)  (important) */

        a.clear(); b.clear(); c.clear(); // a = a, b = e1, c = e2

        a.expr = to_string(digits[0]);
        a.val = digits[0];
        a.wrap1();

        b.expr = "(" + to_string(digits[1]) + "+" + to_string(digits[2]) + ")";
        b.val = digits[1] + digits[2];
        b.wrap1();

        c.expr = "(" + to_string(digits[3]) + "+" + to_string(digits[4]) + ")";
        c.val = digits[3] + digits[4];
        c.wrap1();


        // (b-c) should be minimized
        bool multiply = target < a.val;
        double factor = multiply ? target / a.val : a.val / target;

        target1 = 1 + 2 * factor; // 1 + 2 * factor and 1 + factor

        std::cerr << "* Method 4 :\n";
        std::cerr << "b initial = " << b.val << ", target = " << target1 << ", ";
        b = nearest(b, target1);
        std::cerr << " get " << b.val << '\n';

        std::cerr << "c initial = " << c.val << ", target = " << b.val - factor << ", ";
        c = nearest(c, b.val - factor); // factor ~= e1.val - e2.val
        std::cerr << " get " << c.val << '\n';

        sols[3].expr = "(" + a.expr + (multiply ? "*(" : "/(") +
        ( b.expr + "-" + c.expr )
        + "))";
        factor = b.val - c.val;
        sols[3].val = multiply ? a.val * factor : a.val / factor;

        std::cerr << "a.val = " << a.val << '\n';

        /* ----------------------------------
                    Final result */

        int minindex = 0;
        assert(NSOL != 0);
        for (int i = 0; i < NSOL; ++i) {
            if (std::abs(target - sols[i].val) < std::abs(target - sols[minindex].val)) minindex = i;
            std::cerr << "Sol " << i << ", diff = " << std::abs(target - sols[i].val) << "\n";
        }
        std::cerr << "Choose " << minindex << "; target = " << target << '\n';
        totalscore += std::abs(target - sols[minindex].val);

        std::cout << sols[minindex].expr << '\n';
    }

    // #undef cerr // in case no-debug
    std::cerr << "total score = " << totalscore << '\n';
}

Entrada de entrada estándar, salida a salida estándar.

usuario202729
fuente
Sí, creo que <1 MB. Tenga en cuenta que si el programa viola algo que puede disminuir N_ITER(actualmente es 1000)
user202729
@geokavel Ahora es cuestionable si 1 / sin_100000000 (2)está permitido, o sin_1.374059274 (1).
user202729
1 / sin_100000000 (2)está permitido si tiene los dígitos 1 y 2 a su disposición. No tengo idea de cómo sin_1.374059274funcionaría. ¿Qué significa repetir pecado un número no entero de veces?
geokavel
@geokavel Pero la fórmula anterior tarda una eternidad en evaluar, por lo que no es difícil calcular la puntuación. El último se puede definir en.wikipedia.org/wiki/… | ¿Cómo es el programa en casos de prueba oficiales?
user202729
Veo lo que quiere decir con una iteración parcial, pero creo que es demasiado difícil para mí implementarlo. Su programa se ejecuta a tiempo, solo unos 25 segundos.
geokavel
2

Python 2 , radianes, puntaje 0.0032 en la prueba oficial

Este es el segundo borrador de solución que da un puntaje promedio de 0.0032 puntos. Como usa una composición de muchos sin, usé la siguiente notación compacta para la fórmula de salida:

  • sin_1 x=sin(x)
  • sin_2 x=sin(sin(x))
  • ...
  • sin_7 x=sin(sin(sin(sin(sin(sin(sin(x)))))))
  • ...
import math
import bisect
s1=[[float(t) for t in e.split()] for e in s0.split('\n')]
maxi=int(1e7)
A=[]
B=[]
C=[]
D=[]
a=1
for i in range(maxi):
	A.append(a)
	C.append(1/a)
	b=math.sin(a)
	c=a-b
	B.append(1/c)
	D.append(c)
	a=b
B.sort() 
C.sort() 
A.sort() 
D.sort() 
d15={0:'sqrt_100 tan_4 cos_2 sin 0',1:'sqrt_100 tan_4 cos_2 sin 1',2:'sqrt_100 tan_2 cos_2 sin 2',3:'sqrt_100 tan_4 cos_2 sin 3',4:'sqrt_100 tan_4 cos_2 sin 4',5:'sqrt_100 tan_4 cos_2 sin 5',6:'sqrt_100 tan_4 cos_2 sin 6',7:'sqrt_100 tan_2 cos_2 sin 7',8:'sqrt_100 tan_2 cos_2 sin 8',9:'sqrt_100 tan_4 cos_2 sin 9'}
def d16(d):return '('+d15[d]+')'

def S0(l):
	cpt=0
	d=l[:-1]
	r=l[-1]
	a1,a2,a3,a4,a5=[int(t) for t in d]
	i1=bisect.bisect(B, r)-1
	w1=abs(r-B[i1])
	i2=bisect.bisect(C, w1)-1
	w2=abs(w1-C[i2]) 
	s='('+d16(a1)+'/(sin_'+str(i1)+' '+d16(a2)+'-'+'sin_'+str(i1+1)+' '+d16(a3)+')'+'+'+d16(a4)+'/sin_'+str(i2)+' '+d16(a5)+')'
	return (w2,s)

def S1(l):
	cpt=0
	d=l[:-1]
	r=l[-1]
	a1,a2,a3,a4,a5=[int(t) for t in d]
	i1=bisect.bisect(C, r)-1
	w1=abs(r-C[i1])
	i2=bisect.bisect(A, w1)-1
	w2=abs(w1-A[i2]) 
	s='('+d16(a1)+'/sin_'+str(i1)+' '+d16(a2)+'+sin_'+str(maxi-i2-1)+' ('+d16(a3)+'*'+d16(a4)+'*'+d16(a5)+')'
	return (w2,s)

def S2(l):
	cpt=0
	d=l[:-1]
	r=l[-1]
	a1,a2,a3,a4,a5=[int(t) for t in d]
	i1=bisect.bisect(A, r)-1
	w1=abs(r-A[i1])
	i2=bisect.bisect(D, w1)-1
	w2=abs(w1-D[i2]) 
	s='('+'(sin_'+str(maxi-i2-1)+' '+d16(a1)+'-'+'sin_'+str(maxi-i2)+' '+d16(a2)+')'+'+sin_'+str(maxi-i1-1)+' ('+d16(a3)+'*'+d16(a4)+'*'+d16(a5)+'))'
	return (w2,s)

def S3(l):
	cpt=0
	d=l[:-1]
	r=l[-1]
	a1,a2,a3,a4,a5=[int(t) for t in d]
	i1=bisect.bisect(A, r)-1
	w2=abs(r-A[i1])
	s='('+'sin_'+str(maxi-i1-1)+' ('+d16(a1)+'*'+d16(a2)+'*'+d16(a3)+'*'+d16(a4)+'*'+d16(a5)+'))'
	return (w2,s)

def S4(l):
	cpt=0
	d=l[:-1]
	r=l[-1]
	a1,a2,a3,a4,a5=[int(t) for t in d]
	i1=bisect.bisect(B, r)-1
	w2=abs(r-B[i1])
	s='('+d16(a1)+'/(sin_'+str(i1)+' '+d16(a2)+'-'+'sin_'+str(i1+1)+' '+d16(a3)+'*'+d16(a4)+'*'+d16(a5)+')'+')'
	return (w2,s)

def S5(l):
	cpt=0
	d=l[:-1]
	r=l[-1]
	a1,a2,a3,a4,a5=[int(t) for t in d]
	i1=bisect.bisect(C, r)-1
	w2=abs(r-C[i1])
	s='('+d16(a1)+'/sin_'+str(i1)+' '+d16(a2)+'*'+d16(a3)+'*'+d16(a4)+'*'+d16(a5)+')'
	return (w2,s)

def S6(l):
	cpt=0
	d=l[:-1]
	r=l[-1]
	a1,a2,a3,a4,a5=[int(t) for t in d]
	i1=bisect.bisect(D, r)-1
	w2=abs(r-D[i1])
	s='(sin_'+str(maxi-i1-1)+' '+d16(a1)+'-'+'sin_'+str(maxi-i1)+' '+d16(a2)+'*'+d16(a3)+'*'+d16(a4)+'*'+d16(a5)+')'
	return (w2,s)

def all4(s1):
	s=0
	for l in s1:
		f=min(S0(l),S1(l),S2(l),S3(l),S4(l),S5(l),S6(l))
		print f[1]
		s+=f[0]
	s/=len(s1)
	print 'average unofficial score:',s
all4(s1)

Pruébalo en línea!

mdahmoune
fuente
1
Su programa obtiene un moy de 49.70 en las pruebas oficiales. Por alguna razón que lo hace muy mal en un caso de prueba en el apartado 3 con las siguientes cifras: 6 7 8 0 1.
geokavel
Las salidas +(tan_4 cos_2 sin 6)/(sin_0((-(tan_4 cos_2 sin 7)-(tan_4 cos_2 sin 8)+(tan_4 cos_2 sin 0)+(tan_4 cos_2 sin 1))))de su programa para ese caso de prueba, que es igual a 0.145.
geokavel
Lo siento, escribí mal el puntaje oficial de tu examen la primera vez. Realmente lo haces un poco peor que el promedio en las pruebas oficiales.
geokavel