集合理论算术
前提
已经存在涉及不使用乘法运算符的乘法(这里和此处)的几个挑战,并且这个挑战是相同的(最类似于第二个链接)。
和
例如,
等等。
挑战
我们的目标是使用集合运算(请参见下文),以对自然数进行加法和乘法。为此,所有条目将使用其解释器在下面的相同“设置语言”。这将提供一致性并简化评分。
该解释器允许您将自然数作为集合进行操作。您的任务是编写两个程序主体(请参见下文),其中一个加上自然数,另一个自然将它们相乘。
集合的初步说明
集合遵循通常的数学结构。以下是一些要点:
- 集不排序。
 - 没有集合包含自身
 - 元素是否在集合中,这是布尔值。因此,集合元素不能具有多重性(即元素不能多次出现在集合中。)
 
口译员和细节
用于此挑战的“程序”以“设置语言”编写,并且由两部分组成:标题和正文。
标头
标头非常简单。它告诉解释器您正在解决什么程序。标题是程序的开始行。它以+or *字符开头,后跟两个以空格分隔的整数。例如:
+ 3 5
要么
* 19 2
是有效的标头。第一个表明您正在尝试解决3+5,这意味着您的答案应该是8。除了乘法之外,第二个相似。
身体
正文是您对口译员的实际指示所在。这才是真正构成您的“加法”或“乘法”程序的要素。您的答案将包含两个程序主体,每个任务主体一个。然后,您将更改标题以实际执行测试用例。
语法及指示
指令由一个命令后跟零个或多个参数组成。为了以下演示的目的,任何字母字符都是变量的名称。回想一下,所有变量都是集合。label是标签的名称(标签是单词,后跟分号(即main_loop:),int是整数。以下是有效的说明:
jump label无条件跳转到标签。标签是一个“单词”,后跟一个分号:例如,main_loop:是一个标签。je A label如果A为空则跳转到标签jne A label如果A为非空,则跳转到标签jic A B label如果A包含B则跳转到标签jidc A B label如果A不包含B则跳转到标签
print A打印A的真实值,其中{}是空集printi variable打印A的整数表示形式(如果存在),否则输出错误。
;分号表示该行的其余部分为注释,解释器将忽略该行
进一步的信息
在程序启动时,存在三个预先存在的变量。他们是set1,set2和ANSWER。set1接受第一个标头参数的值。set2取秒的值。ANSWER最初是空集。程序完成后,解释器检查ANSWER标题中定义的算术问题答案的整数表示。如果是的话,它会向stdout发出一条消息来表明这一点。
解释器还显示使用的操作数。每条指令都是一个操作。启动标签也需要执行一次操作(标签只能启动一次)。
您最多可以有20个变量(包括3个预定义变量)和20个标签。
口译员代码
关于此解释器的重要说明在此解释器中使用大量(> 30)时,事情非常缓慢。我将概述其原因。
- 集的结构使得通过增加一个自然数,可以有效地使集结构的大小增加一倍。第n个自然数内有2 ^ n个空集(这意味着如果您将n看成一棵树,则有n个空集。请注意,只有空集可以是叶子。)这意味着处理30个值很明显比处理20或10的成本更高(您正在查看2 ^ 10 vs 2 ^ 20 vs 2 ^ 30)。
 - 平等检查是递归的。由于据称场景是无序的,因此这似乎是解决此问题的自然方法。
 - 有两个内存泄漏,我不知道如何解决。对不起,我对C / C ++不好。由于我们仅处理小数,并且已分配的内存在程序结束时释放,因此这实际上并不是一个大问题。(在任何人说任何东西之前,我都知道
std::vector;我正在将其作为学习练习。如果您知道如何解决它,请让我知道,我将进行编辑,否则,因为它有效,所以我将其保留照原样。) 
此外,注意包括到路径set.h中interpreter.cpp的文件。事不宜迟,源代码(C ++):
设定
using namespace std;
//MEMORY LEAK IN THE ADD_SELF METHOD
class set {
    private:
        long m_size;
        set* m_elements;
        bool m_initialized;
        long m_value;
    public:
        set() {
            m_size =0;
            m_initialized = false;
            m_value=0;
        }
        ~set() {
            if(m_initialized) {
                //delete[] m_elements;
            }
        }
        void init() {
            if(!m_initialized) {
                m_elements = new set[0];
                m_initialized = true;
            }
        }
        void uninit() {
            if(m_initialized) {
                //delete[] m_elements;
            }
        }
        long size() {
            return m_size;
        }
        set* elements() {
            return m_elements;
        }
        bool is_empty() {
            if(m_size ==0) {return true;}
            else {return false;}
        }
        bool is_eq(set otherset) {
            if( (*this).size() != otherset.size() ) {
                return false;
            }
            else if ( (*this).size()==0 && otherset.size()==0 ) { 
                return true;
            }
            else {
                for(int i=0;i<m_size;i++) {
                    bool matched = false;
                    for(int j=0;j<otherset.size();j++) {
                        matched = (*(m_elements+i)).is_eq( *(otherset.elements()+j) );
                        if( matched) {
                            break;
                        }
                    }
                    if(!matched) {
                        return false;
                    }
                }
                return true;
            } 
        }
        bool contains(set set1) {
            for(int i=0;i<m_size;i++) {
                if( (*(m_elements+i)).is_eq(set1) ) {
                    return true;
                }
            }
            return false;
        }
        void add(set element) {
            (*this).init();
            bool alreadythere = false;
            for(int i=0;i<m_size;i++) {
                if( (*(m_elements+i)).is_eq(element) ) { 
                    alreadythere=true;
                }
            }
            if(!alreadythere) {
                set *temp = new set[m_size+1];
                for(int i=0; i<m_size; i++) {
                    *(temp+i)= *(m_elements+i);
                }
                *(temp+m_size)=element;
                m_size++;
                delete[] m_elements;
                m_elements = new set[m_size];
                for(int i=0;i<m_size;i++) {
                    *(m_elements+i) = *(temp+i);
                }
                delete[] temp;
            }
        }
        void add_self() {
            set temp_set;
            for(int i=0;i<m_size;i++) {
                temp_set.add( *(m_elements+i) );
            }
            (*this).add(temp_set);
            temp_set.uninit();
        }
        void remove(set set1) {
            (*this).init();
            for(int i=0;i<m_size;i++) {
                if(  (*(m_elements+i)).is_eq(set1) ) {
                    set* temp = new set[m_size-1];
                    for(int j=0;j<m_size;j++) {
                        if(j<i) {
                            *(temp+j)=*(m_elements+j);
                        }
                        else if(j>i) {
                            *(temp+j-1)=*(m_elements+j);
                        }
                    }
                    delete[] m_elements;
                    m_size--;
                    m_elements = new set[m_size];
                    for(int j=0;j<m_size;j++) {
                        *(m_elements+j)= *(temp+j);
                    }
                    delete[] temp;
                    break;
                }
            }
        }
        void join(set set1) {
            for(int i=0;i<set1.size();i++) {
                (*this).add( *(set1.elements()+i) );
            }
        }
        void diff(set set1) {
            for(int i=0;i<set1.size();i++) {
                (*this).remove( *(set1.elements()+i) );
            }
        }
        void intersect(set set1) {
             for(int i=0;i<m_size;i++) {
                bool keep = false;
                 for(int j=0;j<set1.size();j++) {
                     if(  (*(m_elements+i)).is_eq( *(set1.elements()+j) ) ) {
                         keep = true;
                         break;
                     }
                 }
                 if(!keep) {
                    (*this).remove( *(m_elements+i) );
                 }
             }
         }
        void natural(long number) {
            ////////////////////////// 
            //MEMORY LEAK?
            //delete[] m_elements;
            /////////////////////////
            m_size = 0;
            m_elements = new set[m_size];
            for(long i=1;i<=number;i++) {
                (*this).add_self();
            }
            m_value = number;
        }
        void disp() {
            if( m_size==0) {cout<<"{}";}
            else {
                cout<<"{";
                for(int i=0; i<m_size; i++) {
                    (*(m_elements+i)).disp();
                    if(i<m_size-1) {cout<<", ";}
                    //else{cout<<" ";}
                }
                cout<<"}";
            }
        }
        long value() {
            return m_value;
        }
};
const set EMPTY_SET;
解释器
#include<fstream>
#include<iostream>
#include<string>
#include<assert.h>
#include<cmath>
#include "headers/set.h"
using namespace std;
string labels[20];
int jump_points[20];
int label_index=0;
const int max_var = 20;
set* set_ptrs[max_var];
string set_names[max_var];
long OPERATIONS = 0;
void assign_var(string name, set other_set) {
    static int index = 0;
    bool exists = false;
    int i = 0;
    while(i<index) {
        if(name==set_names[i]) {
            exists = true;
            break;
        }
        i++;
    }
    if(exists && index<max_var) {
        *(set_ptrs[i]) = other_set;
    }
    else if(!exists && index<max_var) {
        set_ptrs[index] = new set;
        *(set_ptrs[index]) = other_set;
        set_names[index] = name;
        index++;
    }
}
int getJumpPoint(string str) {
    for(int i=0;i<label_index;i++) {
        //cout<<labels[i]<<"\n";
        if(labels[i]==str) {
            //cout<<jump_points[i];
            return jump_points[i];
        }
    }
    cerr<<"Invalid Label Name: '"<<str<<"'\n";
    //assert(0);
    return -1;
}
long strToLong(string str) { 
    long j=str.size()-1;
    long value = 0;
    for(long i=0;i<str.size();i++) {
        long x = str[i]-48;
        assert(x>=0 && x<=9);  // Crash if there was a non digit character
        value+=x*floor( pow(10,j) );
        j--;
    }
    return value;
}
long getValue(string str) {
    for(int i=0;i<max_var;i++) {
        if(set_names[i]==str) {
            set set1;
            set1.natural( (*(set_ptrs[i])).size() );
            if( set1.is_eq( *(set_ptrs[i]) )   ) {
                return (*(set_ptrs[i])).size();
            }
            else {
                cerr<<"That is not a valid integer construction";
                return 0;
            }
        }
    }
    return strToLong(str);
}
int main(int argc, char** argv){
    if(argc<2){std::cerr<<"No input file given"; return 1;}
    ifstream inf(argv[1]);
    if(!inf){std::cerr<<"File open failed";return 1;}
    assign_var("ANSWER", EMPTY_SET);
    int answer;
    string str;
    inf>>str; 
    if(str=="*") { 
        inf>>str;
        long a = strToLong(str);
        inf>>str;
        long b = strToLong(str);
        answer = a*b;
        set set1; set set2;
        set1.natural(a); set2.natural(b);
        assign_var("set1", set1);
        assign_var("set2",set2);
        //cout<<answer;
    }
    else if(str=="+") {
        inf>>str;
        long a = strToLong(str);
        inf>>str;
        long b = strToLong(str);
        answer = a+b;
        set set1; set set2;
        set1.natural(a); set2.natural(b);
        assign_var("set1", set1);
        assign_var("set2",set2);
        //cout<<answer;
    }
    else{ 
         cerr<<"file must start with '+' or '*'"; 
        return 1;
    }
    // parse for labels
    while(inf) {
        if(inf) {   
            inf>>str;
            if(str[str.size()-1]==':') {
                str.erase(str.size()-1);
                labels[label_index] = str; 
                jump_points[label_index] = inf.tellg();
                //cout<<str<<": "<<jump_points[label_index]<<"\n";
                label_index++;
                OPERATIONS++;
            }
        }
    }
    inf.clear();
    inf.seekg(0,ios::beg);
    // parse for everything else
    while(inf) {
        if(inf) {
            inf>>str;
            if(str==";") {
                getline(inf, str,'\n');
            }
            // jump label
            if(str=="jump") {    
                inf>>str;
                inf.seekg( getJumpPoint(str),ios::beg);
                OPERATIONS++;
            }
            // je set label
            if(str=="je") {        
                inf>>str;
                for(int i=0;i<max_var;i++) {
                    if( set_names[i]==str) {
                        if( (*(set_ptrs[i])).is_eq(EMPTY_SET) ) {
                            inf>>str;
                            inf.seekg( getJumpPoint(str),ios::beg);
                            OPERATIONS++; 
                        }
                        break;
                    }
                }
            }
            // jne set label
            if(str=="jne") {
                inf>>str;
                for(int i=0;i<max_var;i++) {
                    if( set_names[i]==str) {
                        if(! (*(set_ptrs[i])).is_eq(EMPTY_SET) ) {
                            inf>>str;
                            inf.seekg( getJumpPoint(str),ios::beg);
                            OPERATIONS++; 
                        }
                        break;
                    }
                }
            }
            // jic set1 set2 label 
            // jump if set1 contains set2
            if(str=="jic") {
                inf>>str;
                string str2;
                inf>>str2;
                set set1;
                set set2;
                for(int i=0;i<max_var;i++) {
                    if( set_names[i]==str ) {
                        set1 = *(set_ptrs[i]);
                    }
                    if(set_names[i]==str2) {
                        set2 = *(set_ptrs[i]);
                    }
                }
                if( set1.contains(set2) ) {
                    inf>>str;
                    inf.seekg( getJumpPoint(str),ios::beg);
                    OPERATIONS++; 
                }
                else {inf>>str;}
            }
            // jidc set1 set2 label
            // jump if set1 doesn't contain set2
            if(str=="jidc") {
                inf>>str;
                string str2;
                inf>>str2;
                set set1;
                set set2;
                for(int i=0;i<max_var;i++) {
                    if( set_names[i]==str ) {
                        set1 = *(set_ptrs[i]);
                    }
                    if(set_names[i]==str2) {
                        set2 = *(set_ptrs[i]);
                    }
                }
                if( !set1.contains(set2) ) {
                    inf>>str;
                    inf.seekg( getJumpPoint(str),ios::beg);
                    OPERATIONS++; 
                }
                else {inf>>str;}
            }
            // assign variable set/int
            if(str=="assign") {
                inf>>str;
                string str2;
                inf>>str2;
                set set1;
                set1.natural( getValue(str2) );
                assign_var(str,set1);
                OPERATIONS++;
            }
            // union set1 set2 set3
            // set1 = set2 u set3
            if(str=="union") {
                inf>>str;
                int i=0;
                while(i<max_var) {
                    if( set_names[i] == str ) {
                        break;
                    }
                    i++;
                }
                set set1;
                set set2;
                string str1;
                inf>>str1;
                string str2;
                inf>>str2;
                for(int j=0;j<max_var;j++) {
                    if( str1 == set_names[j] ) {
                        set1= *(set_ptrs[j]); 
                    }
                    if( str2 == set_names[j] ) {
                        set2= *(set_ptrs[j]);
                    }
                }
                set1.join(set2);
                if(i==max_var) {
                    assign_var(str,set1);
                }
                else {
                    set_names[i]= str;
                    set_ptrs[i] = new set;
                    *(set_ptrs[i]) = set1;
                }
                OPERATIONS++;
            }
            // intersect set1 set2 set3
            // set1 = set2^set3
            if(str == "intersect") {
                inf>>str;
                int i=0;
                while(i<max_var) {
                    if( set_names[i] == str ) {
                        break;
                    }
                    i++;
                }
                set set1;
                set set2;
                string str1;
                inf>>str1;
                string str2;
                inf>>str2;
                for(int j=0;j<max_var;j++) {
                    if( str1 == set_names[j] ) {
                        set1= *(set_ptrs[j]); 
                    }
                    if( str2 == set_names[j] ) {
                        set2= *(set_ptrs[j]);
                    }
                }
                set1.intersect(set2);
                if(i==max_var) {
                    assign_var(str,set1);
                }
                else {
                    set_names[i]= str;
                    set_ptrs[i] = new set;
                    *(set_ptrs[i]) = set1;
                }
                OPERATIONS++;
            }
            // difference set1 set2 set3
            // set1 = set2\set3
            if(str == "difference") {
                inf>>str;
                int i=0;
                while(i<max_var) {
                    if( set_names[i] == str ) {
                        break;
                    }
                    i++;
                }
                set set1;
                set set2;
                string str1;
                inf>>str1;
                string str2;
                inf>>str2;
                for(int j=0;j<max_var;j++) {
                    if( str1 == set_names[j] ) {
                        set1= *(set_ptrs[j]); 
                    }
                    if( str2 == set_names[j] ) {
                        set2= *(set_ptrs[j]);
                    }
                }
                set1.diff(set2);
                if(i==max_var) {
                    assign_var(str,set1);
                }
                else {
                    set_names[i]= str;
                    set_ptrs[i] = new set;
                    *(set_ptrs[i]) = set1;
                }
                OPERATIONS++;
            }
            // add set1 set2
            // put set2 in set 1
            if(str=="add") {
                inf>>str;
                int i = 0; int j =0;
                while(i<max_var) {
                    if(set_names[i]==str) {
                        break;
                    }
                    i++;
                }
                inf>>str;
                while(j<max_var) {
                    if(set_names[j]==str) {
                    break;
                    }   
                    j++;             
                }
                set set2 = *(set_ptrs[j]);
                if( ! (*(set_ptrs[i])).is_eq(set2) ){
                    (*(set_ptrs[i])).add(set2);
                }
                else {
                    (*(set_ptrs[i])).add_self();
                }
                OPERATIONS++;
            }
            // remove set1 set2
            // remove set2 from set1
            if(str=="remove") {
                inf>>str;
                int i = 0; int j =0;
                while(i<max_var) {
                    if(set_names[i]==str) {
                        break;
                    }
                    i++;
                }
                inf>>str;
                while(j<max_var) {
                    if(set_names[j]==str) {
                    break;
                    }   
                    j++;             
                }
                set set2 = *(set_ptrs[j]);
                (*(set_ptrs[i])).remove(set2);
                OPERATIONS++;
            }
            // print set
            // prints true representation of set
            if(str=="print") {
                inf>>str;
                for(int i=0;i<max_var;i++) {
                    if(set_names[i]==str) {
                        (*(set_ptrs[i])).disp();
                    }
                }
                cout<<"\n";
            }
            // printi set
            // prints integer representation of set, if exists.
            if(str=="printi") {
                inf>>str;
                cout<<getValue(str);
                cout<<"\n";
            }
        }
    }
    cout<<"You used "<<OPERATIONS<<" operations\n";
    set testset;
    testset.natural(answer);
    switch( testset.is_eq( *(set_ptrs[0]) ) ) {
        case 1:
            cout<<"Your answer is correct, the set 'ANSWER' is equivalent "<<answer<<".\n";
            break;
        case 0:
            cout<<"Your answer is incorrect\n";
    }
   // cout<<"\n";
    return 0;
}
获奖条件
您是两个编写两个程序BODIES的人,其中一个将标题中的数字相乘,另一个将标题中的数字相加。
这是最快的代码挑战。最快的速度取决于每个程序用于解决两个测试用例的操作数。测试用例是以下标题行:
补充:
+ 15 12
和
+ 12 15
和乘法
* 4 5
和
* 5 4
每种情况的分数是所用操作的数量(在程序完成时,口译员将指出该数字)。总分数是每个测试用例的分数之和。
有关有效条目的示例,请参见我的示例条目。
获奖作品满足以下条件:
- 包含两个程序主体,一个主体相乘,另一个主体相加
 - 总得分最低(测试用例的得分总和)
 - 如果有足够的时间和内存,则适用于解释器可以处理的任何整数(〜2 ^ 31)
 - 运行时不显示任何错误
 - 不使用调试命令
 - 不利用解释器中的缺陷。这意味着您的实际程序应作为伪代码以及“设置语言”中的可解释程序有效。
 - 不利用标准漏洞(这意味着没有硬编码测试用例。)
 
请参阅我的示例以获取该语言的参考实现和示例用法。
$$...$$适用于Meta,但不适用于Main。我使用CodeCogs生成图像。
                










