การแสดงออกทางคณิตศาสตร์!


15

คุณได้รับหมายเลข 6: 5 หลัก [0-9] และหมายเลขเป้าหมาย เป้าหมายของคุณคือการกระจายโอเปอเรเตอร์ระหว่างตัวเลขเพื่อให้ใกล้เคียงกับเป้าหมาย คุณต้องใช้ตัวเลขแต่ละตัวเพียงครั้งเดียวและสามารถใช้ตัวดำเนินการต่อไปนี้ได้ หลายครั้งตามที่คุณต้องการ: + - * / () ^ sqrt sin cos tan. ตัวอย่างเช่นถ้าฉันให้ฉันสามารถส่งออก8 2 4 7 2 65 82-(2*7)-4สิ่งนี้ประเมินเป็น 64 จึงให้คะแนนกับฉัน 1 เนื่องจากฉันอยู่ห่างจากเป้าหมาย 1 ข้อ หมายเหตุ:คุณไม่สามารถใส่จุดทศนิยมระหว่างตัวเลขได้

ฉันกำลังใช้รหัสจากคำตอบ StackOverflowนี้เพื่อประเมินนิพจน์ทางคณิตศาสตร์ ที่ด้านล่างของคำถามนี้มีโปรแกรมที่คุณสามารถใช้ทดสอบได้

ฟังก์ชั่นผูกมัด (อัพเดต!)

@mdahmoune ได้เปิดเผยระดับใหม่ของความซับซ้อนในการท้าทายนี้ เช่นนี้ฉันกำลังเพิ่มคุณสมบัติใหม่: การผูกมัดฟังก์ชั่นยูนารี สิ่งนี้ใช้ได้กับบาป, cos, สีแทนและ sqrt ตอนนี้แทนการเขียนคุณสามารถเขียนsin(sin(sin(sin(10)))) sin_4(10)ลองใช้ในผู้ประเมิน!

อินพุต

กรณีทดสอบ 200 บรรทัดที่คั่นด้วยตัวเลข 5 หลักและหมายเลขเป้าหมายที่คั่นด้วยช่องว่าง คุณสามารถใช้โปรแกรมที่ด้านล่างของคำถามเพื่อสร้างกรณีทดสอบตัวอย่าง แต่ฉันจะมีกรณีทดสอบของตัวเองสำหรับการให้คะแนนอย่างเป็นทางการ กรณีทดสอบแบ่งออกเป็น 5 ส่วนจาก 40 การทดสอบพร้อมช่วงต่อไปนี้สำหรับหมายเลขเป้าหมาย:

  • ส่วนที่ 1: [0,1] (ถึง 5 จุดทศนิยม)
  • ส่วนที่ 2: [0,10] (ถึงทศนิยม 4 ตำแหน่ง)
  • ส่วนที่ 3: [0,1000] (ถึง 3 จุดทศนิยม)
  • ส่วนที่ 4: [0,10 6 ] (ถึง 1 จุดทศนิยม)
  • ส่วนที่ 5: [0,10 9 ] (ถึง 0 จุดทศนิยม)

เอาท์พุต

นิพจน์ทางคณิตศาสตร์แยกกัน 200 บรรทัด ตัวอย่างเช่นถ้ากรณีทดสอบคือ5 6 7 8 9 25.807ผลลัพธ์ที่เป็นไปได้78-59+6

เกณฑ์การให้คะแนน

เป้าหมายในแต่ละรอบคือการเข้าใกล้จำนวนเป้าหมายมากกว่ารายการแข่งขันอื่น ๆ ฉันจะใช้Mario Kart 8 การให้คะแนนซึ่งเป็น: หากมีหลายคำตอบที่ได้คะแนนเท่ากันคะแนนจะถูกแบ่งให้เท่ากันปัดเศษเป็น int ที่ใกล้ที่สุด ตัวอย่างเช่นหากโปรแกรมในสถานที่ที่ 5-8 ถูกผูกไว้พวกเขาแต่ละคนจะได้รับ (8 + 7 + 6 + 5) / 4 = 6.5 => 7คะแนนรอบนั้น เมื่อสิ้นสุดรอบ 200 รายการที่ได้คะแนนมากที่สุดจะเป็นผู้ชนะ หากทั้งสองโปรแกรมมีคะแนนเท่ากันในตอนท้ายไทเบรกเกอร์คือโปรแกรมที่ทำงานเสร็จเร็วขึ้น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

กฎระเบียบ

  1. คุณสามารถใช้ภาษาใดภาษาหนึ่งที่ติดตั้งล่วงหน้าใน Mac เช่น C, C ++, Java, PhP, Perl, Python (2 หรือ 3), Ruby และ Swift หากคุณมีภาษาที่คุณต้องการใช้กับคอมไพเลอร์ / ล่ามที่เป็นการดาวน์โหลดที่ค่อนข้างเล็กฉันสามารถเพิ่มมันได้ คุณยังสามารถใช้ภาษาที่มีล่ามออนไลน์ได้ แต่จะไม่ทำงานอย่างรวดเร็ว
  2. ระบุคำตอบของคุณหากคุณต้องการให้ฟังก์ชันคำนวณได้เป็นองศาหรือเรเดียน
  3. โปรแกรมของคุณจะต้องส่งออกโซลูชั่นไปยังกรณีทดสอบทั้งหมด 200 กรณี (ไปยังไฟล์หรือ STDOUT) 60 วินาทีบน Mac ของฉัน
  4. จะต้องมีการสุ่มแบบสุ่ม
  5. เอาต์พุตทั้งหมดของคุณสำหรับกรณีทดสอบทั้งหมดต้องไม่เกิน1 MBล้านบาท
  6. หากคุณได้ปรับปรุงวิธีแก้ปัญหาของคุณและต้องการให้ทำคะแนนใหม่ให้เพิ่มคะแนนซ้ำที่ด้านบนสุดของคำตอบด้วยตัวหนา

โปรแกรม

(เปลี่ยนอาร์กิวเมนต์ "deg" เป็น "rad" หากคุณต้องการเรเดียน)

  1. ทดสอบการประเมินผล
  2. ให้คะแนนโปรแกรมของคุณสำหรับกรณีทดสอบ
  3. สร้างกรณีทดสอบ:

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>

ลีดเดอร์บอร์ด

  1. user202729 ( C ++ ): 2856, 152 ชนะ
  2. mdahmoune ( Python 2 ) [v2]: 2544, 48 ชนะ

คะแนนส่วน (# ของผู้ชนะ):

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

เกี่ยวข้อง: สร้างสมการที่ถูกต้องโดยใช้หมายเลขที่ผู้ใช้ระบุ


มีเหตุผลใดบ้างที่ฟังก์ชันตรีโกณมิติต้องใช้องศา? อาจมีการเพิ่มตัวเลือกสำหรับคำตอบเพื่อระบุเรเดียนหรือองศา
notjagan

ชุดของตัวเลขประกอบด้วยตัวเลขที่ไม่ใช่ศูนย์หรือไม่
mdahmoune

@mdahmoune กรณีทดสอบถูกสร้างขึ้นแบบสุ่มดังนั้นตัวเลขอาจเป็น 0 ทั้งหมดคุณแค่ต้องทำให้ดีที่สุดในสถานการณ์นั้น ในโหมดการศึกษาระดับปริญญาผมก็สามารถที่จะได้รับทั้งหมดทางขึ้นไปยัง 3283.14 cos(0)/sin(0^0)/sin(0^0)ด้วย
geokavel

Thanx สำหรับคำตอบที่สมบูรณ์แบบของคุณ :)
mdahmoune

มันเป็นวิธีการให้คะแนนแบบเดียวกันหรือไม่สำหรับ 5 ส่วนที่ต่างกัน? Abs (target_value-generated_expression_value)? I
mdahmoune

คำตอบ:


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';
}

อินพุตจากอินพุตมาตรฐานเอาต์พุตไปยังเอาต์พุตมาตรฐาน


ใช่ฉันคิดว่า <1MB โปรดทราบว่าหากโปรแกรมละเมิดสิ่งที่คุณสามารถลดได้N_ITER(ปัจจุบันคือ 1,000)
user202729

@geokavel ตอนนี้ก็เป็นที่น่าสงสัยถ้าได้รับอนุญาตหรือ1 / sin_100000000 (2) sin_1.374059274 (1)
user202729

1 / sin_100000000 (2)ได้รับอนุญาตถ้าคุณมีตัวเลข 1 และ 2 ในการกำจัดของคุณ ฉันไม่รู้ว่าsin_1.374059274จะทำงานอย่างไร การทำซ้ำจำนวนครั้งที่ไม่ใช่จำนวนเต็มหมายความว่าอะไร
geokavel

@geokavel แต่สูตรเก่าใช้การประเมินตลอดไปดังนั้นจึงไม่ยากที่จะคำนวณคะแนน สามารถกำหนดภายหลังได้en.wikipedia.org/wiki/… | โปรแกรมในกรณีทดสอบอย่างเป็นทางการเป็นอย่างไร
user202729

ฉันเห็นสิ่งที่คุณหมายถึงโดยการทำซ้ำบางส่วน แต่ฉันคิดว่ามันยากเกินไปสำหรับฉันที่จะใช้มัน โปรแกรมของคุณทำงานในช่วงเวลาที่เหมาะสม - เพียงประมาณ 25 วินาที
geokavel

2

Python 2เรเดียนคะแนน 0.0032 จากการทดสอบอย่างเป็นทางการ

นี่คือโซลูชันร่างที่สองให้คะแนนเฉลี่ย 0.0032 คะแนน เนื่องจากมันใช้องค์ประกอบจำนวนมากของsinฉันใช้สัญกรณ์กะทัดรัดต่อไปนี้สำหรับสูตรผลลัพธ์

  • 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)

ลองออนไลน์!


1
โปรแกรมของคุณได้รับ moy 49.70 จากการทดสอบอย่างเป็นทางการ ด้วยเหตุผลบางอย่างที่มันไม่ดีจริงๆในกรณีทดสอบในส่วนที่ 3 6 7 8 0 1ด้วยตัวเลขต่อไปนี้:
geokavel

โปรแกรมของคุณแสดงผล+(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))))สำหรับกรณีทดสอบนั้นซึ่งเท่ากับ 0.145
geokavel

ขออภัยฉันเขียนคะแนนการทดสอบอย่างเป็นทางการของคุณผิดครั้งแรก คุณทำแย่กว่าค่าเฉลี่ยเล็กน้อยเล็กน้อยจากการทดสอบอย่างเป็นทางการ
geokavel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.